UNPKG

@grafana/faro-web-sdk

Version:

Faro instrumentations, metas, transports for web.

138 lines 6.09 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MESSAGE_TYPE_URL_CHANGE = void 0; exports.monitorUrlChanges = monitorUrlChanges; exports.__resetUrlChangeMonitorForTests = __resetUrlChangeMonitorForTests; var faro_core_1 = require("@grafana/faro-core"); exports.MESSAGE_TYPE_URL_CHANGE = 'url-change'; var urlChangeObservable; var isInstrumented = false; var lastHref; var originalPushState; var originalReplaceState; var onPopStateHandler; var onHashChangeHandler; var onNavigateHandler; var originalNavigateEventIntercept; function monitorUrlChanges() { if (!urlChangeObservable) { urlChangeObservable = new faro_core_1.Observable(); lastHref = location.href; } function emit(trigger, toOverride) { var next = toOverride !== null && toOverride !== void 0 ? toOverride : location.href; if (next !== lastHref) { urlChangeObservable.notify({ type: exports.MESSAGE_TYPE_URL_CHANGE, from: lastHref, to: next, trigger: trigger }); lastHref = next; } } if (!isInstrumented) { var hasNavigation = 'navigation' in window && 'NavigateEvent' in window; if (hasNavigation) { // Prefer Navigation API when supported: do not patch history or add popstate/hashchange listeners onNavigateHandler = function (e) { try { var destination = e === null || e === void 0 ? void 0 : e.destination; if ((destination === null || destination === void 0 ? void 0 : destination.sameDocument) && typeof destination.url === 'string') { emit('navigate', destination.url); } } catch (_err) { // Swallow to avoid impacting host app } }; window.navigation.addEventListener('navigate', onNavigateHandler); var NavigateEventConstructor = window.NavigateEvent; if (NavigateEventConstructor && NavigateEventConstructor.prototype && typeof NavigateEventConstructor.prototype.intercept === 'function') { if (!originalNavigateEventIntercept) { originalNavigateEventIntercept = NavigateEventConstructor.prototype.intercept; } // Wrap intercept to detect soft navigations (cross-document turned same-document) NavigateEventConstructor.prototype.intercept = function (options) { try { var canIntercept = !!(this === null || this === void 0 ? void 0 : this.canIntercept); var destination = this === null || this === void 0 ? void 0 : this.destination; if (canIntercept && destination && destination.sameDocument === false && typeof destination.url === 'string') { emit('navigate-intercept', destination.url); } } catch (_err) { // ignore } return originalNavigateEventIntercept.call(this, options); }; } isInstrumented = true; } else { // Fallback: history API patching + popstate/hashchange if (!originalPushState) { originalPushState = window.history.pushState; } window.history.pushState = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var result = originalPushState.apply(window.history, args); emit('pushState'); return result; }; if (!originalReplaceState) { originalReplaceState = window.history.replaceState; } window.history.replaceState = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var result = originalReplaceState.apply(window.history, args); emit('replaceState'); return result; }; onPopStateHandler = function () { return emit('popstate'); }; onHashChangeHandler = function () { return emit('hashchange'); }; window.addEventListener('popstate', onPopStateHandler); window.addEventListener('hashchange', onHashChangeHandler); isInstrumented = true; } } return urlChangeObservable; } // Test-only utility to reset state between tests function __resetUrlChangeMonitorForTests() { var _a, _b; if (onPopStateHandler) { window.removeEventListener('popstate', onPopStateHandler); } if (onHashChangeHandler) { window.removeEventListener('hashchange', onHashChangeHandler); } if (onNavigateHandler && ((_a = window.navigation) === null || _a === void 0 ? void 0 : _a.removeEventListener)) { window.navigation.removeEventListener('navigate', onNavigateHandler); } if (originalPushState) { window.history.pushState = originalPushState; } if (originalReplaceState) { window.history.replaceState = originalReplaceState; } if (originalNavigateEventIntercept && ((_b = window.NavigateEvent) === null || _b === void 0 ? void 0 : _b.prototype)) { window.NavigateEvent.prototype.intercept = originalNavigateEventIntercept; } urlChangeObservable = undefined; isInstrumented = false; lastHref = undefined; onPopStateHandler = undefined; onHashChangeHandler = undefined; onNavigateHandler = undefined; originalPushState = undefined; originalReplaceState = undefined; originalNavigateEventIntercept = undefined; } //# sourceMappingURL=urlChangeMonitor.js.map