cloudflare-next-intl 0.4.5 → 0.5.0
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/cookie_consent/client/components/clarity_script.d.ts +4 -8
- package/dist/src/cookie_consent/client/components/clarity_script.js +4 -8
- package/dist/src/cookie_consent/client/components/cookie_consent_analytics.js +4 -6
- package/dist/src/cookie_consent/gdpr_countries.d.ts +2 -2
- package/dist/src/cookie_consent/gdpr_countries.js +3 -3
- package/dist/src/server/components/server_provider.js +10 -1
- package/dist/src/types/types.d.ts +8 -5
- package/package.json +4 -6
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Loads and initializes Microsoft Clarity. Split into its own module and
|
|
3
|
-
* loaded via `next/dynamic` from `cookie_consent_analytics.tsx`
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* `secrets.clarityProjectId` (and never render this component) don't need
|
|
8
|
-
* `@microsoft/clarity` (an optional peer dependency) installed at all — the
|
|
9
|
-
* dynamic-imported chunk containing this file is only built/requested the
|
|
10
|
-
* first time it's actually rendered.
|
|
3
|
+
* loaded via `next/dynamic` from `cookie_consent_analytics.tsx` so it's
|
|
4
|
+
* only fetched as a separate chunk once actually rendered (consent granted
|
|
5
|
+
* and `secrets.clarityProjectId` set) — `@microsoft/clarity` is a real
|
|
6
|
+
* dependency of this package, so it's always installed regardless.
|
|
11
7
|
*/
|
|
12
8
|
export default function ClarityScript({ projectId }: {
|
|
13
9
|
projectId: string;
|
|
@@ -9,14 +9,10 @@ function getClarityModule() {
|
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
11
|
* Loads and initializes Microsoft Clarity. Split into its own module and
|
|
12
|
-
* loaded via `next/dynamic` from `cookie_consent_analytics.tsx`
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
* `secrets.clarityProjectId` (and never render this component) don't need
|
|
17
|
-
* `@microsoft/clarity` (an optional peer dependency) installed at all — the
|
|
18
|
-
* dynamic-imported chunk containing this file is only built/requested the
|
|
19
|
-
* first time it's actually rendered.
|
|
12
|
+
* loaded via `next/dynamic` from `cookie_consent_analytics.tsx` so it's
|
|
13
|
+
* only fetched as a separate chunk once actually rendered (consent granted
|
|
14
|
+
* and `secrets.clarityProjectId` set) — `@microsoft/clarity` is a real
|
|
15
|
+
* dependency of this package, so it's always installed regardless.
|
|
20
16
|
*/
|
|
21
17
|
export default function ClarityScript({ projectId }) {
|
|
22
18
|
useEffect(() => {
|
|
@@ -3,12 +3,10 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
3
3
|
import { useEffect } from 'react';
|
|
4
4
|
import dynamic from 'next/dynamic';
|
|
5
5
|
import useCookieConsent from '../use_cookie_consent';
|
|
6
|
-
// Hoisted to module scope
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// module, so bundlers only resolve it when `ClarityScript` is actually
|
|
11
|
-
// rendered — see that file's doc comment for why this matters.
|
|
6
|
+
// Hoisted to module scope — calling `dynamic()` inside the component body
|
|
7
|
+
// creates a brand-new component identity every render, forcing a
|
|
8
|
+
// remount. Splitting into a separate chunk keeps `@microsoft/clarity`'s
|
|
9
|
+
// import out of this module until `ClarityScript` is actually rendered.
|
|
12
10
|
const ClarityScript = dynamic(() => import('./clarity_script'));
|
|
13
11
|
/**
|
|
14
12
|
* Renders whichever analytics/ads scripts have a resolved secret, gated on
|
|
@@ -8,8 +8,8 @@ export declare const defaultGdprCountries: readonly string[];
|
|
|
8
8
|
/**
|
|
9
9
|
* Resolves whether the cookie-consent banner is required for a visitor.
|
|
10
10
|
*
|
|
11
|
-
* - Neither getter set:
|
|
12
|
-
*
|
|
11
|
+
* - Neither getter set: fail-safe — consent is required by default since
|
|
12
|
+
* the visitor's country can't be determined at all.
|
|
13
13
|
* - Either getter set: fail-safe — a country that couldn't be resolved
|
|
14
14
|
* still requires consent; only a resolved country OUTSIDE
|
|
15
15
|
* `gdprCountries` skips the banner. `getCountryCode` takes precedence
|
|
@@ -33,8 +33,8 @@ function getGdprCountriesSet(gdprCountries) {
|
|
|
33
33
|
/**
|
|
34
34
|
* Resolves whether the cookie-consent banner is required for a visitor.
|
|
35
35
|
*
|
|
36
|
-
* - Neither getter set:
|
|
37
|
-
*
|
|
36
|
+
* - Neither getter set: fail-safe — consent is required by default since
|
|
37
|
+
* the visitor's country can't be determined at all.
|
|
38
38
|
* - Either getter set: fail-safe — a country that couldn't be resolved
|
|
39
39
|
* still requires consent; only a resolved country OUTSIDE
|
|
40
40
|
* `gdprCountries` skips the banner. `getCountryCode` takes precedence
|
|
@@ -42,7 +42,7 @@ function getGdprCountriesSet(gdprCountries) {
|
|
|
42
42
|
*/
|
|
43
43
|
export default async function resolveRequiresConsent(getCountryCode, getCloudflareContext, gdprCountries) {
|
|
44
44
|
if (!getCountryCode && !getCloudflareContext)
|
|
45
|
-
return
|
|
45
|
+
return true;
|
|
46
46
|
const countryCode = getCountryCode
|
|
47
47
|
? await getCountryCode()
|
|
48
48
|
: (await getCloudflareContext({ async: true }))?.cf?.country;
|
|
@@ -59,8 +59,17 @@ export default async function LocationzationProvider({ language, messages, child
|
|
|
59
59
|
let analyticsSecrets;
|
|
60
60
|
let requiresConsent = true;
|
|
61
61
|
if (config.cookieConsent) {
|
|
62
|
-
requiresConsent = await resolveRequiresConsent(config.cookieConsent.getCountryCode, config.cookieConsent.getCloudflareContext, config.cookieConsent.gdprCountries);
|
|
63
62
|
const isDevEnvironment = process.env.NODE_ENV === 'development';
|
|
63
|
+
// `getCloudflareContext` under `next dev`'s Cloudflare dev shim can
|
|
64
|
+
// crash the local workerd process (a native RPC panic, not a
|
|
65
|
+
// catchable JS error — see cloudflare/workers-sdk#8687) merely by
|
|
66
|
+
// being called, regardless of what it resolves to. `getCountryCode`
|
|
67
|
+
// is caller-supplied and may be dev-safe, so only skip the
|
|
68
|
+
// `getCloudflareContext` path in dev; fail-safe to `true`
|
|
69
|
+
// (banner shown) same as an unresolved country would.
|
|
70
|
+
requiresConsent = !isDevEnvironment
|
|
71
|
+
? await resolveRequiresConsent(config.cookieConsent.getCountryCode, config.cookieConsent.getCloudflareContext, config.cookieConsent.gdprCountries)
|
|
72
|
+
: true;
|
|
64
73
|
const analyticsAllowedInEnv = config.cookieConsent.enableAnalyticsInDevMode === true || !isDevEnvironment;
|
|
65
74
|
if (config.cookieConsent.autoWireAnalytics !== false && analyticsAllowedInEnv) {
|
|
66
75
|
analyticsSecrets = config.cookieConsent.getSecrets
|
|
@@ -155,10 +155,9 @@ export interface CookieConsentRoutingConfig {
|
|
|
155
155
|
* `getCloudflareContext`) decides whether the cookie-consent banner is
|
|
156
156
|
* required at all: visitors outside `gdprCountries` skip the banner and
|
|
157
157
|
* get analytics immediately (still gated by `enableAnalyticsInDevMode`).
|
|
158
|
-
* Omit BOTH to
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* once you need real GDPR-region gating.
|
|
158
|
+
* Omit BOTH to require consent for everyone (fail-safe default — the
|
|
159
|
+
* visitor's country can't be determined at all without either getter).
|
|
160
|
+
* Set one of the two getters to scope the banner to GDPR regions only.
|
|
162
161
|
*/
|
|
163
162
|
getCloudflareContext?: CookieConsentGetCloudflareContext;
|
|
164
163
|
/**
|
|
@@ -219,7 +218,11 @@ export interface CookieConsentAnalyticsSecrets {
|
|
|
219
218
|
googleAdsId?: string;
|
|
220
219
|
/** Google AdSense publisher ID, e.g. `"ca-pub-XXXXXXXXXXXXXXXX"`. */
|
|
221
220
|
googleAdSenseId?: string;
|
|
222
|
-
/**
|
|
221
|
+
/**
|
|
222
|
+
* Microsoft Clarity project ID. `@microsoft/clarity` is a real
|
|
223
|
+
* dependency of this package (small, so always installed) — loaded and
|
|
224
|
+
* initialized automatically once consent is granted.
|
|
225
|
+
*/
|
|
223
226
|
clarityProjectId?: string;
|
|
224
227
|
}
|
|
225
228
|
export interface FirebaseAuthRoutingConfig {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cloudflare-next-intl",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
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",
|
|
@@ -181,8 +181,10 @@
|
|
|
181
181
|
"url": "https://github.com/demian-ilnytskyi/cloudflare-next-intl/issues"
|
|
182
182
|
},
|
|
183
183
|
"homepage": "https://github.com/demian-ilnytskyi/cloudflare-next-intl#readme",
|
|
184
|
+
"dependencies": {
|
|
185
|
+
"@microsoft/clarity": "^1.0.2"
|
|
186
|
+
},
|
|
184
187
|
"peerDependencies": {
|
|
185
|
-
"@microsoft/clarity": ">=1.0.0",
|
|
186
188
|
"firebase": ">=10.0.0",
|
|
187
189
|
"next": ">=12.0.0",
|
|
188
190
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0",
|
|
@@ -194,15 +196,11 @@
|
|
|
194
196
|
},
|
|
195
197
|
"firebase": {
|
|
196
198
|
"optional": true
|
|
197
|
-
},
|
|
198
|
-
"@microsoft/clarity": {
|
|
199
|
-
"optional": true
|
|
200
199
|
}
|
|
201
200
|
},
|
|
202
201
|
"devDependencies": {
|
|
203
202
|
"@eslint/eslintrc": "^3",
|
|
204
203
|
"@eslint/js": "^9.27.0",
|
|
205
|
-
"@microsoft/clarity": "^1.0.2",
|
|
206
204
|
"@testing-library/dom": "^10.4.1",
|
|
207
205
|
"@testing-library/jest-dom": "^7.0.0",
|
|
208
206
|
"@testing-library/react": "^16.3.2",
|