ra-core
Version:
Core components of react-admin, a frontend Framework for building admin applications on top of REST services, using ES6, React
89 lines • 3.99 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.useCheckForApplicationUpdate = void 0;
const react_1 = require("react");
const useEvent_1 = require("./useEvent.cjs");
/**
* Checks if the application code has changed and calls the provided onNewVersionAvailable function when needed.
*
* It checks for code update by downloading the provided URL (default to the HTML page) and
* comparing the hash of the response with the hash of the current page.
*
* @param {UseCheckForApplicationUpdateOptions} options The options
* @param {Function} options.onNewVersionAvailable The function to call when a new version of the application is available.
* @param {string} options.url Optional. The URL to download to check for code update. Defaults to the current URL.
* @param {RequestInit} options.fetchOptions Optional. The options passed to fetch function when checking for update.
* @param {number} options.interval Optional. The interval in milliseconds between two checks. Defaults to 3600000 (1 hour).
* @param {boolean} options.disabled Optional. Whether the check should be disabled. Defaults to false.
*/
const useCheckForApplicationUpdate = (options) => {
const { url = window.location.href, fetchOptions, interval: delay = ONE_HOUR, onNewVersionAvailable: onNewVersionAvailableProp, disabled = process.env.NODE_ENV !== 'production', } = options;
const currentHash = (0, react_1.useRef)();
const onNewVersionAvailable = (0, useEvent_1.useEvent)(onNewVersionAvailableProp);
(0, react_1.useEffect)(() => {
if (disabled)
return;
getHashForUrl(url, fetchOptions).then(hash => {
if (hash != null) {
currentHash.current = hash;
}
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [disabled, url, JSON.stringify(fetchOptions)]);
(0, react_1.useEffect)(() => {
if (disabled)
return;
const interval = setInterval(() => {
getHashForUrl(url, fetchOptions)
.then(hash => {
if (hash != null && currentHash.current !== hash) {
// Store the latest hash to avoid calling the onNewVersionAvailable function multiple times
// or when users have closed the notification
currentHash.current = hash;
onNewVersionAvailable();
}
})
.catch(() => {
// Ignore errors to avoid issues when connectivity is lost
});
}, delay);
return () => clearInterval(interval);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [
delay,
onNewVersionAvailable,
disabled,
url,
// eslint-disable-next-line react-hooks/exhaustive-deps
JSON.stringify(fetchOptions),
]);
};
exports.useCheckForApplicationUpdate = useCheckForApplicationUpdate;
const getHashForUrl = async (url, fetchOptions) => {
try {
const response = await fetch(url, fetchOptions);
if (!response.ok)
return null;
const text = await response.text();
return hash(text);
}
catch (e) {
return null;
}
};
// Simple hash function, taken from https://stackoverflow.com/a/52171480/3723993, suggested by Copilot
const hash = (value, seed = 0) => {
let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
for (let i = 0, ch; i < value.length; i++) {
ch = value.charCodeAt(i);
h1 = Math.imul(h1 ^ ch, 2654435761);
h2 = Math.imul(h2 ^ ch, 1597334677);
}
h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507);
h1 ^= Math.imul(h2 ^ (h2 >>> 13), 3266489909);
h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507);
h2 ^= Math.imul(h1 ^ (h1 >>> 13), 3266489909);
return 4294967296 * (2097151 & h2) + (h1 >>> 0);
};
const ONE_HOUR = 1000 * 60 * 60;
//# sourceMappingURL=useCheckForApplicationUpdate.js.map