cloudflare-next-intl 0.6.5 → 0.6.6
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/dist/src/client/components/client_provider.js +2 -0
- package/dist/src/error_handling/index.d.ts +1 -0
- package/dist/src/error_handling/index.js +1 -0
- package/dist/src/error_handling/install_global_error_override.d.ts +20 -0
- package/dist/src/error_handling/install_global_error_override.js +44 -0
- package/dist/src/error_handling/report_error.d.ts +7 -3
- package/dist/src/error_handling/report_error.js +21 -10
- package/dist/src/firebase_auth/client/auth_user_provider.js +1 -1
- package/dist/src/types/types.d.ts +28 -3
- package/package.json +5 -1
|
@@ -5,6 +5,7 @@ import { createContext, useMemo } from "react";
|
|
|
5
5
|
import dynamic from "next/dynamic";
|
|
6
6
|
import config from "@intl-config";
|
|
7
7
|
import installConsoleErrorOverride from "../../error_handling/install_console_error_override";
|
|
8
|
+
import installGlobalErrorOverride from "../../error_handling/install_global_error_override";
|
|
8
9
|
export const LocaleContext = createContext(undefined);
|
|
9
10
|
// Hoisted to module scope — calling `dynamic()` inside the component body
|
|
10
11
|
// creates a brand-new component identity every render, forcing React to
|
|
@@ -22,6 +23,7 @@ export default function LocationzationClientProvider({ language, messages, initi
|
|
|
22
23
|
setLocaleCache(language);
|
|
23
24
|
setMessageForLocaleCache(language, messages);
|
|
24
25
|
installConsoleErrorOverride(config, true);
|
|
26
|
+
installGlobalErrorOverride(config);
|
|
25
27
|
// `LocaleContext.Provider` stays the outermost element here — the
|
|
26
28
|
// client `AuthUserProvider` (and its descendants calling
|
|
27
29
|
// usePathname()/useLocale()) must render as a CHILD of it, not a
|
|
@@ -3,6 +3,7 @@ export type { WithErrorHandlingOptions } from './with_error_handling';
|
|
|
3
3
|
export { default as reportError } from './report_error';
|
|
4
4
|
export type { ReportErrorConfig } from './report_error';
|
|
5
5
|
export { default as installConsoleErrorOverride } from './install_console_error_override';
|
|
6
|
+
export { default as installGlobalErrorOverride } from './install_global_error_override';
|
|
6
7
|
export { default as stringifyUnknown } from './stringify_unknown';
|
|
7
8
|
export { default as formatErrorMessage } from './format_error_message';
|
|
8
9
|
export { defaultIgnoredConsoleErrors } from './default_ignored_console_errors';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { default as withErrorHandling } from './with_error_handling';
|
|
2
2
|
export { default as reportError } from './report_error';
|
|
3
3
|
export { default as installConsoleErrorOverride } from './install_console_error_override';
|
|
4
|
+
export { default as installGlobalErrorOverride } from './install_global_error_override';
|
|
4
5
|
export { default as stringifyUnknown } from './stringify_unknown';
|
|
5
6
|
export { default as formatErrorMessage } from './format_error_message';
|
|
6
7
|
export { defaultIgnoredConsoleErrors } from './default_ignored_console_errors';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ReportErrorConfig } from './report_error';
|
|
2
|
+
/**
|
|
3
|
+
* Client-only: attaches `window.addEventListener('error'|'unhandledrejection', ...)`
|
|
4
|
+
* handlers that route through `config.errorHandling.onError`/`reportError` —
|
|
5
|
+
* catches uncaught exceptions and unhandled promise rejections that never go
|
|
6
|
+
* through `console.error` at all (unlike `installConsoleErrorOverride`),
|
|
7
|
+
* e.g. Next.js's own internal "Failed to fetch RSC payload" navigation
|
|
8
|
+
* fallback. Neither handler calls `event.preventDefault()` — the browser's
|
|
9
|
+
* own default handling (logging to the console) still happens, nothing is
|
|
10
|
+
* swallowed. Safe to call more than once (a no-op after the first call in
|
|
11
|
+
* this JS realm). Takes effect when `config.errorHandling.overrideWindowErrors`
|
|
12
|
+
* is `true`, or when it's omitted and `overrideConsoleError` is `true` (so
|
|
13
|
+
* enabling `overrideConsoleError` alone catches everything by default; pass
|
|
14
|
+
* `overrideWindowErrors: false` explicitly to opt out of just this part).
|
|
15
|
+
* No-op when `window` doesn't exist (server-side).
|
|
16
|
+
*
|
|
17
|
+
* @param config Pass the relevant slices of your `RoutingConfig` directly —
|
|
18
|
+
* `{ errorHandling: config.errorHandling, generate: config.generate }`.
|
|
19
|
+
*/
|
|
20
|
+
export default function installGlobalErrorOverride(config: ReportErrorConfig | undefined): void;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import reportError from './report_error';
|
|
2
|
+
import stringifyUnknown from './stringify_unknown';
|
|
3
|
+
/**
|
|
4
|
+
* Client-only: attaches `window.addEventListener('error'|'unhandledrejection', ...)`
|
|
5
|
+
* handlers that route through `config.errorHandling.onError`/`reportError` —
|
|
6
|
+
* catches uncaught exceptions and unhandled promise rejections that never go
|
|
7
|
+
* through `console.error` at all (unlike `installConsoleErrorOverride`),
|
|
8
|
+
* e.g. Next.js's own internal "Failed to fetch RSC payload" navigation
|
|
9
|
+
* fallback. Neither handler calls `event.preventDefault()` — the browser's
|
|
10
|
+
* own default handling (logging to the console) still happens, nothing is
|
|
11
|
+
* swallowed. Safe to call more than once (a no-op after the first call in
|
|
12
|
+
* this JS realm). Takes effect when `config.errorHandling.overrideWindowErrors`
|
|
13
|
+
* is `true`, or when it's omitted and `overrideConsoleError` is `true` (so
|
|
14
|
+
* enabling `overrideConsoleError` alone catches everything by default; pass
|
|
15
|
+
* `overrideWindowErrors: false` explicitly to opt out of just this part).
|
|
16
|
+
* No-op when `window` doesn't exist (server-side).
|
|
17
|
+
*
|
|
18
|
+
* @param config Pass the relevant slices of your `RoutingConfig` directly —
|
|
19
|
+
* `{ errorHandling: config.errorHandling, generate: config.generate }`.
|
|
20
|
+
*/
|
|
21
|
+
export default function installGlobalErrorOverride(config) {
|
|
22
|
+
const enabled = config?.errorHandling?.overrideWindowErrors ?? config?.errorHandling?.overrideConsoleError;
|
|
23
|
+
if (enabled !== true)
|
|
24
|
+
return;
|
|
25
|
+
if (typeof window === 'undefined')
|
|
26
|
+
return;
|
|
27
|
+
if (window.__isGlobalErrorOverrideInstalled)
|
|
28
|
+
return;
|
|
29
|
+
window.__isGlobalErrorOverrideInstalled = true;
|
|
30
|
+
window.addEventListener('error', (event) => {
|
|
31
|
+
void reportError(config, {
|
|
32
|
+
error: event.error ?? stringifyUnknown(event.message, true),
|
|
33
|
+
classOrMethodName: 'Global Window Error Handler',
|
|
34
|
+
isClient: true,
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
window.addEventListener('unhandledrejection', (event) => {
|
|
38
|
+
void reportError(config, {
|
|
39
|
+
error: event.reason,
|
|
40
|
+
classOrMethodName: 'Global Unhandled Rejection Handler',
|
|
41
|
+
isClient: true,
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
}
|
|
@@ -4,13 +4,17 @@ export interface ReportErrorConfig {
|
|
|
4
4
|
generate?: GenerateRoutingConfig;
|
|
5
5
|
}
|
|
6
6
|
/**
|
|
7
|
-
* Reports `params
|
|
8
|
-
* `console.error(
|
|
7
|
+
* Reports `params`: logs `params.formattedMessage` via the real
|
|
8
|
+
* `console.error` (unless `config.errorHandling.logToConsole` is `false`)
|
|
9
|
+
* AND calls `config.errorHandling.onError` when set — both run, not one
|
|
10
|
+
* instead of the other, so wiring `onError` (Sentry, Telegram, etc) never
|
|
11
|
+
* silently loses the console output. Skips reporting entirely when
|
|
9
12
|
* `config.errorHandling.enable === false`, `params.consent` is set and not
|
|
10
13
|
* `true` (reporting to a third party without cookie consent can itself be
|
|
11
14
|
* GDPR-relevant), or dedup throttles it (on by default — see
|
|
12
15
|
* `errorHandling.dedup`/`throttleMs`/`resetDedup`). Never throws — a broken
|
|
13
|
-
*
|
|
16
|
+
* `onError` must not mask the original error (falls back to logging via the
|
|
17
|
+
* real console instead).
|
|
14
18
|
*
|
|
15
19
|
* Always overwrites `params.formattedMessage` with a fresh
|
|
16
20
|
* `formatErrorMessage(params)` before reporting — a human-readable one-line
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import formatErrorMessage from './format_error_message';
|
|
2
2
|
import stringifyUnknown from './stringify_unknown';
|
|
3
3
|
const DEFAULT_THROTTLE_MS = 5000;
|
|
4
|
+
// Captured once at module load — BEFORE `installConsoleErrorOverride` can
|
|
5
|
+
// ever patch `console.error` — so `callOnError`'s own fallback/always-log
|
|
6
|
+
// path calls the real console, never the override. Calling a possibly-
|
|
7
|
+
// patched `console.error` here would loop straight back into
|
|
8
|
+
// `reportError` (the override's job is to call `reportError`), producing
|
|
9
|
+
// a duplicate (or, if `onError` itself throws, an infinite) report.
|
|
10
|
+
const originalConsoleError = console.error.bind(console);
|
|
4
11
|
// Module-scope dedup state — safe by default only because a fresh JS realm
|
|
5
12
|
// (isolate/Worker instance) starts with it cleared. In a long-lived server
|
|
6
13
|
// process reused across many requests, pass `resetDedup: true` on the first
|
|
@@ -13,26 +20,30 @@ function buildDedupKey(params) {
|
|
|
13
20
|
}
|
|
14
21
|
async function callOnError(config, params) {
|
|
15
22
|
const paramsWithFormattedMessage = { ...params, formattedMessage: formatErrorMessage(params) };
|
|
16
|
-
|
|
17
|
-
|
|
23
|
+
if (config?.logToConsole !== false) {
|
|
24
|
+
originalConsoleError(paramsWithFormattedMessage.formattedMessage);
|
|
25
|
+
}
|
|
26
|
+
if (config?.onError) {
|
|
27
|
+
try {
|
|
18
28
|
await config.onError(paramsWithFormattedMessage);
|
|
19
29
|
}
|
|
20
|
-
|
|
21
|
-
|
|
30
|
+
catch {
|
|
31
|
+
originalConsoleError(paramsWithFormattedMessage.formattedMessage);
|
|
22
32
|
}
|
|
23
33
|
}
|
|
24
|
-
catch {
|
|
25
|
-
console.error(paramsWithFormattedMessage.formattedMessage);
|
|
26
|
-
}
|
|
27
34
|
}
|
|
28
35
|
/**
|
|
29
|
-
* Reports `params
|
|
30
|
-
* `console.error(
|
|
36
|
+
* Reports `params`: logs `params.formattedMessage` via the real
|
|
37
|
+
* `console.error` (unless `config.errorHandling.logToConsole` is `false`)
|
|
38
|
+
* AND calls `config.errorHandling.onError` when set — both run, not one
|
|
39
|
+
* instead of the other, so wiring `onError` (Sentry, Telegram, etc) never
|
|
40
|
+
* silently loses the console output. Skips reporting entirely when
|
|
31
41
|
* `config.errorHandling.enable === false`, `params.consent` is set and not
|
|
32
42
|
* `true` (reporting to a third party without cookie consent can itself be
|
|
33
43
|
* GDPR-relevant), or dedup throttles it (on by default — see
|
|
34
44
|
* `errorHandling.dedup`/`throttleMs`/`resetDedup`). Never throws — a broken
|
|
35
|
-
*
|
|
45
|
+
* `onError` must not mask the original error (falls back to logging via the
|
|
46
|
+
* real console instead).
|
|
36
47
|
*
|
|
37
48
|
* Always overwrites `params.formattedMessage` with a fresh
|
|
38
49
|
* `formatErrorMessage(params)` before reporting — a human-readable one-line
|
|
@@ -183,7 +183,7 @@ export default function AuthUserProvider({ initialUser = null, children }) {
|
|
|
183
183
|
}
|
|
184
184
|
finally {
|
|
185
185
|
await clearSession(sessionCookieName, refreshTokenCookieName);
|
|
186
|
-
|
|
186
|
+
router.push(fa.redirectAuthPath);
|
|
187
187
|
}
|
|
188
188
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
189
189
|
}, [fa.redirectAuthPath, sessionCookieName, refreshTokenCookieName]);
|
|
@@ -167,11 +167,22 @@ export interface ErrorHandlingRoutingConfig {
|
|
|
167
167
|
*/
|
|
168
168
|
enable?: boolean;
|
|
169
169
|
/**
|
|
170
|
-
* Called with the caught error whenever one is reported
|
|
171
|
-
* `console.error
|
|
172
|
-
*
|
|
170
|
+
* Called with the caught error whenever one is reported, in ADDITION to
|
|
171
|
+
* the always-on `console.error(params.formattedMessage)` (see
|
|
172
|
+
* `logToConsole` to disable that). Use this to wire your own
|
|
173
|
+
* error-tracking/logging transport (Sentry, Telegram, etc) alongside the
|
|
174
|
+
* console log, not instead of it. Omit to just log to the console.
|
|
173
175
|
*/
|
|
174
176
|
onError?: (params: ErrorHandlingParams) => void | Promise<void>;
|
|
177
|
+
/**
|
|
178
|
+
* Whether `reportError` also logs `params.formattedMessage` via the
|
|
179
|
+
* real, unpatched `console.error` (captured at module load, before
|
|
180
|
+
* `installConsoleErrorOverride` can touch it — so this never loops back
|
|
181
|
+
* into `reportError` even when the override is installed). Defaults to
|
|
182
|
+
* `true`. Set `false` if `onError` is your only sink and you don't want
|
|
183
|
+
* console output at all.
|
|
184
|
+
*/
|
|
185
|
+
logToConsole?: boolean;
|
|
175
186
|
/**
|
|
176
187
|
* Whether `reportError`/`withErrorHandling` replace the global
|
|
177
188
|
* `console.error` so every `console.error(...)` call in your app is
|
|
@@ -201,6 +212,20 @@ export interface ErrorHandlingRoutingConfig {
|
|
|
201
212
|
* substring match.
|
|
202
213
|
*/
|
|
203
214
|
ignoreConsoleError?: (message: string) => boolean;
|
|
215
|
+
/**
|
|
216
|
+
* Whether the client `LocationzationClientProvider` also installs
|
|
217
|
+
* `window.addEventListener('error'|'unhandledrejection', ...)` handlers
|
|
218
|
+
* that route through `onError`/`reportError` the same way
|
|
219
|
+
* `overrideConsoleError` does for `console.error(...)` calls. Catches
|
|
220
|
+
* uncaught exceptions and unhandled promise rejections that never go
|
|
221
|
+
* through `console.error` at all — e.g. Next.js's own internal
|
|
222
|
+
* "Failed to fetch RSC payload" navigation-fallback error. Defaults to
|
|
223
|
+
* `overrideConsoleError`'s value (so setting just `overrideConsoleError:
|
|
224
|
+
* true` catches everything by default) — pass `false` explicitly to
|
|
225
|
+
* enable console overriding without the window listeners. No-op on the
|
|
226
|
+
* server (no `window` there).
|
|
227
|
+
*/
|
|
228
|
+
overrideWindowErrors?: boolean;
|
|
204
229
|
/**
|
|
205
230
|
* Dedup: `reportError` skips reporting an error whose key (`dedupKey`,
|
|
206
231
|
* or a built-in key derived from `classOrMethodName`/`error`/`params`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cloudflare-next-intl",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.6",
|
|
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",
|
|
@@ -148,6 +148,10 @@
|
|
|
148
148
|
"types": "./dist/src/error_handling/install_console_error_override.d.ts",
|
|
149
149
|
"import": "./dist/src/error_handling/install_console_error_override.js"
|
|
150
150
|
},
|
|
151
|
+
"./installGlobalErrorOverride": {
|
|
152
|
+
"types": "./dist/src/error_handling/install_global_error_override.d.ts",
|
|
153
|
+
"import": "./dist/src/error_handling/install_global_error_override.js"
|
|
154
|
+
},
|
|
151
155
|
"./stringifyUnknown": {
|
|
152
156
|
"types": "./dist/src/error_handling/stringify_unknown.d.ts",
|
|
153
157
|
"import": "./dist/src/error_handling/stringify_unknown.js"
|