cloudflare-next-intl 0.10.17 → 0.10.18
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/README.md +2 -3
- package/dist/src/cookie_consent/client/components/clarity_script.js +28 -10
- package/dist/src/firebase_auth/client/firebase_client.js +5 -13
- package/dist/src/server/components/helper_script.d.ts +3 -1
- package/dist/src/server/components/helper_script.js +6 -2
- package/dist/src/types/types.d.ts +0 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -409,7 +409,7 @@ export default async function RootLayout({ children, params }) {
|
|
|
409
409
|
return (
|
|
410
410
|
<html lang={locale}>
|
|
411
411
|
<head>
|
|
412
|
-
<IntlHelperScript />
|
|
412
|
+
<IntlHelperScript locale={locale} />
|
|
413
413
|
</head>
|
|
414
414
|
<body>
|
|
415
415
|
<IntlProvider language={locale}>{children}</IntlProvider>
|
|
@@ -516,8 +516,7 @@ Features include:
|
|
|
516
516
|
- `createForgotPasswordAction(locale, actionCodeSettings?)`: Accepts optional Firebase `AuthActionCodeSettings` (e.g. `url` redirect link).
|
|
517
517
|
- `sendVerificationEmail(actionCodeSettings?)` on `useAuthUser()`: Custom action email settings when resending email verification.
|
|
518
518
|
- `followSameOriginContinueUrl`: Automatically forwards emailed action links with `continueUrl` to the specified path (or external URL) directly from `intlMiddleware` (default `true`; set `false` on `firebaseAuth` config to disable). If `continueUrl` points to home root (`/`), it resolves to `actionLinkPath` (if set) or the mode target path (e.g. `/reset-password`).
|
|
519
|
-
- `appCheck`: Firebase App Check integration supporting reCAPTCHA Enterprise (`recaptchaEnterpriseSiteKey`) and reCAPTCHA v3 (`recaptchaV3SiteKey`). For reCAPTCHA v3, defaults to a `CustomProvider` using an explicit `render=explicit` script tag to avoid iframe/webworker CDN integrity issues in private windows (`useExplicitRecaptchaScript: false` to opt out).
|
|
520
|
-
- `lazyInit`: defers App Check's own initialization (not just the script above) to that same first-need moment instead of running it as part of every `getFirebaseAuthClient()` call. Off by default — App Check reads the App Check provider off the app per-request and silently omits the `X-Firebase-AppCheck` header if it isn't registered yet, so deferring is only safe when App Check enforcement is off for every product this app calls (Auth, Firestore, Functions, etc).
|
|
519
|
+
- `appCheck`: Firebase App Check integration supporting reCAPTCHA Enterprise (`recaptchaEnterpriseSiteKey`) and reCAPTCHA v3 (`recaptchaV3SiteKey`). For reCAPTCHA v3, defaults to a `CustomProvider` using an explicit `render=explicit` script tag to avoid iframe/webworker CDN integrity issues in private windows (`useExplicitRecaptchaScript: false` to opt out). Both the script and App Check's own initialization are always deferred to first actual need (the first `getAppCheckToken()`/token mint) rather than run as part of every `getFirebaseAuthClient()` call, so a page that never mints a token never pays reCAPTCHA's ~345KB cost. **Note:** because of that deferral, a request made through `getFirebaseAuthClient()`'s `auth` before anything has called `getAppCheckToken()` (e.g. a sign-in call) goes out without an `X-Firebase-AppCheck` header — only a concern if App Check enforcement is on for Auth/Firestore/Functions. Supports server-side token minting via service accounts.
|
|
521
520
|
- `resolveOptionalAuthUser()` (`cloudflare-next-intl/resolveOptionalAuthUser`): best-effort variant of `getAuthUser()` for callers that want to *attach* the current user when one happens to be known — error/telemetry reporting, analytics, logging — without failing or changing behavior when no request/session context is available. Swallows every failure and resolves `{ user: null }` instead of throwing. Use `getAuthUser()` (not this) whenever your own output actually depends on who's signed in — `checkDynamicPages` (below) treats `getAuthUser()`/`useAuthUser()`/`withUserDb()` as page-blocking dynamic-API signals but does not follow into this helper, so it's also the way to read "whoever's signed in, if anyone" from a page or a module it imports without forcing that page dynamic.
|
|
522
521
|
- `resolveErrorReportingUser(useAuthUser?)` (same subpath): gated form of `resolveOptionalAuthUser()` for an `onError` sink — pass `ErrorHandlingParams.useAuthUser` straight through. Defaults to `false`: when not `true`, resolves `{ user: null }` immediately without calling `getAuthUser()` at all, so a page reached only through your `onError` sink's default path stays static-eligible. A specific `reportError({ ..., useAuthUser: true })` call site opts in per-call when it actually wants the user on that report.
|
|
523
522
|
|
|
@@ -10,16 +10,34 @@ function getClarityModule() {
|
|
|
10
10
|
}
|
|
11
11
|
export default function ClarityScript({ projectId }) {
|
|
12
12
|
useEffect(() => {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
13
|
+
let handle;
|
|
14
|
+
let timeout;
|
|
15
|
+
const init = () => {
|
|
16
|
+
getClarityModule()
|
|
17
|
+
.then(({ default: Clarity }) => {
|
|
18
|
+
Clarity.init(projectId);
|
|
19
|
+
Clarity.consent();
|
|
20
|
+
})
|
|
21
|
+
.catch((error) => void reportError(undefined, {
|
|
22
|
+
error,
|
|
23
|
+
classOrMethodName: 'ClarityScript',
|
|
24
|
+
isClient: true,
|
|
25
|
+
}));
|
|
26
|
+
};
|
|
27
|
+
if (typeof window !== 'undefined' && 'requestIdleCallback' in window) {
|
|
28
|
+
handle = window.requestIdleCallback(init, { timeout: 3000 });
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
timeout = setTimeout(init, 1500);
|
|
32
|
+
}
|
|
33
|
+
return () => {
|
|
34
|
+
if (handle !== undefined && typeof window !== 'undefined' && 'cancelIdleCallback' in window) {
|
|
35
|
+
window.cancelIdleCallback(handle);
|
|
36
|
+
}
|
|
37
|
+
if (timeout !== undefined) {
|
|
38
|
+
clearTimeout(timeout);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
23
41
|
}, [projectId]);
|
|
24
42
|
return null;
|
|
25
43
|
}
|
|
@@ -122,12 +122,15 @@ async function initializeFirebaseAppCheck(app, appCheckConfig) {
|
|
|
122
122
|
}
|
|
123
123
|
const APP_CHECK_TOKEN_TIMEOUT_MS = 10000;
|
|
124
124
|
let appCheckInitPromise;
|
|
125
|
-
function
|
|
125
|
+
async function ensureAppCheck() {
|
|
126
126
|
if (appCheckInitPromise)
|
|
127
127
|
return appCheckInitPromise;
|
|
128
128
|
const appCheckConfig = config.firebaseAuth?.appCheck;
|
|
129
129
|
if (!appCheckConfig || typeof window === 'undefined')
|
|
130
|
-
return
|
|
130
|
+
return;
|
|
131
|
+
const { app } = await getFirebaseAuthClient();
|
|
132
|
+
if (appCheckInitPromise)
|
|
133
|
+
return appCheckInitPromise;
|
|
131
134
|
appCheckInitPromise = (async () => {
|
|
132
135
|
try {
|
|
133
136
|
cachedAppCheck = await initializeFirebaseAppCheck(app, appCheckConfig);
|
|
@@ -138,15 +141,6 @@ function initAppCheckOnce(app) {
|
|
|
138
141
|
})();
|
|
139
142
|
return appCheckInitPromise;
|
|
140
143
|
}
|
|
141
|
-
async function ensureAppCheck() {
|
|
142
|
-
if (appCheckInitPromise)
|
|
143
|
-
return appCheckInitPromise;
|
|
144
|
-
const appCheckConfig = config.firebaseAuth?.appCheck;
|
|
145
|
-
if (!appCheckConfig || typeof window === 'undefined')
|
|
146
|
-
return;
|
|
147
|
-
const { app } = await getFirebaseAuthClient();
|
|
148
|
-
return initAppCheckOnce(app);
|
|
149
|
-
}
|
|
150
144
|
export async function getAppCheckToken() {
|
|
151
145
|
await ensureAppCheck().catch(() => undefined);
|
|
152
146
|
if (!cachedAppCheck)
|
|
@@ -189,8 +183,6 @@ export async function getFirebaseAuthClient() {
|
|
|
189
183
|
measurementId: fa.measurementId,
|
|
190
184
|
};
|
|
191
185
|
const app = getApps().length ? getApp() : initializeApp(firebaseConfig);
|
|
192
|
-
if (!fa.appCheck?.lazyInit)
|
|
193
|
-
await initAppCheckOnce(app);
|
|
194
186
|
if (perfModule) {
|
|
195
187
|
cachedPerformance = perfModule.initializePerformance(app, { instrumentationEnabled: false });
|
|
196
188
|
}
|
|
@@ -1,2 +1,4 @@
|
|
|
1
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>";
|
|
2
|
-
export default function HelperScript(
|
|
2
|
+
export default function HelperScript({ locale }: {
|
|
3
|
+
locale?: string;
|
|
4
|
+
}): Component | null;
|
|
@@ -6,9 +6,13 @@ import { defaultStaleDeployPatterns } from "../../error_handling/is_stale_deploy
|
|
|
6
6
|
const isDev = process.env.NODE_ENV === 'development';
|
|
7
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>';
|
|
8
8
|
const secureCookieAttribute = isDev ? '+ " Secure;"' : '';
|
|
9
|
-
export default function HelperScript() {
|
|
9
|
+
export default function HelperScript({ locale }) {
|
|
10
10
|
const reloadHtml = config.errorHandling?.staleDeployReloadHtml ?? defaultReloadHtml;
|
|
11
|
-
|
|
11
|
+
const analytics = config.cookieConsent?.analytics;
|
|
12
|
+
const hasGoogle = !!(analytics?.googleAnalyticsId || analytics?.googleAdsId || analytics?.googleAdSenseId);
|
|
13
|
+
const hasClarity = !!analytics?.clarityProjectId;
|
|
14
|
+
const hasFirebase = !!config.firebaseAuth;
|
|
15
|
+
return _jsxs(_Fragment, { children: [locale && _jsx("meta", { httpEquiv: "Content-Language", content: locale }), hasGoogle && _jsx("link", { rel: "dns-prefetch", href: "https://www.googletagmanager.com" }), hasClarity && _jsx("link", { rel: "dns-prefetch", href: "https://www.clarity.ms" }), hasClarity && _jsx("link", { rel: "dns-prefetch", href: "https://scripts.clarity.ms" }), hasFirebase && _jsx("link", { rel: "dns-prefetch", href: "https://firebaseinstallations.googleapis.com" }), !isDev &&
|
|
12
16
|
_jsx("script", { id: "stale-deploy-early-catch", dangerouslySetInnerHTML: {
|
|
13
17
|
__html: `(function() {
|
|
14
18
|
try {
|
|
@@ -165,7 +165,6 @@ export interface FirebaseAppCheckConfig {
|
|
|
165
165
|
recaptchaV3SiteKey?: string;
|
|
166
166
|
recaptchaEnterpriseSiteKey?: string;
|
|
167
167
|
useExplicitRecaptchaScript?: boolean;
|
|
168
|
-
lazyInit?: boolean;
|
|
169
168
|
debugToken?: boolean | string;
|
|
170
169
|
isTokenAutoRefreshEnabled?: boolean;
|
|
171
170
|
clientEmail: string;
|