// utils/urlWatcher.ts // there's a _lot_ of typescript fuckery happening here, because this whole class violates the laws of nature // please do not be alarmed. export class UrlWatcher { // eslint-disable-next-line no-use-before-define private static instance: UrlWatcher; private lastUrl: string = window.location.href; private constructor() { this.patchHistoryMethods(); this.init(); } static getInstance(): UrlWatcher { if (!UrlWatcher.instance) { UrlWatcher.instance = new UrlWatcher(); } return UrlWatcher.instance; } private patchHistoryMethods() { const originalPushState = window.history.pushState; const originalReplaceState = window.history.replaceState; window.history.pushState = function (...args) { const result = originalPushState.apply(this, args); window.dispatchEvent(new Event("urlchange")); return result; }; window.history.replaceState = function (...args) { const result = originalReplaceState.apply(this, args); window.dispatchEvent(new Event("urlchange")); return result; }; } private init() { // Handle all relevant events window.addEventListener("popstate", () => this.checkUrlChange()); window.addEventListener("urlchange", () => this.checkUrlChange()); // Fallback for missed changes setInterval(() => this.checkUrlChange(), 1000); } private async checkUrlChange() { const currentUrl = window.location.href; if (currentUrl !== this.lastUrl) { this.lastUrl = currentUrl; await this.pingUrl(currentUrl); } } private async pingUrl(url: string) { try { const response = await fetch( url.replace( "localhost:3000", "staging.developer.salesforce.com" ), { method: "HEAD", redirect: "manual" } ); if ( response.type === "opaqueredirect" || (response.status >= 300 && response.status < 400) ) { // eslint-disable-next-line no-self-assign window.location.href = window.location.href; } } catch (error) { console.error("Error checking URL:", error); } } }