cloudflare-next-intl 0.9.23 → 0.9.25

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.
@@ -46,7 +46,8 @@ export function googleConsentModeBootstrapScript(config) {
46
46
  document.head.appendChild(a);
47
47
  })();`
48
48
  : '';
49
- return `window.dataLayer = window.dataLayer || [];
49
+ return `try {
50
+ window.dataLayer = window.dataLayer || [];
50
51
  function gtag(){dataLayer.push(arguments);}
51
52
  gtag('consent', 'default', {
52
53
  'ad_storage': 'denied',
@@ -58,5 +59,6 @@ gtag('consent', 'default', {
58
59
  gtag('js', new Date());
59
60
  ${configCalls}
60
61
  ${gtagLoader}
61
- ${adSenseLoader}`;
62
+ ${adSenseLoader}
63
+ } catch (e) { try { console.error('Cookie Consent Analytics Script Error:', e); } catch (e2) {} }`;
62
64
  }
@@ -1 +1,2 @@
1
+ export declare const defaultReloadHtml = "<div style=\"position:fixed;inset:0;background:#ffffff;display:flex;align-items:center;justify-content:center;z-index:9999999;\"><div style=\"width:36px;height:36px;border:3px solid #e5e7eb;border-top-color:#17181b;border-radius:50%;animation:cfni-spin 0.8s linear infinite;\"></div><style>@keyframes cfni-spin{to{transform:rotate(360deg)}}</style></div>";
1
2
  export default function HelperScript(): Component | null;
@@ -4,14 +4,17 @@ import config from "../../config/intl_config.js";
4
4
  import ClientHelperScript from "../../client/components/client_helper_script.js";
5
5
  import { defaultStaleDeployPatterns } from "../../error_handling/is_stale_deploy_error.js";
6
6
  const isDev = process.env.NODE_ENV === 'development';
7
+ export const defaultReloadHtml = '<div style="position:fixed;inset:0;background:#ffffff;display:flex;align-items:center;justify-content:center;z-index:9999999;"><div style="width:36px;height:36px;border:3px solid #e5e7eb;border-top-color:#17181b;border-radius:50%;animation:cfni-spin 0.8s linear infinite;"></div><style>@keyframes cfni-spin{to{transform:rotate(360deg)}}</style></div>';
7
8
  const appCheck = config.firebaseAuth?.appCheck;
8
9
  const shouldLoadExplicitRecaptchaScript = !!appCheck?.recaptchaV3SiteKey && appCheck.useExplicitRecaptchaScript !== false;
9
10
  const secureCookieAttribute = isDev ? '+ " Secure;"' : '';
10
11
  export default function HelperScript() {
12
+ const reloadHtml = config.errorHandling?.staleDeployReloadHtml ?? defaultReloadHtml;
11
13
  return _jsxs(_Fragment, { children: [shouldLoadExplicitRecaptchaScript &&
12
14
  _jsx("script", { src: "https://www.google.com/recaptcha/api.js?render=explicit", async: true, defer: true }), !isDev &&
13
15
  _jsx("script", { id: "stale-deploy-early-catch", dangerouslySetInnerHTML: {
14
16
  __html: `(function() {
17
+ try {
15
18
  var patterns = ${JSON.stringify(defaultStaleDeployPatterns)};
16
19
  var key = 'stale-deploy-recovery-reloaded';
17
20
  var attemptedThisLoad = false;
@@ -37,7 +40,15 @@ export default function HelperScript() {
37
40
  }
38
41
  attemptedThisLoad = true;
39
42
  sessionStorage.setItem(key, buildId);
40
- console.warn('[StaleDeploy early-catch] Reloading for buildId:', buildId);
43
+ try {
44
+ if (document.documentElement) {
45
+ document.documentElement.style.backgroundColor = '#ffffff';
46
+ }
47
+ if (document.body) {
48
+ document.body.style.backgroundColor = '#ffffff';
49
+ document.body.innerHTML = ${JSON.stringify(reloadHtml)};
50
+ }
51
+ } catch (e) {}
41
52
  try {
42
53
  var u = new URL(window.location.href);
43
54
  u.searchParams.set('_stale_reload', String(Date.now()));
@@ -53,28 +64,41 @@ export default function HelperScript() {
53
64
  window.addEventListener('unhandledrejection', function(e) {
54
65
  recover(e.reason && (e.reason.message || e.reason), 'unhandledrejection');
55
66
  });
67
+ } catch (e) { try { console.error('Stale Deploy Early Catch Script Error:', e); } catch (e2) {} }
56
68
  })();`
57
69
  } }), !isDev &&
58
70
  _jsx("script", { id: "build-id-script", children: `(async function() {
59
71
  try {
60
72
  const resp = await fetch('/BUILD_ID', { method: 'HEAD', cache: 'no-store' });
61
73
  if (resp.ok) {
62
- const BUILD_ID = resp.headers.get('ETag')?.replace(/W\\/|"/g, '');
74
+ let BUILD_ID;
75
+ try {
76
+ BUILD_ID = resp.headers.get('ETag')?.replace(/W\\/|"/g, '');
77
+ } catch (e) { BUILD_ID = undefined; }
63
78
  if(!BUILD_ID) return;
64
- console.log('Build ID:', BUILD_ID);
79
+ try { console.log('Build ID:', BUILD_ID); } catch (e) {}
65
80
 
66
- const prevBuild = localStorage.getItem('buildId');
81
+ let prevBuild;
82
+ try {
83
+ prevBuild = localStorage.getItem('buildId');
84
+ } catch (e) { prevBuild = null; }
67
85
 
68
86
  if (prevBuild !== BUILD_ID) {
69
- localStorage.setItem('buildId', BUILD_ID);
70
- localStorage.setItem('buildIdSetAt', String(Date.now()));
87
+ try {
88
+ localStorage.setItem('buildId', BUILD_ID);
89
+ localStorage.setItem('buildIdSetAt', String(Date.now()));
90
+ } catch (e) {}
71
91
  if(prevBuild){
72
- window.location.reload(true);
92
+ try {
93
+ window.location.reload(true);
94
+ } catch (e) {
95
+ try { window.location.reload(); } catch (e2) {}
96
+ }
73
97
  }
74
98
  }
75
99
  }
76
100
  } catch (e) {
77
- console.error('Check Build ID Script Error:', e);
101
+ try { console.error('Check Build ID Script Error:', e); } catch (e2) {}
78
102
  }
79
103
  })();` }), _jsx("script", { id: "intl-app-state-checker", children: `(function() {
80
104
  try {
@@ -87,16 +111,22 @@ export default function HelperScript() {
87
111
  // Use a regex to find the cookie directly, avoiding splits and loops.
88
112
  // The non-capturing group (?:^|; ) matches the start of the string or a '; '
89
113
  // to ensure we're not matching a substring of another cookie's name.
90
- const match = document.cookie.match(new RegExp(\`(?:^|; )\${name}=([^;]*)\`));
91
- return match ? decodeURIComponent(match[1]) : null;
114
+ try {
115
+ const match = document.cookie.match(new RegExp(\`(?:^|; )\${name}=([^;]*)\`));
116
+ return match ? decodeURIComponent(match[1]) : null;
117
+ } catch (e) {
118
+ return null;
119
+ }
92
120
  };
93
121
 
94
122
  function setTheme(isDark){
95
- const classList=document.documentElement.classList;
96
- // This check is efficient as it only touches the DOM when a change is needed.
97
- if (classList.contains('dark') !== isDark) {
98
- classList.toggle('dark', isDark);
99
- }
123
+ try {
124
+ const classList=document.documentElement.classList;
125
+ // This check is efficient as it only touches the DOM when a change is needed.
126
+ if (classList.contains('dark') !== isDark) {
127
+ classList.toggle('dark', isDark);
128
+ }
129
+ } catch (e) {}
100
130
  }
101
131
 
102
132
  function syncTheme(){
@@ -124,37 +154,45 @@ export default function HelperScript() {
124
154
  if (locale && locale !== '${config.defaultLocale}' && !pathname.startsWith(\`/\${locale}\`)) {
125
155
  const newPath = \`/\${locale}\${pathname === '/' ? '' : pathname}\${search}\${hash}\`;
126
156
  // Redirecting will stop further script execution on this page.
127
- window.location.href = newPath;
157
+ try {
158
+ window.location.href = newPath;
159
+ } catch (e) {}
128
160
  } else {
129
161
  const isDark = getCookie('${isDarkCookieKey}');
130
162
  if(isDark===null){
131
- const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
163
+ let prefersDark = false;
164
+ try {
165
+ prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
166
+ } catch (e) {}
132
167
  setTheme(prefersDark);
133
- document.cookie = '${isDarkCookieKey}=' +
134
- prefersDark +
135
- '; path=/; max-age=31536000; SameSite=Lax;'
136
- ${secureCookieAttribute};
168
+ try {
169
+ document.cookie = '${isDarkCookieKey}=' +
170
+ prefersDark +
171
+ '; path=/; max-age=31536000; SameSite=Lax;'
172
+ ${secureCookieAttribute};
173
+ } catch (e) {}
137
174
  }else{
138
175
  setTheme(isDark==='true');
139
176
  }
140
177
  // 3. Set up listeners for client-side navigation (only if not redirecting).
141
-
142
- // Store original history methods.
143
- const pushState = history.pushState;
144
- const replaceState = history.replaceState;
145
- const back = history.back;
178
+ try {
179
+ // Store original history methods.
180
+ const pushState = history.pushState;
181
+ const replaceState = history.replaceState;
182
+ const back = history.back;
146
183
 
147
- history.back = function (...args) {
148
- back.apply(history, args);
149
- };
150
- history.pushState = function (...args) {
151
- pushState.apply(history, args);
152
- syncTheme(); // Re-sync theme after navigation.
153
- };
154
- history.replaceState = function (...args) {
155
- replaceState.apply(history, args);
156
- syncTheme(); // Re-sync theme after state replacement.
157
- };
184
+ history.back = function (...args) {
185
+ try { back.apply(history, args); } catch (e) {}
186
+ };
187
+ history.pushState = function (...args) {
188
+ try { pushState.apply(history, args); } catch (e) {}
189
+ try { syncTheme(); } catch (e) {} // Re-sync theme after navigation.
190
+ };
191
+ history.replaceState = function (...args) {
192
+ try { replaceState.apply(history, args); } catch (e) {}
193
+ try { syncTheme(); } catch (e) {} // Re-sync theme after state replacement.
194
+ };
195
+ } catch (e) {}
158
196
  }
159
197
  } catch (e) {
160
198
  console.error('App State check Script Error:', e);
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import LinkComponent from 'next/link.js';
4
- import { forwardRef, useEffect, useState, useTransition, } from 'react';
4
+ import { forwardRef, useCallback, useEffect, useState, useTransition, } from 'react';
5
5
  import config from '../../config/intl_config.js';
6
6
  import { getLocaleCache } from '../../general/cache_variables.js';
7
7
  import { usePathname, useRouter } from 'next/navigation.js';
@@ -28,7 +28,7 @@ function CustomLinkFunction({ href, prefetch, prefetchType = 'custom', onClick,
28
28
  useEffect(() => {
29
29
  setIsNavigating(false);
30
30
  }, [pathname]);
31
- const triggerPrefetch = () => {
31
+ const triggerPrefetch = useCallback(() => {
32
32
  if (!isCustom || !urlString || urlString.startsWith('#') || prefetchedRoutes.has(urlString)) {
33
33
  return;
34
34
  }
@@ -38,13 +38,13 @@ function CustomLinkFunction({ href, prefetch, prefetchType = 'custom', onClick,
38
38
  }
39
39
  catch {
40
40
  }
41
- };
41
+ }, [isCustom, urlString, pathnames, router]);
42
42
  useEffect(() => {
43
43
  if (!isCustom)
44
44
  return;
45
- const timer = setTimeout(triggerPrefetch, 600);
45
+ const timer = setTimeout(triggerPrefetch, 500);
46
46
  return () => clearTimeout(timer);
47
- }, [urlString, isCustom]);
47
+ }, [urlString, isCustom, triggerPrefetch]);
48
48
  const handleHoverPrefetch = () => {
49
49
  if (isCustom) {
50
50
  triggerPrefetch();
@@ -64,6 +64,7 @@ export interface ErrorHandlingRoutingConfig {
64
64
  suppressClientConsoleError?: boolean;
65
65
  ignoreConsoleErrors?: readonly string[];
66
66
  staleDeployPatterns?: readonly string[];
67
+ staleDeployReloadHtml?: string;
67
68
  ignoreConsoleError?: (message: string) => boolean;
68
69
  overrideWindowErrors?: boolean;
69
70
  dedup?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudflare-next-intl",
3
- "version": "0.9.23",
3
+ "version": "0.9.25",
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",