cloudflare-next-intl 0.9.18 → 0.9.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
@@ -657,7 +657,7 @@ export default function GlobalError({
657
657
  }
658
658
  ```
659
659
 
660
- - `isStaleDeployError(error: unknown, patterns?: readonly string[]): boolean`: Returns `true` if the error indicates a missing chunk, failed fetch, dynamically imported module failure, CSS chunk failure, closed connection, corrupted RSC payload, hydration error #412 from a stale deployment, or an aborted stream missing an error value (`undefined`). Defaults to `defaultStaleDeployPatterns` (or patterns configured in `intl-config.ts` via `errorHandling.staleDeployPatterns`).
660
+ - `isStaleDeployError(error: unknown, patterns?: readonly string[]): boolean`: Returns `true` if the error indicates a missing chunk, failed fetch, dynamically imported module failure, CSS chunk failure, closed connection, corrupted RSC payload, hydration error #412 from a stale deployment, an unhandled `UnrecognizedActionError`/`server action not found` rejection, or an aborted stream missing an error value (`undefined`). Defaults to `defaultStaleDeployPatterns` (or patterns configured in `intl-config.ts` via `errorHandling.staleDeployPatterns`).
661
661
  - `setStaleDeployPatterns(patterns: readonly string[]): void`: Setter to update the active pattern list and pre-compute lowercased substrings for maximum runtime performance.
662
662
  - `getStaleDeployPatterns(): readonly string[]`: Returns the currently active pattern list.
663
663
  - `clearClientCache(): Promise<void>`: Best-effort cleanup that deletes all CacheStorage caches (`window.caches`), unregisters active Service Workers, and clears `sessionStorage`.
@@ -687,7 +687,7 @@ export default function GlobalError({
687
687
  }
688
688
  ```
689
689
 
690
- - `useStaleDeployRecovery(error: unknown, onRecover?: () => Promise<unknown>, delayMs = 5000): boolean`: Detects a stale-deploy error via `isStaleDeployError` and, **once per build id**, waits `delayMs`, runs `onRecover` (if provided) and `clearClientCache` in parallel, then reloads the page. The build id is read from `localStorage['buildId']` (set by `IntlHelperScript`'s `BUILD_ID` check) and a `sessionStorage` marker records which build id already spent its reload, so a repeat failure on the same build falls through to `false` (render your normal error UI) instead of reloading forever. A redeploy changes the build id and re-arms exactly one more attempt. **Exception:** if the build id was written within the last 60 seconds (`localStorage['buildIdSetAt']`, also set by `IntlHelperScript`), the hook recovers anyway — a stale-deploy error moments after adopting a new build is the deploy still settling, not a real failure, so the one-reload cap is bypassed for that window.
690
+ - `useStaleDeployRecovery(error: unknown, onRecover?: () => Promise<unknown>, delayMs = 5000): boolean`: Detects a stale-deploy error via `isStaleDeployError` and, **once per build id**, waits `delayMs`, runs `onRecover` (if provided) and `clearClientCache` in parallel, then reloads the page. The build id is read from `localStorage['buildId']` (set by `IntlHelperScript`'s `BUILD_ID` check) and a `sessionStorage` marker records which build id already spent its reload, so a repeat failure on the same build falls through to `false` (render your normal error UI) instead of reloading forever. A redeploy changes the build id and re-arms exactly one more attempt.
691
691
  - `shouldRecoverFromStaleDeploy(error: unknown, buildId: string, marker: string | null, recentBuild = false): boolean`: The pure predicate behind the hook, exported for testing.
692
692
  - `isRecentBuild(setAt: number | null, now: number, windowMs = 60000): boolean`: Whether `setAt` (typically `buildIdSetAt`) falls within `windowMs` of `now`.
693
693
 
@@ -8,6 +8,8 @@ export const defaultStaleDeployPatterns = [
8
8
  'minified react error #412',
9
9
  'the above error occurred in a react component',
10
10
  'the connection to the page was unexpectedly closed',
11
+ 'server action not found',
12
+ 'unrecognizedactionerror',
11
13
  ];
12
14
  let activePatterns = defaultStaleDeployPatterns;
13
15
  let activeLowercasedPatterns = defaultStaleDeployPatterns.map((p) => p.toLowerCase());
@@ -25,7 +27,7 @@ export default function isStaleDeployError(error, patterns) {
25
27
  return false;
26
28
  if (!(error instanceof Error))
27
29
  return false;
28
- if (error.name === 'ChunkLoadError')
30
+ if (error.name === 'ChunkLoadError' || error.name === 'UnrecognizedActionError')
29
31
  return true;
30
32
  const message = (error.message || '').toLowerCase();
31
33
  const list = patterns ? patterns.map((p) => p.toLowerCase()) : activeLowercasedPatterns;
@@ -1,3 +1,3 @@
1
1
  export declare function isRecentBuild(setAt: number | null, now: number, windowMs?: number): boolean;
2
- export declare function shouldRecoverFromStaleDeploy(error: unknown, buildId: string, marker: string | null, recentBuild?: boolean): boolean;
2
+ export declare function shouldRecoverFromStaleDeploy(error: unknown, buildId: string, marker: string | null, _recentBuild?: boolean): boolean;
3
3
  export default function useStaleDeployRecovery(error: unknown, onRecover?: () => Promise<unknown>, delayMs?: number): boolean;
@@ -26,8 +26,9 @@ function buildIdSetAt() {
26
26
  export function isRecentBuild(setAt, now, windowMs = RECENT_BUILD_WINDOW_MS) {
27
27
  return setAt !== null && now - setAt < windowMs;
28
28
  }
29
- export function shouldRecoverFromStaleDeploy(error, buildId, marker, recentBuild = false) {
30
- return isStaleDeployError(error) && (marker !== buildId || recentBuild);
29
+ export function shouldRecoverFromStaleDeploy(error, buildId, marker, _recentBuild = false) {
30
+ const isMarkerActive = marker !== null && marker !== '' && (buildId === 'unknown' || marker === buildId);
31
+ return isStaleDeployError(error) && !isMarkerActive;
31
32
  }
32
33
  function canRecover(error) {
33
34
  if (typeof window === 'undefined')
@@ -12,11 +12,16 @@ export function LocalTime({ format, timestampMs }) {
12
12
  }
13
13
  export function CopyButton({ text, label = 'Copy', copiedLabel = 'Copied', }) {
14
14
  const [copied, setCopied] = useState(false);
15
+ useEffect(() => {
16
+ if (!copied)
17
+ return;
18
+ const timer = setTimeout(() => setCopied(false), 1500);
19
+ return () => clearTimeout(timer);
20
+ }, [copied]);
15
21
  function handleCopy(event) {
16
22
  event.preventDefault();
17
23
  void navigator.clipboard.writeText(text).then(() => {
18
24
  setCopied(true);
19
- setTimeout(() => setCopied(false), 1500);
20
25
  });
21
26
  }
22
27
  return (_jsx("button", { type: "button", onClick: handleCopy, className: "rounded-md border border-gray-300 px-2 py-1 text-[11px] font-medium text-gray-500 hover:bg-gray-100 hover:text-gray-700 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-200", children: copied ? copiedLabel : label }));
package/llms.txt CHANGED
@@ -30,7 +30,7 @@ other subpath can be used.
30
30
  - `./vite` — `cloudflareNextIntl(options?)` / `cloudflareNextIntlPlugin`, `imageOptimizerPlugin(options?)` / `imageOptimizer`, `buildIdAsset(fileName?)`, `localeFilePlugin(options?)`, `userAgentStubPlugin()`, `cfWorkersClientStubPlugin()`: All-in-one Vite plugin required for Vinext/Cloudflare Workers environments (bundles `@locale-file/*` via eager glob, resolves `@intl-config`, stubs Node.js `user-agent` to prevent runtime `node:fs` errors, stubs `cloudflare:workers` for client builds, emits client `BUILD_ID`, and runs build-time/dev Image Optimizer with Next.js blur placeholder shimming).
31
31
  - `./image-optimizer` / `./imageOptimizer` — image optimization suite: `imageOptimizerPlugin`, `imageOptimizer`, `resolveOptions`, `resolveImageConfig`, `resolveBlurOptions`, `processImage`, `makeBlurDataURL`, `getImageBlurSvg`, `renderManifest`, `writeManifest`, `isFresh`, `loadCache`, `saveCache`, `collectImages`, `run`.
32
32
  - `./errorHandling` — error reporting & stale deploy recovery barrel: `reportError`, `withErrorHandling`, `installConsoleErrorOverride`, `installGlobalErrorOverride`, `stringifyUnknown`, `formatErrorMessage`, `defaultIgnoredConsoleErrors`, `createServerErrorAction`, `isStaleDeployError`, `defaultStaleDeployPatterns`, `setStaleDeployPatterns`, `getStaleDeployPatterns`, `clearClientCache`, `useStaleDeployRecovery`, `shouldRecoverFromStaleDeploy`, `isRecentBuild`.
33
- - `./isStaleDeployError` — `isStaleDeployError(error, patterns?)`, `setStaleDeployPatterns(patterns)`, `getStaleDeployPatterns()`: detector returning `true` for version skew / chunk load / dynamic import / hydration errors (ChunkLoadError, failed to fetch, dynamically imported module failure, loading CSS chunk, connection closed, RSC payload failure, minified error #412, or missing stream error `undefined`) with fast pre-lowercased pattern cache and intl-config integration (`errorHandling.staleDeployPatterns`).
33
+ - `./isStaleDeployError` — `isStaleDeployError(error, patterns?)`, `setStaleDeployPatterns(patterns)`, `getStaleDeployPatterns()`: detector returning `true` for version skew / chunk load / dynamic import / server action 404 / hydration errors (ChunkLoadError, UnrecognizedActionError, server action not found, failed to fetch, dynamically imported module failure, loading CSS chunk, connection closed, RSC payload failure, minified error #412, or missing stream error `undefined`) with fast pre-lowercased pattern cache and intl-config integration (`errorHandling.staleDeployPatterns`).
34
34
  - `./clearClientCache` — `clearClientCache()`: async helper wiping `window.caches`, unregistering service workers, and clearing `sessionStorage` for recovering from stale deployments.
35
35
  - `useStaleDeployRecovery(error, onRecover?, delayMs?)` (client hook, in `./errorHandling`) — once per build id (`localStorage['buildId']`, `sessionStorage` marker), waits `delayMs` (default 5000ms), runs optional `onRecover()` + `clearClientCache()` in parallel, then `window.location.reload()`. Returns whether a reload is pending, so caller renders a loading state instead of error UI. Recovers even past the one-reload cap when `localStorage['buildIdSetAt']` is <60s old (new deploy still settling). `shouldRecoverFromStaleDeploy(error, buildId, marker, recentBuild?)` and `isRecentBuild(setAt, now, windowMs?)` are the pure predicates.
36
36
  - `./createServerErrorAction` — `createServerErrorAction(action, config)`: wrapper for server actions with standardized error reporting.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudflare-next-intl",
3
- "version": "0.9.18",
3
+ "version": "0.9.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",