cloudflare-next-intl 0.8.32 → 0.8.33

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.
@@ -2,9 +2,8 @@
2
2
  * Auto-rendered alongside `FirebaseAuthClientProvider` when
3
3
  * `firebaseAuth.performance` isn't `false` — records Firebase Performance
4
4
  * custom traces for Web Vitals metrics (`web_cls`, `web_fcp`, `web_fid`,
5
- * `web_lcp`, `web_ttfb`, `web_inp`) and SPA route changes (`route_change`),
6
- * alongside Firebase Performance's own automatic page-load/network traces.
7
- * No-ops if `firebaseAuth.performance` is disabled (`getFirebasePerformanceSync`
8
- * never resolves an instance).
5
+ * `web_lcp`, `web_ttfb`, `web_inp`), alongside Firebase Performance's own
6
+ * automatic page-load/network traces. No-ops if `firebaseAuth.performance`
7
+ * is disabled (`getFirebasePerformanceSync` never resolves an instance).
9
8
  */
10
9
  export default function AutoFirebasePerformanceEvents(): null;
@@ -1,7 +1,5 @@
1
1
  'use client';
2
- import { usePathname } from 'next/navigation';
3
2
  import { useReportWebVitals } from 'next/web-vitals';
4
- import { useEffect, useRef } from 'react';
5
3
  import reportError from '../../../error_handling/report_error';
6
4
  import { getFirebaseAuthClient, getFirebasePerformanceSync } from '../firebase_client';
7
5
  /**
@@ -28,84 +26,18 @@ async function recordFirebaseTrace(name, durationMs, attributes, metrics) {
28
26
  });
29
27
  }
30
28
  }
31
- const SLOW_RESOURCE_THRESHOLD_MS = 1000;
32
29
  /**
33
30
  * Auto-rendered alongside `FirebaseAuthClientProvider` when
34
31
  * `firebaseAuth.performance` isn't `false` — records Firebase Performance
35
32
  * custom traces for Web Vitals metrics (`web_cls`, `web_fcp`, `web_fid`,
36
- * `web_lcp`, `web_ttfb`, `web_inp`) and SPA route changes (`route_change`),
37
- * alongside Firebase Performance's own automatic page-load/network traces.
38
- * No-ops if `firebaseAuth.performance` is disabled (`getFirebasePerformanceSync`
39
- * never resolves an instance).
33
+ * `web_lcp`, `web_ttfb`, `web_inp`), alongside Firebase Performance's own
34
+ * automatic page-load/network traces. No-ops if `firebaseAuth.performance`
35
+ * is disabled (`getFirebasePerformanceSync` never resolves an instance).
40
36
  */
41
37
  export default function AutoFirebasePerformanceEvents() {
42
38
  useReportWebVitals((metric) => {
43
39
  const value = Math.round(metric.name === 'CLS' ? metric.value * 1000 : metric.value);
44
40
  void recordFirebaseTrace(`web_${metric.name.toLowerCase()}`, value, { rating: metric.rating });
45
41
  });
46
- const path = usePathname();
47
- const isFirstRoute = useRef(true);
48
- const lastRouteChangeRef = useRef(Date.now());
49
- const longTaskStats = useRef({ count: 0, totalDuration: 0 });
50
- // Mount-only: registers a PerformanceObserver for long tasks (main-thread
51
- // blocks >= 50ms). Not all browsers support the 'longtask' entry type, so
52
- // this is a best-effort signal. The final route's tail of accumulated
53
- // long tasks between the last route change and unmount is intentionally
54
- // dropped rather than flushed here — this is a monitoring signal, not a
55
- // billing metric, and an occasional dropped tail sample is acceptable.
56
- useEffect(() => {
57
- if (typeof PerformanceObserver === 'undefined' || !PerformanceObserver.supportedEntryTypes?.includes('longtask'))
58
- return;
59
- const observer = new PerformanceObserver((list) => {
60
- for (const entry of list.getEntries()) {
61
- longTaskStats.current.count += 1;
62
- longTaskStats.current.totalDuration += entry.duration;
63
- }
64
- });
65
- observer.observe({ type: 'longtask', buffered: true });
66
- return () => observer.disconnect();
67
- }, []);
68
- // Mount-only: registers a PerformanceObserver for slow non-fetch/XHR
69
- // resources (scripts, images, stylesheets, fonts, etc). Firebase
70
- // Performance's own automatic network monitoring already instruments
71
- // fetch/XHR, so those are skipped here to avoid duplicate signals.
72
- // `buffered: true` also catches resources that loaded before this
73
- // component mounted (it only mounts after `AuthUserProvider`).
74
- useEffect(() => {
75
- if (typeof PerformanceObserver === 'undefined' || !PerformanceObserver.supportedEntryTypes?.includes('resource'))
76
- return;
77
- const observer = new PerformanceObserver((list) => {
78
- for (const entry of list.getEntries()) {
79
- if (entry.initiatorType === 'fetch' || entry.initiatorType === 'xmlhttprequest')
80
- continue;
81
- if (entry.duration < SLOW_RESOURCE_THRESHOLD_MS)
82
- continue;
83
- void recordFirebaseTrace('slow_resource', entry.duration, {
84
- initiator_type: entry.initiatorType,
85
- resource: entry.name.slice(-100),
86
- }, { transfer_size_bytes: Math.round(entry.transferSize ?? 0) });
87
- }
88
- });
89
- observer.observe({ type: 'resource', buffered: true });
90
- return () => observer.disconnect();
91
- }, []);
92
- useEffect(() => {
93
- const now = Date.now();
94
- const duration = now - lastRouteChangeRef.current;
95
- lastRouteChangeRef.current = now;
96
- if (isFirstRoute.current) {
97
- isFirstRoute.current = false;
98
- return;
99
- }
100
- // Approximates navigation duration as time between path-change commits —
101
- // App Router exposes no public "navigation start" event this package
102
- // can hook into, so this is not a precise navigation timing.
103
- void recordFirebaseTrace('route_change', duration, { path: path.slice(-100) });
104
- const { count, totalDuration } = longTaskStats.current;
105
- longTaskStats.current = { count: 0, totalDuration: 0 };
106
- if (count > 0) {
107
- void recordFirebaseTrace('route_long_tasks', totalDuration, { path: path.slice(-100) }, { long_task_count: count });
108
- }
109
- }, [path]);
110
42
  return null;
111
43
  }
@@ -160,6 +160,7 @@ export async function refreshIdToken(apiKey, refreshToken, options) {
160
160
  method: 'POST',
161
161
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
162
162
  body: `grant_type=refresh_token&refresh_token=${encodeURIComponent(refreshToken)}`,
163
+ cache: 'no-store',
163
164
  });
164
165
  if (!res.ok) {
165
166
  if (res.status === 400) {
@@ -499,5 +500,7 @@ function buildRedirect(baseResponse, url) {
499
500
  const redirectResponse = NextResponse.redirect(url);
500
501
  baseResponse.cookies.getAll().forEach((cookie) => redirectResponse.cookies.set(cookie));
501
502
  baseResponse.headers.forEach((value, key) => redirectResponse.headers.set(key, value));
503
+ // Explicitly prevent OpenNext/Cloudflare from caching these auth redirects.
504
+ redirectResponse.headers.set('Cache-Control', 'private, no-cache, no-store, max-age=0, must-revalidate');
502
505
  return redirectResponse;
503
506
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudflare-next-intl",
3
- "version": "0.8.32",
3
+ "version": "0.8.33",
4
4
  "description": "Optimized Next Intl Package Special for App Router and Cloudflare",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",