cloudflare-next-intl 0.10.19 → 0.10.20

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 CHANGED
@@ -516,7 +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). 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.
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). When `appCheck` is configured, `getFirebaseAuthClient()` waits for App Check to initialize before returning, so every request made through its `auth` (sign-in included) carries an `X-Firebase-AppCheck` header and passes App Check enforcement. The trade-off: App Check (and, with token auto-refresh on, the reCAPTCHA script) now starts on the first `getFirebaseAuthClient()` call instead of the first token mint. If App Check initialization fails, the client is still returned, just without App Check. Supports server-side token minting via service accounts.
520
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.
521
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.
522
522
 
@@ -128,7 +128,7 @@ async function ensureAppCheck() {
128
128
  const appCheckConfig = config.firebaseAuth?.appCheck;
129
129
  if (!appCheckConfig || typeof window === 'undefined')
130
130
  return;
131
- const { app } = await getFirebaseAuthClient();
131
+ const { app } = await loadFirebaseAuthClient();
132
132
  if (appCheckInitPromise)
133
133
  return appCheckInitPromise;
134
134
  appCheckInitPromise = (async () => {
@@ -160,7 +160,7 @@ export async function getAppCheckToken() {
160
160
  }
161
161
  let cached;
162
162
  let cachedPromise;
163
- export async function getFirebaseAuthClient() {
163
+ async function loadFirebaseAuthClient() {
164
164
  requireFirebaseAuthConfig(config.firebaseAuth);
165
165
  if (cached)
166
166
  return cached;
@@ -204,6 +204,11 @@ export async function getFirebaseAuthClient() {
204
204
  }
205
205
  return cachedPromise;
206
206
  }
207
+ export async function getFirebaseAuthClient() {
208
+ const client = await loadFirebaseAuthClient();
209
+ await ensureAppCheck().catch(() => undefined);
210
+ return client;
211
+ }
207
212
  export function getFirebaseAuthClientSync() {
208
213
  return cached;
209
214
  }
@@ -5,9 +5,7 @@ import requireFirebaseAuthConfig from '../require_config.js';
5
5
  import { defaultAppCheckTokenCookieName, defaultRefreshTokenCookieName, defaultSessionCookieName, isIdTokenExpired, refreshIdToken, sessionCookieOptions } from '../middleware/update_session.js';
6
6
  import reportError from '../../error_handling/report_error.js';
7
7
  import mintServerAppCheckToken from './mint_server_app_check_token.js';
8
- let baseAppReady;
9
- let firebaseAppModuleReady;
10
- let firebaseAuthModuleReady;
8
+ const baseAppName = 'firebase-auth-server-base';
11
9
  function persistRefreshedSession(cookieStore, sessionCookieName, refreshTokenCookieName, idToken, refreshToken) {
12
10
  const options = sessionCookieOptions(config.firebaseAuth, true);
13
11
  try {
@@ -38,10 +36,10 @@ export const getAuthenticatedAppForUser = cache(async function getAuthenticatedA
38
36
  const appCheckToken = cookieStore.get(appCheckTokenCookieName)?.value
39
37
  ?? await mintServerAppCheckToken(fa.projectId, fa.apiKey, fa.appCheck);
40
38
  const attempt = async (idToken) => {
41
- firebaseAppModuleReady ?? (firebaseAppModuleReady = import('@firebase/app'));
42
- firebaseAuthModuleReady ?? (firebaseAuthModuleReady = import('@firebase/auth'));
43
- const { initializeApp, initializeServerApp } = await firebaseAppModuleReady;
44
- const { getAuth } = await firebaseAuthModuleReady;
39
+ const [{ getApps, initializeApp, initializeServerApp }, { getAuth }] = await Promise.all([
40
+ import('@firebase/app'),
41
+ import('@firebase/auth'),
42
+ ]);
45
43
  const firebaseConfig = {
46
44
  apiKey: fa.apiKey,
47
45
  authDomain: fa.authDomain,
@@ -51,8 +49,8 @@ export const getAuthenticatedAppForUser = cache(async function getAuthenticatedA
51
49
  appId: fa.appId,
52
50
  measurementId: fa.measurementId,
53
51
  };
54
- baseAppReady ?? (baseAppReady = (async () => initializeApp(firebaseConfig, 'firebase-auth-server-base'))());
55
- const baseApp = await baseAppReady;
52
+ const baseApp = getApps().find(app => app.name === baseAppName)
53
+ ?? initializeApp(firebaseConfig, baseAppName);
56
54
  const firebaseServerApp = initializeServerApp(baseApp, { authIdToken: idToken, appCheckToken });
57
55
  const auth = getAuth(firebaseServerApp);
58
56
  await auth.authStateReady();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudflare-next-intl",
3
- "version": "0.10.19",
3
+ "version": "0.10.20",
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",