{samlData &&
}
{loading && (
diff --git a/apps/login/src/helpers/colors.ts b/apps/login/src/helpers/colors.ts
index eafa25351..c3a92132d 100644
--- a/apps/login/src/helpers/colors.ts
+++ b/apps/login/src/helpers/colors.ts
@@ -30,13 +30,13 @@ export type ColorMap = {
[_key in MapName]: Color[];
};
-export const DARK_PRIMARY = "#2073c4";
+export const DARK_PRIMARY = "#eeeeee";
export const PRIMARY = "#5469d4";
export const DARK_WARN = "#ff3b5b";
export const WARN = "#cd3d56";
-export const DARK_BACKGROUND = "#111827";
+export const DARK_BACKGROUND = "#252526";
export const BACKGROUND = "#fafafa";
export const DARK_TEXT = "#ffffff";
diff --git a/apps/login/src/lib/theme.test.ts b/apps/login/src/lib/theme.test.ts
index 9351e6ff9..f5df8bdd5 100644
--- a/apps/login/src/lib/theme.test.ts
+++ b/apps/login/src/lib/theme.test.ts
@@ -78,6 +78,12 @@ describe("Theme Configuration", () => {
describe("getThemeConfig", () => {
it("should return default theme when no environment variables are set", () => {
+ delete process.env.NEXT_PUBLIC_THEME_ROUNDNESS;
+ delete process.env.NEXT_PUBLIC_THEME_LAYOUT;
+ delete process.env.NEXT_PUBLIC_THEME_APPEARANCE;
+ delete process.env.NEXT_PUBLIC_THEME_SPACING;
+ delete process.env.NEXT_PUBLIC_THEME_BACKGROUND_IMAGE;
+
const config = getThemeConfig();
expect(config.roundness).toBe(DEFAULT_THEME.roundness);
diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts
index 7001be94b..a46232c48 100644
--- a/apps/login/src/lib/zitadel.ts
+++ b/apps/login/src/lib/zitadel.ts
@@ -30,7 +30,7 @@ import {
VerifyU2FRegistrationRequest,
} from "@zitadel/proto/zitadel/user/v2/user_service_pb";
import { getTranslations } from "next-intl/server";
-import { unstable_cacheLife as cacheLife } from "next/cache";
+
import { getUserAgent } from "./fingerprint";
import { createLogger } from "./logger";
@@ -40,13 +40,55 @@ import { createServiceForHost } from "./service";
const logger = createLogger("zitadel");
-const useCache = process.env.DEBUG !== "true";
+const useCache = process.env.API_CACHE_ENABLED !== "false";
-async function cacheWrapper(callback: Promise) {
- "use cache";
- cacheLife("hours");
+let cacheConfig: Record = {};
+try {
+ if (process.env.API_CACHE_CONFIG) {
+ cacheConfig = JSON.parse(process.env.API_CACHE_CONFIG);
+ }
+} catch (e) {
+ console.error("Failed to parse API_CACHE_CONFIG", e);
+}
- return callback;
+const defaultCacheTTL = (cacheConfig.defaultMinutes ?? 15) * 60 * 1000; // 15 mins default
+const longCacheTTL = (cacheConfig.longMinutes ?? 60) * 60 * 1000; // 1 hour default
+
+/**
+ * Helper to determine the TTL for a specific API method.
+ * Allows overriding per-resource via the API_CACHE_CONFIG environment variable.
+ */
+function getTTLForKey(keyPrefix: string, fallbackTtl: number) {
+ const configTTL = cacheConfig[keyPrefix];
+ if (typeof configTTL === "number" && !isNaN(configTTL)) {
+ return configTTL * 60 * 1000; // Config expects minutes
+ }
+ return fallbackTtl;
+}
+
+const promiseCache = new Map; expiresAt: number }>();
+
+/**
+ * A stale-while-revalidate in-memory cache to keep data fresh and deduplicate concurrent requests.
+ * We cache the Promise, so concurrent requests share the exact same execution.
+ */
+function freshCache(key: string, fetcher: () => Promise, ttlMs: number): Promise {
+ if (!useCache) {
+ return fetcher();
+ }
+
+ const now = Date.now();
+ const cached = promiseCache.get(key);
+ if (cached && now < cached.expiresAt) {
+ return cached.promise;
+ }
+
+ const promise = fetcher();
+ promiseCache.set(key, { promise, expiresAt: now + ttlMs });
+
+ promise.catch(() => promiseCache.delete(key));
+
+ return promise;
}
export async function getHostedLoginTranslation({
@@ -57,29 +99,35 @@ export async function getHostedLoginTranslation({
organization?: string;
locale?: string;
}>) {
- const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig);
+ const fetcher = async () => {
+ const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig);
- const callback = settingsService
- .getHostedLoginTranslation(
- {
- level: organization
- ? {
- case: "organizationId",
- value: organization,
- }
- : {
- case: "instance",
- value: true,
- },
- locale: locale,
- },
- {},
- )
- .then((resp) => {
- return resp.translations ? resp.translations : undefined;
- });
+ return settingsService
+ .getHostedLoginTranslation(
+ {
+ level: organization
+ ? {
+ case: "organizationId",
+ value: organization,
+ }
+ : {
+ case: "instance",
+ value: true,
+ },
+ locale: locale,
+ },
+ {},
+ )
+ .then((resp) => {
+ return resp.translations ? resp.translations : undefined;
+ });
+ };
- return useCache ? cacheWrapper(callback) : callback;
+ return freshCache(
+ `getHostedLoginTranslation-${organization || "instance"}-${locale || "default"}`,
+ fetcher,
+ getTTLForKey("getHostedLoginTranslation", longCacheTTL),
+ );
}
export async function getBrandingSettings({
@@ -88,13 +136,19 @@ export async function getBrandingSettings({
}: WithServiceConfig<{
organization?: string;
}>) {
- const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig);
+ const fetcher = async () => {
+ const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig);
- const callback = settingsService
- .getBrandingSettings({ ctx: makeReqCtx(organization) }, {})
- .then((resp) => (resp.settings ? resp.settings : undefined));
+ return settingsService
+ .getBrandingSettings({ ctx: makeReqCtx(organization) }, {})
+ .then((resp) => (resp.settings ? resp.settings : undefined));
+ };
- return useCache ? cacheWrapper(callback) : callback;
+ return freshCache(
+ `getBrandingSettings-${organization || "instance"}`,
+ fetcher,
+ getTTLForKey("getBrandingSettings", longCacheTTL),
+ );
}
export async function getLoginSettings({
@@ -103,41 +157,61 @@ export async function getLoginSettings({
}: WithServiceConfig<{
organization?: string;
}>) {
- const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig);
+ const fetcher = async () => {
+ const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig);
- const callback = settingsService
- .getLoginSettings({ ctx: makeReqCtx(organization) }, {})
- .then((resp) => (resp.settings ? resp.settings : undefined));
+ return settingsService
+ .getLoginSettings({ ctx: makeReqCtx(organization) }, {})
+ .then((resp) => (resp.settings ? resp.settings : undefined));
+ };
- return useCache ? cacheWrapper(callback) : callback;
+ return freshCache(
+ `getLoginSettings-${organization || "instance"}`,
+ fetcher,
+ getTTLForKey("getLoginSettings", defaultCacheTTL),
+ );
}
export async function getSecuritySettings({ serviceConfig }: WithServiceConfig) {
- const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig);
+ const fetcher = async () => {
+ const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig);
- const callback = settingsService.getSecuritySettings({}).then((resp) => (resp.settings ? resp.settings : undefined));
+ return settingsService.getSecuritySettings({}).then((resp) => (resp.settings ? resp.settings : undefined));
+ };
- return useCache ? cacheWrapper(callback) : callback;
+ return freshCache(`getSecuritySettings-instance`, fetcher, getTTLForKey("getSecuritySettings", defaultCacheTTL));
}
export async function getLockoutSettings({ serviceConfig, orgId }: WithServiceConfig<{ orgId?: string }>) {
- const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig);
+ const fetcher = async () => {
+ const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig);
- const callback = settingsService
- .getLockoutSettings({ ctx: makeReqCtx(orgId) }, {})
- .then((resp) => (resp.settings ? resp.settings : undefined));
+ return settingsService
+ .getLockoutSettings({ ctx: makeReqCtx(orgId) }, {})
+ .then((resp) => (resp.settings ? resp.settings : undefined));
+ };
- return useCache ? cacheWrapper(callback) : callback;
+ return freshCache(
+ `getLockoutSettings-${orgId || "instance"}`,
+ fetcher,
+ getTTLForKey("getLockoutSettings", defaultCacheTTL),
+ );
}
export async function getPasswordExpirySettings({ serviceConfig, orgId }: WithServiceConfig<{ orgId?: string }>) {
- const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig);
+ const fetcher = async () => {
+ const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig);
- const callback = settingsService
- .getPasswordExpirySettings({ ctx: makeReqCtx(orgId) }, {})
- .then((resp) => (resp.settings ? resp.settings : undefined));
+ return settingsService
+ .getPasswordExpirySettings({ ctx: makeReqCtx(orgId) }, {})
+ .then((resp) => (resp.settings ? resp.settings : undefined));
+ };
- return useCache ? cacheWrapper(callback) : callback;
+ return freshCache(
+ `getPasswordExpirySettings-${orgId || "instance"}`,
+ fetcher,
+ getTTLForKey("getPasswordExpirySettings", defaultCacheTTL),
+ );
}
export async function listIDPLinks({ serviceConfig, userId }: WithServiceConfig<{ userId: string }>) {
@@ -165,16 +239,18 @@ export async function registerTOTP({ serviceConfig, userId }: WithServiceConfig<
}
export async function getAllowedLanguages({ serviceConfig }: WithServiceConfig) {
- const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig);
+ const fetcher = async () => {
+ const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig);
- const callback = settingsService.getGeneralSettings({}, {}).then((resp) => {
- return {
- allowedLanguages: resp.allowedLanguages,
- defaultLanguage: resp.defaultLanguage,
- };
- });
+ return settingsService.getGeneralSettings({}, {}).then((resp) => {
+ return {
+ allowedLanguages: resp.allowedLanguages,
+ defaultLanguage: resp.defaultLanguage,
+ };
+ });
+ };
- return useCache ? cacheWrapper(callback) : callback;
+ return freshCache(`getGeneralSettings-instance`, fetcher, getTTLForKey("getGeneralSettings", longCacheTTL));
}
export async function getLegalAndSupportSettings({
@@ -183,13 +259,19 @@ export async function getLegalAndSupportSettings({
}: WithServiceConfig<{
organization?: string;
}>) {
- const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig);
+ const fetcher = async () => {
+ const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig);
- const callback = settingsService
- .getLegalAndSupportSettings({ ctx: makeReqCtx(organization) }, {})
- .then((resp) => (resp.settings ? resp.settings : undefined));
+ return settingsService
+ .getLegalAndSupportSettings({ ctx: makeReqCtx(organization) }, {})
+ .then((resp) => (resp.settings ? resp.settings : undefined));
+ };
- return useCache ? cacheWrapper(callback) : callback;
+ return freshCache(
+ `getLegalAndSupportSettings-${organization || "instance"}`,
+ fetcher,
+ getTTLForKey("getLegalAndSupportSettings", longCacheTTL),
+ );
}
export async function getPasswordComplexitySettings({
@@ -198,13 +280,19 @@ export async function getPasswordComplexitySettings({
}: WithServiceConfig<{
organization?: string;
}>) {
- const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig);
+ const fetcher = async () => {
+ const settingsService: Client = await createServiceForHost(SettingsService, serviceConfig);
- const callback = settingsService
- .getPasswordComplexitySettings({ ctx: makeReqCtx(organization) })
- .then((resp) => (resp.settings ? resp.settings : undefined));
+ return settingsService
+ .getPasswordComplexitySettings({ ctx: makeReqCtx(organization) })
+ .then((resp) => (resp.settings ? resp.settings : undefined));
+ };
- return useCache ? cacheWrapper(callback) : callback;
+ return freshCache(
+ `getPasswordComplexitySettings-${organization || "instance"}`,
+ fetcher,
+ getTTLForKey("getPasswordComplexitySettings", defaultCacheTTL),
+ );
}
export async function createSessionFromChecksAndChallenges({
@@ -740,23 +828,29 @@ export async function searchUsers({
}
export async function getDefaultOrg({ serviceConfig }: WithServiceConfig): Promise {
- const orgService: Client = await createServiceForHost(OrganizationService, serviceConfig);
+ const fetcher = async () => {
+ const orgService: Client = await createServiceForHost(OrganizationService, serviceConfig);
- return orgService
- .listOrganizations(
- {
- queries: [
- {
- query: {
- case: "defaultQuery",
- value: {},
+ return orgService
+ .listOrganizations(
+ {
+ queries: [
+ {
+ query: {
+ case: "defaultQuery",
+ value: {},
+ },
},
- },
- ],
- },
- {},
- )
- .then((resp) => (resp?.result && resp.result[0] ? resp.result[0] : null));
+ ],
+ },
+ {},
+ )
+ .then((resp) => (resp?.result && resp.result[0] ? resp.result[0] : null));
+ };
+
+ return useCache
+ ? freshCache(`getDefaultOrg-${"instance"}`, fetcher, getTTLForKey("getDefaultOrg", defaultCacheTTL))
+ : fetcher();
}
export async function getOrgsByDomain({ serviceConfig, domain }: WithServiceConfig<{ domain: string }>) {
diff --git a/apps/login/src/middleware.ts b/apps/login/src/proxy.ts
similarity index 97%
rename from apps/login/src/middleware.ts
rename to apps/login/src/proxy.ts
index b4bf90bf6..b713b13b6 100644
--- a/apps/login/src/middleware.ts
+++ b/apps/login/src/proxy.ts
@@ -6,8 +6,6 @@ import { buildCSP } from "./lib/csp";
import { createLogger } from "./lib/logger";
import { getServiceConfig } from "./lib/service-url";
-export const runtime = "nodejs";
-
const logger = createLogger("middleware");
export const config = {
matcher: ["/.well-known/:path*", "/oauth/:path*", "/oidc/:path*", "/idps/callback/:path*", "/saml/:path*", "/:path*"],
@@ -31,7 +29,7 @@ async function loadSecuritySettings(request: NextRequest): Promise=18.14.0'}
hasBin: true
- '@next/env@15.5.10':
- resolution: {integrity: sha512-plg+9A/KoZcTS26fe15LHg+QxReTazrIOoKKUC3Uz4leGGeNPgLHdevVraAAOX0snnUs3WkRx3eUQpj9mreG6A==}
-
'@next/env@16.1.6':
resolution: {integrity: sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ==}
'@next/eslint-plugin-next@16.1.6':
resolution: {integrity: sha512-/Qq3PTagA6+nYVfryAtQ7/9FEr/6YVyvOtl6rZnGsbReGLf0jZU6gkpr1FuChAQpvV46a78p4cmHOVP8mbfSMQ==}
- '@next/swc-darwin-arm64@15.5.7':
- resolution: {integrity: sha512-IZwtxCEpI91HVU/rAUOOobWSZv4P2DeTtNaCdHqLcTJU4wdNXgAySvKa/qJCgR5m6KI8UsKDXtO2B31jcaw1Yw==}
- engines: {node: '>= 10'}
- cpu: [arm64]
- os: [darwin]
-
'@next/swc-darwin-arm64@16.1.6':
resolution: {integrity: sha512-wTzYulosJr/6nFnqGW7FrG3jfUUlEf8UjGA0/pyypJl42ExdVgC6xJgcXQ+V8QFn6niSG2Pb8+MIG1mZr2vczw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
- '@next/swc-darwin-x64@15.5.7':
- resolution: {integrity: sha512-UP6CaDBcqaCBuiq/gfCEJw7sPEoX1aIjZHnBWN9v9qYHQdMKvCKcAVs4OX1vIjeE+tC5EIuwDTVIoXpUes29lg==}
- engines: {node: '>= 10'}
- cpu: [x64]
- os: [darwin]
-
'@next/swc-darwin-x64@16.1.6':
resolution: {integrity: sha512-BLFPYPDO+MNJsiDWbeVzqvYd4NyuRrEYVB5k2N3JfWncuHAy2IVwMAOlVQDFjj+krkWzhY2apvmekMkfQR0CUQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
- '@next/swc-linux-arm64-gnu@15.5.7':
- resolution: {integrity: sha512-NCslw3GrNIw7OgmRBxHtdWFQYhexoUCq+0oS2ccjyYLtcn1SzGzeM54jpTFonIMUjNbHmpKpziXnpxhSWLcmBA==}
- engines: {node: '>= 10'}
- cpu: [arm64]
- os: [linux]
- libc: [glibc]
-
'@next/swc-linux-arm64-gnu@16.1.6':
resolution: {integrity: sha512-OJYkCd5pj/QloBvoEcJ2XiMnlJkRv9idWA/j0ugSuA34gMT6f5b7vOiCQHVRpvStoZUknhl6/UxOXL4OwtdaBw==}
engines: {node: '>= 10'}
@@ -3112,13 +3081,6 @@ packages:
os: [linux]
libc: [glibc]
- '@next/swc-linux-arm64-musl@15.5.7':
- resolution: {integrity: sha512-nfymt+SE5cvtTrG9u1wdoxBr9bVB7mtKTcj0ltRn6gkP/2Nu1zM5ei8rwP9qKQP0Y//umK+TtkKgNtfboBxRrw==}
- engines: {node: '>= 10'}
- cpu: [arm64]
- os: [linux]
- libc: [musl]
-
'@next/swc-linux-arm64-musl@16.1.6':
resolution: {integrity: sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==}
engines: {node: '>= 10'}
@@ -3126,13 +3088,6 @@ packages:
os: [linux]
libc: [musl]
- '@next/swc-linux-x64-gnu@15.5.7':
- resolution: {integrity: sha512-hvXcZvCaaEbCZcVzcY7E1uXN9xWZfFvkNHwbe/n4OkRhFWrs1J1QV+4U1BN06tXLdaS4DazEGXwgqnu/VMcmqw==}
- engines: {node: '>= 10'}
- cpu: [x64]
- os: [linux]
- libc: [glibc]
-
'@next/swc-linux-x64-gnu@16.1.6':
resolution: {integrity: sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==}
engines: {node: '>= 10'}
@@ -3140,13 +3095,6 @@ packages:
os: [linux]
libc: [glibc]
- '@next/swc-linux-x64-musl@15.5.7':
- resolution: {integrity: sha512-4IUO539b8FmF0odY6/SqANJdgwn1xs1GkPO5doZugwZ3ETF6JUdckk7RGmsfSf7ws8Qb2YB5It33mvNL/0acqA==}
- engines: {node: '>= 10'}
- cpu: [x64]
- os: [linux]
- libc: [musl]
-
'@next/swc-linux-x64-musl@16.1.6':
resolution: {integrity: sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==}
engines: {node: '>= 10'}
@@ -3154,24 +3102,12 @@ packages:
os: [linux]
libc: [musl]
- '@next/swc-win32-arm64-msvc@15.5.7':
- resolution: {integrity: sha512-CpJVTkYI3ZajQkC5vajM7/ApKJUOlm6uP4BknM3XKvJ7VXAvCqSjSLmM0LKdYzn6nBJVSjdclx8nYJSa3xlTgQ==}
- engines: {node: '>= 10'}
- cpu: [arm64]
- os: [win32]
-
'@next/swc-win32-arm64-msvc@16.1.6':
resolution: {integrity: sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
- '@next/swc-win32-x64-msvc@15.5.7':
- resolution: {integrity: sha512-gMzgBX164I6DN+9/PGA+9dQiwmTkE4TloBNx8Kv9UiGARsr9Nba7IpcBRA1iTV9vwlYnrE3Uy6I7Aj6qLjQuqw==}
- engines: {node: '>= 10'}
- cpu: [x64]
- os: [win32]
-
'@next/swc-win32-x64-msvc@16.1.6':
resolution: {integrity: sha512-NRfO39AIrzBnixKbjuo2YiYhB6o9d8v/ymU9m/Xk8cyVk+k7XylniXkHwjs4s70wedVffc6bQNbufk5v0xEm0A==}
engines: {node: '>= 10'}
@@ -5198,6 +5134,9 @@ packages:
resolution: {integrity: sha512-WkhW1HO8pA8JT8e27tvjQHQg8eO5KaOz+WsGkN00RyL5DwHgPSzu4a3eYug+b3rW7OGFub7jadXBuGSrzqgonA==}
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
+ '@schummar/icu-type-parser@1.21.5':
+ resolution: {integrity: sha512-bXHSaW5jRTmke9Vd0h5P7BtWZG9Znqb8gSDxZnxaGSJnGwPLDPfS+3g0BKzeWqzgZPsIVZkM7m2tbo18cm5HBw==}
+
'@shikijs/core@3.21.0':
resolution: {integrity: sha512-AXSQu/2n1UIQekY8euBJlvFYZIw0PHY63jUzGbrOma4wPxzznJXTXkri+QcHeBNaFxiiOljKxxJkVSoB3PjbyA==}
@@ -8530,6 +8469,9 @@ packages:
resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==}
engines: {node: '>=0.10.0'}
+ icu-minify@4.8.3:
+ resolution: {integrity: sha512-65Av7FLosNk7bPbmQx5z5XG2Y3T2GFppcjiXh4z1idHeVgQxlDpAmkGoYI0eFzAvrOnjpWTL5FmPDhsdfRMPEA==}
+
identifier-regex@1.0.1:
resolution: {integrity: sha512-ZrYyM0sozNPZlvBvE7Oq9Bn44n0qKGrYu5sQ0JzMUnjIhpgWYE2JB6aBoFwEYdPjqj7jPyxXTMJiHDOxDfd8yw==}
engines: {node: '>=18'}
@@ -8617,8 +8559,8 @@ packages:
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
engines: {node: '>= 0.4'}
- intl-messageformat@10.7.16:
- resolution: {integrity: sha512-UmdmHUmp5CIKKjSoE10la5yfU+AYJAaiYLsodbjL4lji83JNvgOQUjGaGhGrpFCb0Uh7sl7qfP1IyILa8Z40ug==}
+ intl-messageformat@11.1.2:
+ resolution: {integrity: sha512-ucSrQmZGAxfiBHfBRXW/k7UC8MaGFlEj4Ry1tKiDcmgwQm1y3EDl40u+4VNHYomxJQMJi9NEI3riDRlth96jKg==}
ip-address@10.0.1:
resolution: {integrity: sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==}
@@ -9880,11 +9822,18 @@ packages:
peerDependencies:
typescript: '5'
- next-intl@3.26.5:
- resolution: {integrity: sha512-EQlCIfY0jOhRldiFxwSXG+ImwkQtDEfQeSOEQp6ieAGSLWGlgjdb/Ck/O7wMfC430ZHGeUKVKax8KGusTPKCgg==}
+ next-intl-swc-plugin-extractor@4.8.3:
+ resolution: {integrity: sha512-YcaT+R9z69XkGhpDarVFWUprrCMbxgIQYPUaXoE6LGVnLjGdo8hu3gL6bramDVjNKViYY8a/pXPy7Bna0mXORg==}
+
+ next-intl@4.8.3:
+ resolution: {integrity: sha512-PvdBDWg+Leh7BR7GJUQbCDVVaBRn37GwDBWc9sv0rVQOJDQ5JU1rVzx9EEGuOGYo0DHAl70++9LQ7HxTawdL7w==}
peerDependencies:
- next: ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0
+ next: ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
next-themes@0.2.1:
resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==}
@@ -9902,27 +9851,6 @@ packages:
next-validate-link@1.6.4:
resolution: {integrity: sha512-wR/VKyJlaTbUT5k1uujEnk6O616YtWGt52s9FJa3tRCQ2qL2TGFTAklXJ0QdX1NTAEeP6rGFOTtHEDwveFrc2g==}
- next@15.5.10:
- resolution: {integrity: sha512-r0X65PNwyDDyOrWNKpQoZvOatw7BcsTPRKdwEqtc9cj3wv7mbBIk9tKed4klRaFXJdX0rugpuMTHslDrAU1bBg==}
- engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
- hasBin: true
- peerDependencies:
- '@opentelemetry/api': ^1.1.0
- '@playwright/test': ^1.51.1
- babel-plugin-react-compiler: '*'
- react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
- react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
- sass: ^1.3.0
- peerDependenciesMeta:
- '@opentelemetry/api':
- optional: true
- '@playwright/test':
- optional: true
- babel-plugin-react-compiler:
- optional: true
- sass:
- optional: true
-
next@16.1.6:
resolution: {integrity: sha512-hkyRkcu5x/41KoqnROkfTm2pZVbKxvbZRuNvKXLRXxs3VfyO0WhY50TQS40EuKO9SW3rBj/sF3WbVwDACeMZyw==}
engines: {node: '>=20.9.0'}
@@ -10441,6 +10369,9 @@ packages:
resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==}
engines: {node: '>=10.13.0'}
+ po-parser@2.1.1:
+ resolution: {integrity: sha512-ECF4zHLbUItpUgE3OTtLKlPjeBN+fKEczj2zYjDfCGOzicNs0GK3Vg2IoAYwx7LH/XYw43fZQP6xnZ4TkNxSLQ==}
+
possible-typed-array-names@1.1.0:
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
engines: {node: '>= 0.4'}
@@ -12079,10 +12010,10 @@ packages:
'@types/react':
optional: true
- use-intl@3.26.5:
- resolution: {integrity: sha512-OdsJnC/znPvHCHLQH/duvQNXnP1w0hPfS+tkSi3mAbfjYBGh4JnyfdwkQBfIVf7t8gs9eSX/CntxUMvtKdG2MQ==}
+ use-intl@4.8.3:
+ resolution: {integrity: sha512-nLxlC/RH+le6g3amA508Itnn/00mE+J22ui21QhOWo5V9hCEC43+WtnRAITbJW0ztVZphev5X9gvOf2/Dk9PLA==}
peerDependencies:
- react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
+ react: ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
use-isomorphic-layout-effect@1.2.1:
resolution: {integrity: sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==}
@@ -14085,38 +14016,26 @@ snapshots:
- '@vue/composition-api'
- vue
- '@formatjs/ecma402-abstract@2.3.4':
+ '@formatjs/ecma402-abstract@3.1.1':
dependencies:
- '@formatjs/fast-memoize': 2.2.7
- '@formatjs/intl-localematcher': 0.6.1
+ '@formatjs/fast-memoize': 3.1.0
+ '@formatjs/intl-localematcher': 0.8.1
decimal.js: 10.6.0
tslib: 2.8.1
- '@formatjs/fast-memoize@2.2.7':
- dependencies:
- tslib: 2.8.1
-
'@formatjs/fast-memoize@3.1.0':
dependencies:
tslib: 2.8.1
- '@formatjs/icu-messageformat-parser@2.11.2':
+ '@formatjs/icu-messageformat-parser@3.5.1':
dependencies:
- '@formatjs/ecma402-abstract': 2.3.4
- '@formatjs/icu-skeleton-parser': 1.8.14
+ '@formatjs/ecma402-abstract': 3.1.1
+ '@formatjs/icu-skeleton-parser': 2.1.1
tslib: 2.8.1
- '@formatjs/icu-skeleton-parser@1.8.14':
- dependencies:
- '@formatjs/ecma402-abstract': 2.3.4
- tslib: 2.8.1
-
- '@formatjs/intl-localematcher@0.5.10':
- dependencies:
- tslib: 2.8.1
-
- '@formatjs/intl-localematcher@0.6.1':
+ '@formatjs/icu-skeleton-parser@2.1.1':
dependencies:
+ '@formatjs/ecma402-abstract': 3.1.1
tslib: 2.8.1
'@formatjs/intl-localematcher@0.8.1':
@@ -14949,59 +14868,33 @@ snapshots:
yaml: 2.8.1
yargs: 17.7.2
- '@next/env@15.5.10': {}
-
'@next/env@16.1.6': {}
'@next/eslint-plugin-next@16.1.6':
dependencies:
fast-glob: 3.3.1
- '@next/swc-darwin-arm64@15.5.7':
- optional: true
-
'@next/swc-darwin-arm64@16.1.6':
optional: true
- '@next/swc-darwin-x64@15.5.7':
- optional: true
-
'@next/swc-darwin-x64@16.1.6':
optional: true
- '@next/swc-linux-arm64-gnu@15.5.7':
- optional: true
-
'@next/swc-linux-arm64-gnu@16.1.6':
optional: true
- '@next/swc-linux-arm64-musl@15.5.7':
- optional: true
-
'@next/swc-linux-arm64-musl@16.1.6':
optional: true
- '@next/swc-linux-x64-gnu@15.5.7':
- optional: true
-
'@next/swc-linux-x64-gnu@16.1.6':
optional: true
- '@next/swc-linux-x64-musl@15.5.7':
- optional: true
-
'@next/swc-linux-x64-musl@16.1.6':
optional: true
- '@next/swc-win32-arm64-msvc@15.5.7':
- optional: true
-
'@next/swc-win32-arm64-msvc@16.1.6':
optional: true
- '@next/swc-win32-x64-msvc@15.5.7':
- optional: true
-
'@next/swc-win32-x64-msvc@16.1.6':
optional: true
@@ -16088,7 +15981,6 @@ snapshots:
'@parcel/watcher-win32-arm64': 2.5.1
'@parcel/watcher-win32-ia32': 2.5.1
'@parcel/watcher-win32-x64': 2.5.1
- optional: true
'@phosphor-icons/core@2.1.1': {}
@@ -17541,6 +17433,8 @@ snapshots:
transitivePeerDependencies:
- chokidar
+ '@schummar/icu-type-parser@1.21.5': {}
+
'@shikijs/core@3.21.0':
dependencies:
'@shikijs/types': 3.21.0
@@ -17755,10 +17649,8 @@ snapshots:
'@swc/core-win32-ia32-msvc': 1.15.3
'@swc/core-win32-x64-msvc': 1.15.3
'@swc/helpers': 0.5.17
- optional: true
- '@swc/counter@0.1.3':
- optional: true
+ '@swc/counter@0.1.3': {}
'@swc/helpers@0.5.15':
dependencies:
@@ -17771,7 +17663,6 @@ snapshots:
'@swc/types@0.1.25':
dependencies:
'@swc/counter': 0.1.3
- optional: true
'@tailwindcss/forms@0.5.11(tailwindcss@3.4.14)':
dependencies:
@@ -20948,7 +20839,7 @@ snapshots:
'@types/react': 19.2.14
algoliasearch: 5.37.0
lucide-react: 0.574.0(react@19.2.4)
- next: 16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3)
+ next: 16.1.6(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3)
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
zod: 4.3.6
@@ -20979,7 +20870,7 @@ snapshots:
'@types/mdast': 4.0.4
'@types/mdx': 2.0.13
'@types/react': 19.2.14
- next: 16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3)
+ next: 16.1.6(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3)
react: 19.2.4
vite: 7.1.11(@types/node@25.2.3)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
transitivePeerDependencies:
@@ -21049,7 +20940,7 @@ snapshots:
optionalDependencies:
'@types/mdx': 2.0.13
'@types/react': 19.2.14
- next: 16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3)
+ next: 16.1.6(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3)
transitivePeerDependencies:
- '@emotion/is-prop-valid'
- '@types/react-dom'
@@ -21569,6 +21460,10 @@ snapshots:
dependencies:
safer-buffer: 2.1.2
+ icu-minify@4.8.3:
+ dependencies:
+ '@formatjs/icu-messageformat-parser': 3.5.1
+
identifier-regex@1.0.1:
dependencies:
reserved-identifiers: 1.2.0
@@ -21632,11 +21527,11 @@ snapshots:
hasown: 2.0.2
side-channel: 1.1.0
- intl-messageformat@10.7.16:
+ intl-messageformat@11.1.2:
dependencies:
- '@formatjs/ecma402-abstract': 2.3.4
- '@formatjs/fast-memoize': 2.2.7
- '@formatjs/icu-messageformat-parser': 2.11.2
+ '@formatjs/ecma402-abstract': 3.1.1
+ '@formatjs/fast-memoize': 3.1.0
+ '@formatjs/icu-messageformat-parser': 3.5.1
tslib: 2.8.1
ip-address@10.0.1: {}
@@ -23224,17 +23119,28 @@ snapshots:
dependencies:
typescript: 5.9.3
- next-intl@3.26.5(next@15.5.10(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3))(react@19.2.4):
- dependencies:
- '@formatjs/intl-localematcher': 0.5.10
- negotiator: 1.0.0
- next: 15.5.10(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3)
- react: 19.2.4
- use-intl: 3.26.5(react@19.2.4)
+ next-intl-swc-plugin-extractor@4.8.3: {}
- next-themes@0.2.1(next@15.5.10(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
+ next-intl@4.8.3(@swc/helpers@0.5.17)(next@16.1.6(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3))(react@19.2.4)(typescript@5.9.3):
dependencies:
- next: 15.5.10(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3)
+ '@formatjs/intl-localematcher': 0.8.1
+ '@parcel/watcher': 2.5.1
+ '@swc/core': 1.15.3(@swc/helpers@0.5.17)
+ icu-minify: 4.8.3
+ negotiator: 1.0.0
+ next: 16.1.6(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3)
+ next-intl-swc-plugin-extractor: 4.8.3
+ po-parser: 2.1.1
+ react: 19.2.4
+ use-intl: 4.8.3(react@19.2.4)
+ optionalDependencies:
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - '@swc/helpers'
+
+ next-themes@0.2.1(next@16.1.6(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
+ dependencies:
+ next: 16.1.6(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3)
react: 19.2.4
react-dom: 19.2.4(react@19.2.4)
@@ -23255,33 +23161,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- next@15.5.10(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3):
- dependencies:
- '@next/env': 15.5.10
- '@swc/helpers': 0.5.15
- caniuse-lite: 1.0.30001760
- postcss: 8.4.31
- react: 19.2.4
- react-dom: 19.2.4(react@19.2.4)
- styled-jsx: 5.1.6(@babel/core@7.28.4)(react@19.2.4)
- optionalDependencies:
- '@next/swc-darwin-arm64': 15.5.7
- '@next/swc-darwin-x64': 15.5.7
- '@next/swc-linux-arm64-gnu': 15.5.7
- '@next/swc-linux-arm64-musl': 15.5.7
- '@next/swc-linux-x64-gnu': 15.5.7
- '@next/swc-linux-x64-musl': 15.5.7
- '@next/swc-win32-arm64-msvc': 15.5.7
- '@next/swc-win32-x64-msvc': 15.5.7
- '@opentelemetry/api': 1.9.0
- '@playwright/test': 1.58.0
- sass: 1.97.3
- sharp: 0.34.5
- transitivePeerDependencies:
- - '@babel/core'
- - babel-plugin-macros
-
- next@16.1.6(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3):
+ next@16.1.6(@babel/core@7.28.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.97.3):
dependencies:
'@next/env': 16.1.6
'@swc/helpers': 0.5.15
@@ -23329,8 +23209,7 @@ snapshots:
node-addon-api@6.1.0:
optional: true
- node-addon-api@7.1.1:
- optional: true
+ node-addon-api@7.1.1: {}
node-domexception@1.0.0: {}
@@ -23920,6 +23799,8 @@ snapshots:
pngjs@5.0.0: {}
+ po-parser@2.1.1: {}
+
possible-typed-array-names@1.1.0: {}
postcss-import@15.1.0(postcss@8.5.6):
@@ -25872,10 +25753,12 @@ snapshots:
optionalDependencies:
'@types/react': 19.2.14
- use-intl@3.26.5(react@19.2.4):
+ use-intl@4.8.3(react@19.2.4):
dependencies:
- '@formatjs/fast-memoize': 2.2.7
- intl-messageformat: 10.7.16
+ '@formatjs/fast-memoize': 3.1.0
+ '@schummar/icu-type-parser': 1.21.5
+ icu-minify: 4.8.3
+ intl-messageformat: 11.1.2
react: 19.2.4
use-isomorphic-layout-effect@1.2.1(@types/react@19.2.14)(react@19.2.4):