react-use-query-params
Version:
Strongly typed, routing-library agnostic react hook to use and manipulate query params
156 lines • 21.6 kB
JavaScript
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlUXVlcnlQYXJhbXMuanMiLCJzb3VyY2VSb290IjoiLi9zcmMvIiwic291cmNlcyI6WyJ1c2VRdWVyeVBhcmFtcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsV0FBVyxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBQyxNQUFNLE9BQU8sQ0FBQztBQUUxRSxNQUFNLFNBQVMsR0FBRyxJQUFJLEdBQUcsRUFBYyxDQUFDO0FBRXhDLFNBQVMsWUFBWTtJQUNqQixTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUU7UUFDM0IsUUFBUSxFQUFFLENBQUM7SUFDZixDQUFDLENBQUMsQ0FBQztBQUNQLENBQUM7QUFFRCxDQUFDLFVBQVUsT0FBTztJQUNkLFNBQVMsU0FBUyxDQUFDLElBQVM7UUFDeEIsT0FBTyxVQUFVLEdBQUcsSUFBVztZQUMzQixNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNoRCxZQUFZLEVBQUUsQ0FBQztZQUVmLE9BQU8sYUFBYSxDQUFDO1FBQ3pCLENBQUMsQ0FBQztJQUNOLENBQUM7SUFFRCxPQUFPLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDakQsT0FBTyxDQUFDLFlBQVksR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBRXZELGdFQUFnRTtJQUNoRSxNQUFNLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxFQUFFLEdBQUcsRUFBRTtRQUNyQyxZQUFZLEVBQUUsQ0FBQztJQUNuQixDQUFDLENBQUMsQ0FBQztBQUNQLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztBQVFuQixNQUFNLFVBQVUsZ0JBQWdCLENBQzVCLE1BQTZCLEVBQzdCLFdBQXdDLEVBQ3hDLGVBQXdCLEtBQUs7SUFFN0IsTUFBTSxN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dXNlTWVtbywgdXNlUmVkdWNlciwgdXNlUmVmfSBmcm9tICdyZWFjdCc7XG5cbmNvbnN0IGxpc3RlbmVycyA9IG5ldyBTZXQ8KCkgPT4gdm9pZD4oKTtcblxuZnVuY3Rpb24gcnVuTGlzdGVuZXJzKCkge1xuICAgIGxpc3RlbmVycy5mb3JFYWNoKChsaXN0ZW5lcikgPT4ge1xuICAgICAgICBsaXN0ZW5lcigpO1xuICAgIH0pO1xufVxuXG4oZnVuY3Rpb24gKGhpc3RvcnkpIHtcbiAgICBmdW5jdGlvbiBpbnRlcmNlcHQoZnVuYzogYW55KSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoLi4uYXJnczogYW55W10pIHtcbiAgICAgICAgICAgIGNvbnN0IHJldHVybmVkVmFsdWUgPSBmdW5jLmFwcGx5KGhpc3RvcnksIGFyZ3MpO1xuICAgICAgICAgICAgcnVuTGlzdGVuZXJzKCk7XG5cbiAgICAgICAgICAgIHJldHVybiByZXR1cm5lZFZhbHVlO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGhpc3RvcnkucHVzaFN0YXRlID0gaW50ZXJjZXB0KGhpc3RvcnkucHVzaFN0YXRlKTtcbiAgICBoaXN0b3J5LnJlcGxhY2VTdGF0ZSA9IGludGVyY2VwdChoaXN0b3J5LnJlcGxhY2VTdGF0ZSk7XG5cbiAgICAvLyB0byBoYW5kbGUgYnJvd3NlcidzIG5hdGl2ZSBiYWNrd2FyZCBhbmQgZm9yd2FyZCBmdW5jdGlvbmFsaXR5XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3BvcHN0YXRlJywgKCkgPT4ge1xuICAgICAgICBydW5MaXN0ZW5lcnMoKTtcbiAgICB9KTtcbn0pKHdpbmRvdy5oaXN0b3J5KTtcblxuZXhwb3J0IHR5cGUgVERlZmF1bHRQYXJhbXNPYmplY3QgPSBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuXG5leHBvcnQgdHlwZSBUQWxsUGFyYW1zPFBBUkFNUyBleHRlbmRzIFREZWZhdWx0UGFyYW1zT2JqZWN0PiA9IHtcbiAgICBba2V5IGluIGtleW9mIFBBUkFNU106IHN0cmluZ1tdO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5UXVlcnlQYXJhbXM8UEFSQU1TIGV4dGVuZHMgVERlZmF1bHRQYXJhbXNPYmplY3Q+KFxuICAgIHRhcmdldDogVVJMIHwgVVJMU2VhcmNoUGFyYW1zLFxuICAgIHF1ZXJ5UGFyYW1zOiBQYXJ0aWFsPFRBbGxQYXJhbXM8UEFSQU1TPj4sXG4gICAgcmVtb3ZlRXh0cmFzOiBib29sZWFuID0gZmFsc2UsXG4pIHtcbiAgICBjb25zdCBwYXJhbXMgPSB0YXJnZXQgaW5zdGFuY2VvZiBVUkwgPyB0YXJnZXQuc2VhcmNoUGFyYW1zIDogdGFyZ2V0O1xuXG4gICAgaWYgKHJlbW92ZUV4dHJhcykge1xuICAgICAgICBwYXJhbXMuZm9yRWFjaCgodmFsdWUsIGtleSkgPT4ge1xuICAgICAgICAgICAgaWYgKCEoa2V5IGluIHF1ZXJ5UGFyYW1zKSkge1xuICAgICAgICAgICAgICAgIHBhcmFtcy5kZWxldGUoa2V5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZXNdIG9mIE9iamVjdC5lbnRyaWVzKHF1ZXJ5UGFyYW1zKSkge1xuICAgICAgICBjb25zdCB1c2FibGVWYWx1ZXMgPSBBcnJheS5pc0FycmF5KHZhbHVlcykgPyB2YWx1ZXMgOiBbdmFsdWVzXTtcbiAgICAgICAgcGFyYW1zLmRlbGV0ZShrZXkpO1xuXG4gICAgICAgIGZvciAoY29uc3QgdmFsdWUgb2YgdXNhYmxlVmFsdWVzKSB7XG4gICAgICAgICAgICBwYXJhbXMuYXBwZW5kKGtleSwgdmFsdWUgPz8gJycpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRhcmdldDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVzZVF1ZXJ5UGFyYW1zPFxuICAgIFBBUkFNUyBleHRlbmRzIFREZWZhdWx0UGFyYW1zT2JqZWN0ID0gVERlZmF1bHRQYXJhbXNPYmplY3QsXG4+KCkge1xuICAgIGNvbnN0IGN1cnJlbnRMb2NhdGlvbiA9IHdpbmRvdy5sb2NhdGlvbi5ocmVmO1xuXG4gICAgY29uc3QgdXJsU2VhcmNoUGFyYW1zID0gdXNlTWVtbygoKSA9PiB7XG4gICAgICAgIHJldHVybiBuZXcgVVJMU2VhcmNoUGFyYW1zKHdpbmRvdy5sb2NhdGlvbi5zZWFyY2gpO1xuICAgIH0sIFtjdXJyZW50TG9jYXRpb25dKTtcblxuICAgIGNvbnN0IHdhdGNoaW5nID0gdXNlUmVmPHtcbiAgICAgICAgW2tleSBpbiBrZXlvZiBQQVJBTVNdPzogc3RyaW5nW107XG4gICAgfT4oe30pO1xuXG4gICAgY29uc3Qgd2F0Y2hpbmdMZW5ndGggPSB1c2VSZWY8bnVtYmVyIHwgYm9vbGVhbj4oZmFsc2UpO1xuICAgIGNvbnN0IHBhdXNlV2F0Y2ggPSB1c2VSZWY8Ym9vbGVhbj4oZmFsc2UpO1xuXG4gICAgLy8gc3RvcmVzIGJvdGggdGhlIGtleSBhbmQgdGhlIHZhbHVlcyBhcyBhbiBhcnJheVxuICAgIC8vIG9mIHRoZSBwYXJhbXMgdGhhdCBhcmUgYmVpbmcgd2F0Y2hlZFxuICAgIGNvbnN0IHdhdGNoID0gdXNlQ2FsbGJhY2soXG4gICAgICAgIChrZXk6IGtleW9mIFBBUkFNUykgPT4ge1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIGtleSBpbiB3YXRjaGluZy5jdXJyZW50IHx8XG4gICAgICAgICAgICAgICAgcGF1c2VXYXRjaC5jdXJyZW50IHx8XG4gICAgICAgICAgICAgICAgd2F0Y2hpbmdMZW5ndGguY3VycmVudFxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB3YXRjaGluZy5jdXJyZW50W2tleV0gPSB1cmxTZWFyY2hQYXJhbXMuZ2V0QWxsKFN0cmluZyhrZXkpKTtcbiAgICAgICAgfSxcbiAgICAgICAgW3VybFNlYXJjaFBhcmFtcywgd2F0Y2hpbmddLFxuICAgICk7XG5cbiAgICBjb25zdCBjbGVhcldhdGNoID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgICAgICB3YXRjaGluZy5jdXJyZW50ID0ge307XG4gICAgICAgIHdhdGNoaW5nTGVuZ3RoLmN1cnJlbnQgPSBmYWxzZTtcbiAgICB9LCBbd2F0Y2hpbmddKTtcblxuICAgIC8vIFJlYWN0J3Mgb2ZmaWNpYWxseSByZWNvbW1lbmRlZCB3YXkgb2YgZm9yY2luZyBhIHJlcmVuZGVyXG4gICAgY29uc3QgWywgaW5jcmVtZW50XSA9IHVzZVJlZHVjZXIoKHN0YXRlKSA9PiB7XG4gICAgICAgIHJldHVybiBzdGF0ZSArIDE7XG4gICAgfSwgMCk7XG5cbiAgICBjb25zdCByZXJlbmRlciA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICAgICAgaW5jcmVtZW50KCk7XG4gICAgfSwgW2luY3JlbWVudF0pO1xuXG4gICAgLy8gSGFuZGxlcyBsb2NhdGlvbiBjaGFuZ2VzIHZpYSBsaXN0ZW5lciBtZWNoYW5pc20gYWJvdmUuXG4gICAgY29uc3QgaGFuZGxlID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgICAgICBjb25zdCBjdXJyZW50UGFyYW1zID0gbmV3IFVSTFNlYXJjaFBhcmFtcyh3aW5kb3cubG9jYXRpb24uc2VhcmNoKTtcblxuICAgICAgICBsZXQgc2hvdWxkUmVyZW5kZXIgPSBmYWxzZTtcbiAgICAgICAgbGV0IGxlbmd0aCA9IDA7XG5cbiAgICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZXNdIG9mIE9iamVjdC5lbnRyaWVzKHdhdGNoaW5nLmN1cnJlbnQpKSB7XG4gICAgICAgICAgICBjb25zdCBjdXJyZW50VmFsdWVzID0gY3VycmVudFBhcmFtcy5nZXRBbGwoa2V5KTtcblxuICAgICAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZXMubGVuZ3RoICE9PSB2YWx1ZXM/Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHNob3VsZFJlcmVuZGVyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gdGhlIGZpcnN0IG1pc21hdGNoZWQgdmFsdWUgbWVhbnMgd2UgbmVlZCB0byByZXJlbmRlclxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjdXJyZW50VmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZXNbaV0gIT09IHZhbHVlc1tpXSkge1xuICAgICAgICAgICAgICAgICAgICBzaG91bGRSZXJlbmRlciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGVuZ3RoICs9IDE7XG4gICAgICAgIH1cblxuICAgICAgICBzaG91bGRSZXJlbmRlciA9XG4gICAgICAgICAgICBzaG91bGRSZXJlbmRlciB8fFxuICAgICAgICAgICAgKHdhdGNoaW5nTGVuZ3RoLmN1cnJlbnQgIT09IGZhbHNlICYmXG4gICAgICAgICAgICAgICAgd2F0Y2hpbmdMZW5ndGguY3VycmVudCAhPT0gbGVuZ3RoKTtcblxuICAgICAgICBpZiAoc2hvdWxkUmVyZW5kZXIpIHtcbiAgICAgICAgICAgIGNsZWFyV2F0Y2goKTtcbiAgICAgICAgICAgIHJlcmVuZGVyKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9LCBbd2F0Y2hpbmcsIGNsZWFyV2F0Y2gsIHJlcmVuZGVyXSk7XG5cbiAgICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICAvLyBsaXN0ZW5pbmcgb24gdGhlIGdsb2JhbCB3aW5kb3cgb2JqZWN0XG4gICAgICAgIC8vIHZpYSBpbnRlcmNlcHRpb25zIGFuZCBsaXN0ZW5lcnMuXG4gICAgICAgIGxpc3RlbmVycy5hZGQoaGFuZGxlKTtcblxuICAgICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICAgICAgbGlzdGVuZXJzLmRlbGV0ZShoYW5kbGUpO1xuICAgICAgICB9O1xuICAgIH0sIFtoYW5kbGVdKTtcblxuICAgIGNvbnN0IHBhcmFtcyA9IHVzZU1lbW8oKCkgPT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb3h5KHt9IGFzIFRBbGxQYXJhbXM8UEFSQU1TPiwge1xuICAgICAgICAgICAgZ2V0KHRhcmdldCwga2V5OiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gICAgICAgICAgICAgICAgd2F0Y2goa2V5KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdXJsU2VhcmNoUGFyYW1zLmdldEFsbChrZXkpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG93bktleXModGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgY29uc3Qga2V5cyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gICAgICAgICAgICAgICAgdXJsU2VhcmNoUGFyYW1zLmZvckVhY2goKHZhbHVlLCBrZXkpID0+IHtcbiAgICAgICAgICAgICAgICAgICAga2V5cy5hZGQoa2V5KTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGlmICghcGF1c2VXYXRjaC5jdXJyZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHdhdGNoaW5nTGVuZ3RoLmN1cnJlbnQgPSBrZXlzLnNpemU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIFsuLi5rZXlzXTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodGFyZ2V0LCBwcm9wKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtjb25maWd1cmFibGU6IHRydWUsIGVudW1lcmFibGU6IHRydWUsIHdyaXRhYmxlOiBmYWxzZX07XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaGFzKHRhcmdldCwga2V5OiBzdHJpbmcpIHtcbiAgICAgICAgICAgICAgICB3YXRjaChrZXkpO1xuICAgICAgICAgICAgICAgIHJldHVybiB1cmxTZWFyY2hQYXJhbXMuaGFzKGtleSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICB9LCBbdXJsU2VhcmNoUGFyYW1zXSk7XG5cbiAgICBjb25zdCBzZXRQYXJhbXMgPSB1c2VDYWxsYmFjayhcbiAgICAgICAgKFxuICAgICAgICAgICAgbmV4dFBhcmFtczpcbiAgICAgICAgICAgICAgICB8IFRBbGxQYXJhbXM8UEFSQU1TPlxuICAgICAgICAgICAgICAgIHwgKChcbiAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50OiBUQWxsUGFyYW1zPFBBUkFNUz4sXG4gICAgICAgICAgICAgICAgICApID0+IFBhcnRpYWw8VEFsbFBhcmFtczxQQVJBTVM+PiksXG4gICAgICAgICAgICByZXBsYWNlOiBib29sZWFuID0gZmFsc2UsXG4gICAgICAgICkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXh0VVJMID0gbmV3IFVSTCh3aW5kb3cubG9jYXRpb24uaHJlZik7XG5cbiAgICAgICAgICAgICAgICBwYXVzZVdhdGNoLmN1cnJlbnQgPSB0cnVlO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgbmV4dFBhcmFtc09iamVjdCA9XG4gICAgICAgICAgICAgICAgICAgIG5leHRQYXJhbXMgaW5zdGFuY2VvZiBGdW5jdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgPyBuZXh0UGFyYW1zKHBhcmFtcylcbiAgICAgICAgICAgICAgICAgICAgICAgIDogbmV4dFBhcmFtcztcblxuICAgICAgICAgICAgICAgIHBhdXNlV2F0Y2guY3VycmVudCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgYXBwbHlRdWVyeVBhcmFtcyhuZXh0VVJMLCBuZXh0UGFyYW1zT2JqZWN0LCB0cnVlKTtcblxuICAgICAgICAgICAgICAgIGlmIChyZXBsYWNlKSB7XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5oaXN0b3J5LnJlcGxhY2VTdGF0ZShudWxsLCAnJywgbmV4dFVSTCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgd2luZG93Lmhpc3RvcnkucHVzaFN0YXRlKG51bGwsICcnLCBuZXh0VVJMKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHdoaWxlIHNldHRpbmcgcXVlcnkgcGFyYW1zJywgZXJyb3IpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBwYXVzZVdhdGNoLmN1cnJlbnQgPSBmYWxzZTtcbiAgICAgICAgfSxcbiAgICAgICAgW3BhcmFtc10sXG4gICAgKTtcblxuICAgIHJldHVybiBbcGFyYW1zLCBzZXRQYXJhbXNdIGFzIGNvbnN0O1xufVxuIl19