@flareapp/react 2.6.0 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/inject.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as FlareErrorBoundaryFallbackProps, c as FlareReactContext, i as FlareErrorBoundary, l as MinifiedReactError, n as FlareReactErrorHandlerOptions, o as FlareErrorBoundaryProps, r as flareReactErrorHandler, s as ComponentStackFrame, t as FlareReactErrorHandlerCallback } from "./flareReactErrorHandler-BcVYRMtC.mjs";
1
+ import { a as FlareErrorBoundaryFallbackProps, c as FlareReactContext, i as FlareErrorBoundary, l as MinifiedReactError, n as FlareReactErrorHandlerOptions, o as FlareErrorBoundaryProps, r as flareReactErrorHandler, s as ComponentStackFrame, t as FlareReactErrorHandlerCallback } from "./flareReactErrorHandler-Ce0sCyMK.mjs";
2
2
  export { type ComponentStackFrame, FlareErrorBoundary, type FlareErrorBoundaryFallbackProps, type FlareErrorBoundaryProps, type FlareReactContext, type FlareReactErrorHandlerCallback, type FlareReactErrorHandlerOptions, type MinifiedReactError, flareReactErrorHandler };
package/dist/inject.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { n as FlareErrorBoundary, t as flareReactErrorHandler } from "./flareReactErrorHandler-CfcBSmhG.mjs";
1
+ import { n as FlareErrorBoundary, t as flareReactErrorHandler } from "./flareReactErrorHandler-sRmFoJAG.mjs";
2
2
 
3
3
  export { FlareErrorBoundary, flareReactErrorHandler };
@@ -0,0 +1,63 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_flareReactErrorHandler = require('./flareReactErrorHandler-DBmb7u7U.cjs');
3
+ let react = require("react");
4
+ let _flareapp_js_browser = require("@flareapp/js/browser");
5
+
6
+ //#region src/profiler.ts
7
+ const useMountEffect = typeof window === "undefined" ? react.useEffect : react.useLayoutEffect;
8
+ const FlareProfilerContext = (0, react.createContext)(null);
9
+ /** Records one `browser_component` span for its mount, nested under the nearest profiled ancestor
10
+ * or the active `browser_pageload` / `browser_navigation` root. */
11
+ function FlareProfiler({ name, children }) {
12
+ const context = (0, react.useContext)(FlareProfilerContext);
13
+ const parentRef = (0, react.useRef)(void 0);
14
+ if (parentRef.current === void 0) try {
15
+ parentRef.current = (0, _flareapp_js_browser.resolveComponentParent)(context, (0, _flareapp_js_browser.activeComponentRoot)());
16
+ } catch {
17
+ parentRef.current = null;
18
+ }
19
+ const parent = parentRef.current;
20
+ const ownRef = (0, react.useRef)(null);
21
+ if (parent && ownRef.current === null) try {
22
+ const spanId = (0, _flareapp_js_browser.reserveSpanId)(parent.traceId);
23
+ ownRef.current = spanId ? {
24
+ spanId,
25
+ startNano: (0, _flareapp_js_browser.nowNano)()
26
+ } : null;
27
+ } catch {}
28
+ const providedRef = (0, react.useRef)(void 0);
29
+ if (providedRef.current === void 0) providedRef.current = parent && ownRef.current ? {
30
+ traceId: parent.traceId,
31
+ parentSpanId: ownRef.current.spanId
32
+ } : null;
33
+ const hasRecorded = (0, react.useRef)(false);
34
+ useMountEffect(() => {
35
+ const own = ownRef.current;
36
+ if (!parent || !own || hasRecorded.current) return;
37
+ hasRecorded.current = true;
38
+ try {
39
+ (0, _flareapp_js_browser.recordComponentSpan)({
40
+ name,
41
+ spanId: own.spanId,
42
+ parent,
43
+ startTimeUnixNano: own.startNano,
44
+ endTimeUnixNano: (0, _flareapp_js_browser.nowNano)()
45
+ });
46
+ } catch {}
47
+ }, []);
48
+ if (providedRef.current === null) return children ?? null;
49
+ return (0, react.createElement)(FlareProfilerContext.Provider, { value: providedRef.current }, children ?? null);
50
+ }
51
+ /** Wraps `Component` in a `FlareProfiler`. Name it explicitly when the component is anonymous or minified. */
52
+ function withFlareProfiler(Component, options) {
53
+ const name = options?.name || Component.displayName || Component.name || "Unknown";
54
+ function Profiled(props) {
55
+ return (0, react.createElement)(FlareProfiler, { name }, (0, react.createElement)(Component, props));
56
+ }
57
+ Profiled.displayName = `withFlareProfiler(${name})`;
58
+ return Profiled;
59
+ }
60
+
61
+ //#endregion
62
+ exports.FlareProfiler = FlareProfiler;
63
+ exports.withFlareProfiler = withFlareProfiler;
@@ -0,0 +1,19 @@
1
+ import { ComponentType, FunctionComponent, ReactNode } from "react";
2
+
3
+ //#region src/profiler.d.ts
4
+ type FlareProfilerProps = {
5
+ /** The span's name, as it appears in the trace. */name: string;
6
+ children?: ReactNode;
7
+ };
8
+ /** Records one `browser_component` span for its mount, nested under the nearest profiled ancestor
9
+ * or the active `browser_pageload` / `browser_navigation` root. */
10
+ declare function FlareProfiler({
11
+ name,
12
+ children
13
+ }: FlareProfilerProps): ReactNode;
14
+ /** Wraps `Component` in a `FlareProfiler`. Name it explicitly when the component is anonymous or minified. */
15
+ declare function withFlareProfiler<P extends object>(Component: ComponentType<P>, options?: {
16
+ name?: string;
17
+ }): FunctionComponent<P>;
18
+ //#endregion
19
+ export { FlareProfiler, FlareProfilerProps, withFlareProfiler };
@@ -0,0 +1,19 @@
1
+ import { ComponentType, FunctionComponent, ReactNode } from "react";
2
+
3
+ //#region src/profiler.d.ts
4
+ type FlareProfilerProps = {
5
+ /** The span's name, as it appears in the trace. */name: string;
6
+ children?: ReactNode;
7
+ };
8
+ /** Records one `browser_component` span for its mount, nested under the nearest profiled ancestor
9
+ * or the active `browser_pageload` / `browser_navigation` root. */
10
+ declare function FlareProfiler({
11
+ name,
12
+ children
13
+ }: FlareProfilerProps): ReactNode;
14
+ /** Wraps `Component` in a `FlareProfiler`. Name it explicitly when the component is anonymous or minified. */
15
+ declare function withFlareProfiler<P extends object>(Component: ComponentType<P>, options?: {
16
+ name?: string;
17
+ }): FunctionComponent<P>;
18
+ //#endregion
19
+ export { FlareProfiler, FlareProfilerProps, withFlareProfiler };
@@ -0,0 +1,60 @@
1
+ import { createContext, createElement, useContext, useEffect, useLayoutEffect, useRef } from "react";
2
+ import { activeComponentRoot, nowNano, recordComponentSpan, reserveSpanId, resolveComponentParent } from "@flareapp/js/browser";
3
+
4
+ //#region src/profiler.ts
5
+ const useMountEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
6
+ const FlareProfilerContext = createContext(null);
7
+ /** Records one `browser_component` span for its mount, nested under the nearest profiled ancestor
8
+ * or the active `browser_pageload` / `browser_navigation` root. */
9
+ function FlareProfiler({ name, children }) {
10
+ const context = useContext(FlareProfilerContext);
11
+ const parentRef = useRef(void 0);
12
+ if (parentRef.current === void 0) try {
13
+ parentRef.current = resolveComponentParent(context, activeComponentRoot());
14
+ } catch {
15
+ parentRef.current = null;
16
+ }
17
+ const parent = parentRef.current;
18
+ const ownRef = useRef(null);
19
+ if (parent && ownRef.current === null) try {
20
+ const spanId = reserveSpanId(parent.traceId);
21
+ ownRef.current = spanId ? {
22
+ spanId,
23
+ startNano: nowNano()
24
+ } : null;
25
+ } catch {}
26
+ const providedRef = useRef(void 0);
27
+ if (providedRef.current === void 0) providedRef.current = parent && ownRef.current ? {
28
+ traceId: parent.traceId,
29
+ parentSpanId: ownRef.current.spanId
30
+ } : null;
31
+ const hasRecorded = useRef(false);
32
+ useMountEffect(() => {
33
+ const own = ownRef.current;
34
+ if (!parent || !own || hasRecorded.current) return;
35
+ hasRecorded.current = true;
36
+ try {
37
+ recordComponentSpan({
38
+ name,
39
+ spanId: own.spanId,
40
+ parent,
41
+ startTimeUnixNano: own.startNano,
42
+ endTimeUnixNano: nowNano()
43
+ });
44
+ } catch {}
45
+ }, []);
46
+ if (providedRef.current === null) return children ?? null;
47
+ return createElement(FlareProfilerContext.Provider, { value: providedRef.current }, children ?? null);
48
+ }
49
+ /** Wraps `Component` in a `FlareProfiler`. Name it explicitly when the component is anonymous or minified. */
50
+ function withFlareProfiler(Component, options) {
51
+ const name = options?.name || Component.displayName || Component.name || "Unknown";
52
+ function Profiled(props) {
53
+ return createElement(FlareProfiler, { name }, createElement(Component, props));
54
+ }
55
+ Profiled.displayName = `withFlareProfiler(${name})`;
56
+ return Profiled;
57
+ }
58
+
59
+ //#endregion
60
+ export { FlareProfiler, withFlareProfiler };
@@ -0,0 +1,94 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_flareReactErrorHandler = require('./flareReactErrorHandler-DBmb7u7U.cjs');
3
+ let _flareapp_js_browser = require("@flareapp/js/browser");
4
+
5
+ //#region src/react-router.ts
6
+ /**
7
+ * Rebuild the parameterized template (`/product/:id`) by joining each match's declared `route.path`.
8
+ * Follows Sentry's getNormalizedName, but reads the router's already-resolved `state.matches` rather
9
+ * than matching again.
10
+ */
11
+ function routeNameFromMatches(matches) {
12
+ if (!matches || matches.length === 0) return;
13
+ let path = "";
14
+ for (const match of matches) {
15
+ const routePath = match.route?.path;
16
+ if (!routePath) continue;
17
+ path = routePath[0] === "/" ? routePath : (path.endsWith("/") ? path : path + "/") + routePath;
18
+ }
19
+ if (!path) return;
20
+ if (path[0] !== "/") path = "/" + path;
21
+ return path.replace(/\/{2,}/g, "/");
22
+ }
23
+ /**
24
+ * Trace a React Router v7 data router (createBrowserRouter / createHashRouter / createMemoryRouter):
25
+ * name the browser_pageload root from the initial route, and open a parameterized, held
26
+ * browser_navigation root per route change, named once the router settles. Returns a cleanup that
27
+ * unsubscribes and unregisters. Safe to call before or after tracing is enabled; no-ops when off.
28
+ * Calling it twice on the same router replaces the first instrumentation.
29
+ */
30
+ function traceReactRouter(router) {
31
+ if (typeof router?.subscribe !== "function") return () => {};
32
+ return (0, _flareapp_js_browser.instrumentOnce)(router, (track) => install(router, track));
33
+ }
34
+ function install(router, track) {
35
+ const nav = (0, _flareapp_js_browser.registerNavigationSource)();
36
+ track(() => nav.unregister());
37
+ function routeNameFor(state) {
38
+ return (0, _flareapp_js_browser.routeName)(() => routeNameFromMatches(state.matches), state.location.pathname, hrefOf(state.location));
39
+ }
40
+ function hrefOf(loc) {
41
+ return (0, _flareapp_js_browser.resolveHref)(() => router.createHref?.(loc), keyOf(loc));
42
+ }
43
+ function keyOf(loc) {
44
+ return (loc.pathname || "") + (loc.search || "") + (loc.hash || "");
45
+ }
46
+ let sawInitialSettle = false;
47
+ let inFlight = false;
48
+ let lastLocationKey = keyOf(router.state.location);
49
+ try {
50
+ if (router.state.matches.length > 0) nav.setActiveRouteName(routeNameFor(router.state));
51
+ sawInitialSettle = router.state.initialized === true;
52
+ } catch {}
53
+ function onState(state) {
54
+ if (!sawInitialSettle) {
55
+ lastLocationKey = keyOf(state.location);
56
+ if (state.matches.length > 0) nav.setActiveRouteName(routeNameFor(state));
57
+ if (state.initialized) sawInitialSettle = true;
58
+ return;
59
+ }
60
+ const navState = state.navigation.state;
61
+ if (!inFlight && navState !== "idle") {
62
+ inFlight = true;
63
+ const destination = state.navigation.location ?? state.location;
64
+ nav.startNavigation({
65
+ path: destination.pathname,
66
+ url: hrefOf(destination),
67
+ hold: true
68
+ });
69
+ return;
70
+ }
71
+ if (inFlight && navState === "idle") {
72
+ inFlight = false;
73
+ lastLocationKey = keyOf(state.location);
74
+ nav.settleNavigation(routeNameFor(state));
75
+ return;
76
+ }
77
+ if (!inFlight && navState === "idle") {
78
+ const locationKey = keyOf(state.location);
79
+ if (locationKey !== lastLocationKey) {
80
+ lastLocationKey = locationKey;
81
+ nav.startNavigation({
82
+ path: state.location.pathname,
83
+ url: hrefOf(state.location)
84
+ });
85
+ nav.settleNavigation(routeNameFor(state));
86
+ }
87
+ }
88
+ }
89
+ track(router.subscribe((0, _flareapp_js_browser.insulate)(onState)));
90
+ }
91
+
92
+ //#endregion
93
+ exports.routeNameFromMatches = routeNameFromMatches;
94
+ exports.traceReactRouter = traceReactRouter;
@@ -0,0 +1,54 @@
1
+ //#region src/vendor/reactRouterTypes.d.ts
2
+ type ReactRouterLocationLike = {
3
+ pathname: string;
4
+ search?: string;
5
+ hash?: string;
6
+ state?: unknown;
7
+ };
8
+ type ReactRouterRouteLike = {
9
+ path?: string;
10
+ index?: boolean;
11
+ id?: string;
12
+ };
13
+ type ReactRouterMatchLike = {
14
+ route: ReactRouterRouteLike;
15
+ pathname: string;
16
+ params?: Record<string, string | undefined>;
17
+ };
18
+ type ReactRouterNavigationLike = {
19
+ state: 'idle' | 'loading' | 'submitting';
20
+ location?: ReactRouterLocationLike;
21
+ };
22
+ type ReactRouterStateLike = {
23
+ location: ReactRouterLocationLike;
24
+ matches: ReactRouterMatchLike[];
25
+ navigation: ReactRouterNavigationLike;
26
+ initialized?: boolean;
27
+ };
28
+ type ReactRouterLike = {
29
+ subscribe(cb: (state: ReactRouterStateLike) => void): () => void;
30
+ state: ReactRouterStateLike;
31
+ /**
32
+ * Applies the router's `basename` (and, for a hash router, the `#` prefix) to a location.
33
+ * `state.location.pathname` has both stripped. Optional so a hand-built router still types.
34
+ */
35
+ createHref?(location: ReactRouterLocationLike): string;
36
+ };
37
+ //#endregion
38
+ //#region src/react-router.d.ts
39
+ /**
40
+ * Rebuild the parameterized template (`/product/:id`) by joining each match's declared `route.path`.
41
+ * Follows Sentry's getNormalizedName, but reads the router's already-resolved `state.matches` rather
42
+ * than matching again.
43
+ */
44
+ declare function routeNameFromMatches(matches: ReactRouterMatchLike[] | undefined): string | undefined;
45
+ /**
46
+ * Trace a React Router v7 data router (createBrowserRouter / createHashRouter / createMemoryRouter):
47
+ * name the browser_pageload root from the initial route, and open a parameterized, held
48
+ * browser_navigation root per route change, named once the router settles. Returns a cleanup that
49
+ * unsubscribes and unregisters. Safe to call before or after tracing is enabled; no-ops when off.
50
+ * Calling it twice on the same router replaces the first instrumentation.
51
+ */
52
+ declare function traceReactRouter(router: ReactRouterLike): () => void;
53
+ //#endregion
54
+ export { type ReactRouterLike, type ReactRouterLocationLike, type ReactRouterMatchLike, type ReactRouterNavigationLike, type ReactRouterRouteLike, type ReactRouterStateLike, routeNameFromMatches, traceReactRouter };
@@ -0,0 +1,54 @@
1
+ //#region src/vendor/reactRouterTypes.d.ts
2
+ type ReactRouterLocationLike = {
3
+ pathname: string;
4
+ search?: string;
5
+ hash?: string;
6
+ state?: unknown;
7
+ };
8
+ type ReactRouterRouteLike = {
9
+ path?: string;
10
+ index?: boolean;
11
+ id?: string;
12
+ };
13
+ type ReactRouterMatchLike = {
14
+ route: ReactRouterRouteLike;
15
+ pathname: string;
16
+ params?: Record<string, string | undefined>;
17
+ };
18
+ type ReactRouterNavigationLike = {
19
+ state: 'idle' | 'loading' | 'submitting';
20
+ location?: ReactRouterLocationLike;
21
+ };
22
+ type ReactRouterStateLike = {
23
+ location: ReactRouterLocationLike;
24
+ matches: ReactRouterMatchLike[];
25
+ navigation: ReactRouterNavigationLike;
26
+ initialized?: boolean;
27
+ };
28
+ type ReactRouterLike = {
29
+ subscribe(cb: (state: ReactRouterStateLike) => void): () => void;
30
+ state: ReactRouterStateLike;
31
+ /**
32
+ * Applies the router's `basename` (and, for a hash router, the `#` prefix) to a location.
33
+ * `state.location.pathname` has both stripped. Optional so a hand-built router still types.
34
+ */
35
+ createHref?(location: ReactRouterLocationLike): string;
36
+ };
37
+ //#endregion
38
+ //#region src/react-router.d.ts
39
+ /**
40
+ * Rebuild the parameterized template (`/product/:id`) by joining each match's declared `route.path`.
41
+ * Follows Sentry's getNormalizedName, but reads the router's already-resolved `state.matches` rather
42
+ * than matching again.
43
+ */
44
+ declare function routeNameFromMatches(matches: ReactRouterMatchLike[] | undefined): string | undefined;
45
+ /**
46
+ * Trace a React Router v7 data router (createBrowserRouter / createHashRouter / createMemoryRouter):
47
+ * name the browser_pageload root from the initial route, and open a parameterized, held
48
+ * browser_navigation root per route change, named once the router settles. Returns a cleanup that
49
+ * unsubscribes and unregisters. Safe to call before or after tracing is enabled; no-ops when off.
50
+ * Calling it twice on the same router replaces the first instrumentation.
51
+ */
52
+ declare function traceReactRouter(router: ReactRouterLike): () => void;
53
+ //#endregion
54
+ export { type ReactRouterLike, type ReactRouterLocationLike, type ReactRouterMatchLike, type ReactRouterNavigationLike, type ReactRouterRouteLike, type ReactRouterStateLike, routeNameFromMatches, traceReactRouter };
@@ -0,0 +1,91 @@
1
+ import { instrumentOnce, insulate, registerNavigationSource, resolveHref, routeName } from "@flareapp/js/browser";
2
+
3
+ //#region src/react-router.ts
4
+ /**
5
+ * Rebuild the parameterized template (`/product/:id`) by joining each match's declared `route.path`.
6
+ * Follows Sentry's getNormalizedName, but reads the router's already-resolved `state.matches` rather
7
+ * than matching again.
8
+ */
9
+ function routeNameFromMatches(matches) {
10
+ if (!matches || matches.length === 0) return;
11
+ let path = "";
12
+ for (const match of matches) {
13
+ const routePath = match.route?.path;
14
+ if (!routePath) continue;
15
+ path = routePath[0] === "/" ? routePath : (path.endsWith("/") ? path : path + "/") + routePath;
16
+ }
17
+ if (!path) return;
18
+ if (path[0] !== "/") path = "/" + path;
19
+ return path.replace(/\/{2,}/g, "/");
20
+ }
21
+ /**
22
+ * Trace a React Router v7 data router (createBrowserRouter / createHashRouter / createMemoryRouter):
23
+ * name the browser_pageload root from the initial route, and open a parameterized, held
24
+ * browser_navigation root per route change, named once the router settles. Returns a cleanup that
25
+ * unsubscribes and unregisters. Safe to call before or after tracing is enabled; no-ops when off.
26
+ * Calling it twice on the same router replaces the first instrumentation.
27
+ */
28
+ function traceReactRouter(router) {
29
+ if (typeof router?.subscribe !== "function") return () => {};
30
+ return instrumentOnce(router, (track) => install(router, track));
31
+ }
32
+ function install(router, track) {
33
+ const nav = registerNavigationSource();
34
+ track(() => nav.unregister());
35
+ function routeNameFor(state) {
36
+ return routeName(() => routeNameFromMatches(state.matches), state.location.pathname, hrefOf(state.location));
37
+ }
38
+ function hrefOf(loc) {
39
+ return resolveHref(() => router.createHref?.(loc), keyOf(loc));
40
+ }
41
+ function keyOf(loc) {
42
+ return (loc.pathname || "") + (loc.search || "") + (loc.hash || "");
43
+ }
44
+ let sawInitialSettle = false;
45
+ let inFlight = false;
46
+ let lastLocationKey = keyOf(router.state.location);
47
+ try {
48
+ if (router.state.matches.length > 0) nav.setActiveRouteName(routeNameFor(router.state));
49
+ sawInitialSettle = router.state.initialized === true;
50
+ } catch {}
51
+ function onState(state) {
52
+ if (!sawInitialSettle) {
53
+ lastLocationKey = keyOf(state.location);
54
+ if (state.matches.length > 0) nav.setActiveRouteName(routeNameFor(state));
55
+ if (state.initialized) sawInitialSettle = true;
56
+ return;
57
+ }
58
+ const navState = state.navigation.state;
59
+ if (!inFlight && navState !== "idle") {
60
+ inFlight = true;
61
+ const destination = state.navigation.location ?? state.location;
62
+ nav.startNavigation({
63
+ path: destination.pathname,
64
+ url: hrefOf(destination),
65
+ hold: true
66
+ });
67
+ return;
68
+ }
69
+ if (inFlight && navState === "idle") {
70
+ inFlight = false;
71
+ lastLocationKey = keyOf(state.location);
72
+ nav.settleNavigation(routeNameFor(state));
73
+ return;
74
+ }
75
+ if (!inFlight && navState === "idle") {
76
+ const locationKey = keyOf(state.location);
77
+ if (locationKey !== lastLocationKey) {
78
+ lastLocationKey = locationKey;
79
+ nav.startNavigation({
80
+ path: state.location.pathname,
81
+ url: hrefOf(state.location)
82
+ });
83
+ nav.settleNavigation(routeNameFor(state));
84
+ }
85
+ }
86
+ }
87
+ track(router.subscribe(insulate(onState)));
88
+ }
89
+
90
+ //#endregion
91
+ export { routeNameFromMatches, traceReactRouter };
@@ -0,0 +1,89 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_flareReactErrorHandler = require('./flareReactErrorHandler-DBmb7u7U.cjs');
3
+ let _flareapp_js_browser = require("@flareapp/js/browser");
4
+
5
+ //#region src/tanstack-router.ts
6
+ /**
7
+ * How long a held navigation root waits for `onResolved` before settling itself. Exported so the suite
8
+ * drives it instead of hardcoding the number; not part of the supported surface.
9
+ */
10
+ const STALE_NAVIGATION_TIMEOUT_MS = 5e3;
11
+ /**
12
+ * Trace a TanStack Router instance: name the `browser_pageload` root from the
13
+ * initial route and open a parameterized `browser_navigation` root per route
14
+ * change. Returns a cleanup that unsubscribes and unregisters. Safe to call
15
+ * before or after tracing is enabled; no-ops when tracing is off. Calling it
16
+ * twice on the same router replaces the first instrumentation rather than
17
+ * stacking a second set of subscriptions.
18
+ */
19
+ function traceTanStackRouter(router) {
20
+ if (typeof router?.subscribe !== "function") return () => {};
21
+ return (0, _flareapp_js_browser.instrumentOnce)(router, (track) => install(router, track));
22
+ }
23
+ function install(router, track) {
24
+ const nav = (0, _flareapp_js_browser.registerNavigationSource)();
25
+ track(() => nav.unregister());
26
+ function hrefOf(loc) {
27
+ return (0, _flareapp_js_browser.resolveHref)(() => loc.publicHref ?? loc.href, loc.pathname);
28
+ }
29
+ function routeNameFor(loc) {
30
+ return (0, _flareapp_js_browser.routeName)(() => {
31
+ const matches = router.matchRoutes(loc.pathname, loc.search, {
32
+ preload: false,
33
+ throwOnError: false
34
+ });
35
+ if (!matches.some((m) => m.routeId !== "__root__")) return;
36
+ const last = matches[matches.length - 1];
37
+ return last?.fullPath || last?.routeId;
38
+ }, loc.pathname, hrefOf(loc));
39
+ }
40
+ try {
41
+ nav.setActiveRouteName(routeNameFor(router.state.location));
42
+ } catch {}
43
+ let inFlight = false;
44
+ let destination = null;
45
+ let staleTimer = null;
46
+ function clearStaleTimer() {
47
+ if (staleTimer !== null) {
48
+ clearTimeout(staleTimer);
49
+ staleTimer = null;
50
+ }
51
+ }
52
+ function settle(location) {
53
+ clearStaleTimer();
54
+ inFlight = false;
55
+ destination = null;
56
+ nav.settleNavigation(routeNameFor(location));
57
+ }
58
+ track(clearStaleTimer);
59
+ track(router.subscribe("onBeforeLoad", (0, _flareapp_js_browser.insulate)((event) => {
60
+ if (event.fromLocation === void 0) return;
61
+ if (event.hrefChanged === false) return;
62
+ if (event.toLocation.state === event.fromLocation.state) return;
63
+ if (!inFlight) {
64
+ inFlight = true;
65
+ nav.startNavigation({
66
+ path: event.toLocation.pathname,
67
+ hold: true
68
+ });
69
+ }
70
+ destination = event.toLocation;
71
+ nav.setActiveRouteName(routeNameFor(event.toLocation));
72
+ clearStaleTimer();
73
+ staleTimer = setTimeout((0, _flareapp_js_browser.insulate)(() => {
74
+ staleTimer = null;
75
+ if (destination) settle(destination);
76
+ }), STALE_NAVIGATION_TIMEOUT_MS);
77
+ })));
78
+ track(router.subscribe("onResolved", (0, _flareapp_js_browser.insulate)((event) => {
79
+ if (event.fromLocation === void 0) {
80
+ nav.setActiveRouteName(routeNameFor(event.toLocation));
81
+ return;
82
+ }
83
+ if (inFlight) settle(event.toLocation);
84
+ })));
85
+ }
86
+
87
+ //#endregion
88
+ exports.STALE_NAVIGATION_TIMEOUT_MS = STALE_NAVIGATION_TIMEOUT_MS;
89
+ exports.traceTanStackRouter = traceTanStackRouter;
@@ -0,0 +1,45 @@
1
+ //#region src/vendor/tanstackRouterTypes.d.ts
2
+ type TanStackLocationLike = {
3
+ pathname: string;
4
+ search: unknown;
5
+ href?: string;
6
+ publicHref?: string;
7
+ state?: unknown;
8
+ };
9
+ type TanStackNavEventLike = {
10
+ fromLocation?: TanStackLocationLike;
11
+ toLocation: TanStackLocationLike;
12
+ hrefChanged?: boolean;
13
+ };
14
+ type TanStackMatchLike = {
15
+ routeId?: string;
16
+ fullPath?: string;
17
+ };
18
+ type TanStackRouterLike = {
19
+ subscribe(eventType: 'onBeforeLoad' | 'onResolved', cb: (event: TanStackNavEventLike) => void): () => void;
20
+ matchRoutes(pathname: string, search: unknown, opts?: {
21
+ preload?: boolean;
22
+ throwOnError?: boolean;
23
+ }): TanStackMatchLike[];
24
+ state: {
25
+ location: TanStackLocationLike;
26
+ };
27
+ };
28
+ //#endregion
29
+ //#region src/tanstack-router.d.ts
30
+ /**
31
+ * How long a held navigation root waits for `onResolved` before settling itself. Exported so the suite
32
+ * drives it instead of hardcoding the number; not part of the supported surface.
33
+ */
34
+ declare const STALE_NAVIGATION_TIMEOUT_MS = 5000;
35
+ /**
36
+ * Trace a TanStack Router instance: name the `browser_pageload` root from the
37
+ * initial route and open a parameterized `browser_navigation` root per route
38
+ * change. Returns a cleanup that unsubscribes and unregisters. Safe to call
39
+ * before or after tracing is enabled; no-ops when tracing is off. Calling it
40
+ * twice on the same router replaces the first instrumentation rather than
41
+ * stacking a second set of subscriptions.
42
+ */
43
+ declare function traceTanStackRouter(router: TanStackRouterLike): () => void;
44
+ //#endregion
45
+ export { STALE_NAVIGATION_TIMEOUT_MS, type TanStackLocationLike, type TanStackMatchLike, type TanStackNavEventLike, type TanStackRouterLike, traceTanStackRouter };
@@ -0,0 +1,45 @@
1
+ //#region src/vendor/tanstackRouterTypes.d.ts
2
+ type TanStackLocationLike = {
3
+ pathname: string;
4
+ search: unknown;
5
+ href?: string;
6
+ publicHref?: string;
7
+ state?: unknown;
8
+ };
9
+ type TanStackNavEventLike = {
10
+ fromLocation?: TanStackLocationLike;
11
+ toLocation: TanStackLocationLike;
12
+ hrefChanged?: boolean;
13
+ };
14
+ type TanStackMatchLike = {
15
+ routeId?: string;
16
+ fullPath?: string;
17
+ };
18
+ type TanStackRouterLike = {
19
+ subscribe(eventType: 'onBeforeLoad' | 'onResolved', cb: (event: TanStackNavEventLike) => void): () => void;
20
+ matchRoutes(pathname: string, search: unknown, opts?: {
21
+ preload?: boolean;
22
+ throwOnError?: boolean;
23
+ }): TanStackMatchLike[];
24
+ state: {
25
+ location: TanStackLocationLike;
26
+ };
27
+ };
28
+ //#endregion
29
+ //#region src/tanstack-router.d.ts
30
+ /**
31
+ * How long a held navigation root waits for `onResolved` before settling itself. Exported so the suite
32
+ * drives it instead of hardcoding the number; not part of the supported surface.
33
+ */
34
+ declare const STALE_NAVIGATION_TIMEOUT_MS = 5000;
35
+ /**
36
+ * Trace a TanStack Router instance: name the `browser_pageload` root from the
37
+ * initial route and open a parameterized `browser_navigation` root per route
38
+ * change. Returns a cleanup that unsubscribes and unregisters. Safe to call
39
+ * before or after tracing is enabled; no-ops when tracing is off. Calling it
40
+ * twice on the same router replaces the first instrumentation rather than
41
+ * stacking a second set of subscriptions.
42
+ */
43
+ declare function traceTanStackRouter(router: TanStackRouterLike): () => void;
44
+ //#endregion
45
+ export { STALE_NAVIGATION_TIMEOUT_MS, type TanStackLocationLike, type TanStackMatchLike, type TanStackNavEventLike, type TanStackRouterLike, traceTanStackRouter };