diff --git a/acceptance/tests/register-screen.ts b/acceptance/tests/register-screen.ts index 414e38793bf..d14f5dc9708 100644 --- a/acceptance/tests/register-screen.ts +++ b/acceptance/tests/register-screen.ts @@ -5,12 +5,12 @@ const passwordConfirmField = "password-confirm-text-input"; export async function registerUserScreenPassword(page: Page, firstname: string, lastname: string, email: string) { await registerUserScreen(page, firstname, lastname, email); - await page.getByTestId("Password-radio").click(); + await page.getByTestId("password-radio").click(); } export async function registerUserScreenPasskey(page: Page, firstname: string, lastname: string, email: string) { await registerUserScreen(page, firstname, lastname, email); - await page.getByTestId("Passkeys-radio").click(); + await page.getByTestId("passkey-radio").click(); } export async function registerPasswordScreen(page: Page, password1: string, password2: string) { diff --git a/apps/login/cypress/integration/register.cy.ts b/apps/login/cypress/integration/register.cy.ts index 902c6a8061a..262302c4c35 100644 --- a/apps/login/cypress/integration/register.cy.ts +++ b/apps/login/cypress/integration/register.cy.ts @@ -10,6 +10,16 @@ describe("register", () => { result: [{ id: "256088834543534543" }], }, }); + stub("zitadel.settings.v2.SettingsService", "GetLoginSettings", { + data: { + settings: { + passkeysType: 1, + allowRegister: true, + allowUsernamePassword: true, + defaultRedirectUri: "", + }, + }, + }); stub("zitadel.user.v2.UserService", "AddHumanUser", { data: { userId: "221394658884845598", @@ -53,9 +63,11 @@ describe("register", () => { it("should redirect a user who selects passwordless on register to /passkey/set", () => { cy.visit("/register"); - cy.get('input[autocomplete="firstname"]').focus().type("John"); - cy.get('input[autocomplete="lastname"]').focus().type("Doe"); - cy.get('input[autocomplete="email"]').focus().type("john@zitadel.com"); + cy.get('input[data-testid="firstname-text-input"]').focus().type("John"); + cy.get('input[data-testid="lastname-text-input"]').focus().type("Doe"); + cy.get('input[data-testid="email-text-input"]') + .focus() + .type("john@zitadel.com"); cy.get('input[type="checkbox"][value="privacypolicy"]').check(); cy.get('input[type="checkbox"][value="tos"]').check(); cy.get('button[type="submit"]').click(); diff --git a/apps/login/locales/de.json b/apps/login/locales/de.json index ef71731d1fe..4d5f0c1530d 100644 --- a/apps/login/locales/de.json +++ b/apps/login/locales/de.json @@ -122,6 +122,18 @@ } }, "register": { + "methods": { + "passkey": "Passkey", + "password": "Password" + }, + "disabled": { + "title": "Registrierung deaktiviert", + "description": "Die Registrierung ist deaktiviert. Bitte wenden Sie sich an den Administrator." + }, + "missingdata": { + "title": "Registrierung fehlgeschlagen", + "description": "Einige Daten fehlen. Bitte überprüfen Sie Ihre Eingaben." + }, "title": "Registrieren", "description": "Erstellen Sie Ihr ZITADEL-Konto.", "selectMethod": "Wählen Sie die Methode, mit der Sie sich authentifizieren möchten", @@ -151,7 +163,8 @@ }, "signedin": { "title": "Willkommen {user}!", - "description": "Sie sind angemeldet." + "description": "Sie sind angemeldet.", + "continue": "Weiter" }, "verify": { "userIdMissing": "Keine Benutzer-ID angegeben!", diff --git a/apps/login/locales/en.json b/apps/login/locales/en.json index d6cdc4009eb..c7fd5e30b9a 100644 --- a/apps/login/locales/en.json +++ b/apps/login/locales/en.json @@ -122,6 +122,18 @@ } }, "register": { + "methods": { + "passkey": "Passkey", + "password": "Password" + }, + "disabled": { + "title": "Registration disabled", + "description": "The registration is disabled. Please contact your administrator." + }, + "missingdata": { + "title": "Missing data", + "description": "Provide email, first and last name to register." + }, "title": "Register", "description": "Create your ZITADEL account.", "selectMethod": "Select the method you would like to authenticate", @@ -151,7 +163,8 @@ }, "signedin": { "title": "Welcome {user}!", - "description": "You are signed in." + "description": "You are signed in.", + "continue": "Continue" }, "verify": { "userIdMissing": "No userId provided!", diff --git a/apps/login/locales/es.json b/apps/login/locales/es.json index 0a9c24f93bf..e722db5812c 100644 --- a/apps/login/locales/es.json +++ b/apps/login/locales/es.json @@ -122,6 +122,18 @@ } }, "register": { + "methods": { + "passkey": "Clave de acceso", + "password": "Contraseña" + }, + "disabled": { + "title": "Registro deshabilitado", + "description": "Registrarse está deshabilitado en este momento." + }, + "missingdata": { + "title": "Datos faltantes", + "description": "No se proporcionaron datos suficientes para el registro." + }, "title": "Registrarse", "description": "Crea tu cuenta ZITADEL.", "selectMethod": "Selecciona el método con el que deseas autenticarte", @@ -151,7 +163,8 @@ }, "signedin": { "title": "¡Bienvenido {user}!", - "description": "Has iniciado sesión." + "description": "Has iniciado sesión.", + "continue": "Continuar" }, "verify": { "userIdMissing": "¡No se proporcionó userId!", diff --git a/apps/login/locales/it.json b/apps/login/locales/it.json index 74425a06a0c..9467f0ba840 100644 --- a/apps/login/locales/it.json +++ b/apps/login/locales/it.json @@ -122,6 +122,18 @@ } }, "register": { + "methods": { + "passkey": "Passkey", + "password": "Password" + }, + "disabled": { + "title": "Registration disabled", + "description": "Registrazione disabilitata. Contatta l'amministratore di sistema per assistenza." + }, + "missingdata": { + "title": "Registrazione", + "description": "Inserisci i tuoi dati per registrarti." + }, "title": "Registrati", "description": "Crea il tuo account ZITADEL.", "selectMethod": "Seleziona il metodo con cui desideri autenticarti", @@ -151,7 +163,8 @@ }, "signedin": { "title": "Benvenuto {user}!", - "description": "Sei connesso." + "description": "Sei connesso.", + "continue": "Continua" }, "verify": { "userIdMissing": "Nessun userId fornito!", diff --git a/apps/login/mock/initial-stubs/zitadel.settings.v2.SettingsService.json b/apps/login/mock/initial-stubs/zitadel.settings.v2.SettingsService.json index 6ddf5989ed0..f62b5da0771 100644 --- a/apps/login/mock/initial-stubs/zitadel.settings.v2.SettingsService.json +++ b/apps/login/mock/initial-stubs/zitadel.settings.v2.SettingsService.json @@ -2,7 +2,15 @@ { "service": "zitadel.settings.v2.SettingsService", "method": "GetBrandingSettings", - "out": {} + "out": { + "data": { + "settings": { + "darkTheme": { + "backgroundColor": "#ff0000" + } + } + } + } }, { "service": "zitadel.settings.v2.SettingsService", diff --git a/apps/login/next-env.d.ts b/apps/login/next-env.d.ts index 40c3d68096c..1b3be0840f3 100755 --- a/apps/login/next-env.d.ts +++ b/apps/login/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/apps/login/next.config.mjs b/apps/login/next.config.mjs index e2906b1fa89..a6e1d1a6d8d 100755 --- a/apps/login/next.config.mjs +++ b/apps/login/next.config.mjs @@ -36,7 +36,9 @@ const secureHeaders = [ const nextConfig = { reactStrictMode: true, // Recommended for the `pages` directory, default in `app`. - swcMinify: true, + experimental: { + dynamicIO: true, + }, images: { remotePatterns: [ { diff --git a/apps/login/package.json b/apps/login/package.json index 13927b5168c..f8f3b89a3fb 100644 --- a/apps/login/package.json +++ b/apps/login/package.json @@ -3,7 +3,7 @@ "private": true, "type": "module", "scripts": { - "dev": "next dev", + "dev": "next dev --turbopack", "test": "concurrently --timings --kill-others-on-fail 'npm:test:unit' 'npm:test:integration'", "test:watch": "concurrently --kill-others 'npm:test:unit:watch' 'npm:test:integration:watch'", "test:unit": "vitest", @@ -45,13 +45,13 @@ "copy-to-clipboard": "^3.3.3", "deepmerge": "^4.3.1", "moment": "^2.29.4", - "next": "14.2.14", - "next-intl": "^3.20.0", + "next": "15.0.4-canary.23", + "next-intl": "^3.25.1", "next-themes": "^0.2.1", "nice-grpc": "2.0.1", "qrcode.react": "^3.1.0", - "react": "^18.3.1", - "react-dom": "18.3.1", + "react": "19.0.0-rc-66855b96-20241106", + "react-dom": "19.0.0-rc-66855b96-20241106", "react-hook-form": "7.39.5", "swr": "^2.2.0", "tinycolor2": "1.4.2" @@ -62,8 +62,8 @@ "@testing-library/react": "^16.0.1", "@types/ms": "0.7.34", "@types/node": "22.9.0", - "@types/react": "18.3.12", - "@types/react-dom": "18.3.1", + "@types/react": "npm:types-react@19.0.0-rc.1", + "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1", "@types/tinycolor2": "1.4.3", "@types/uuid": "^10.0.0", "@vercel/git-hooks": "1.0.0", diff --git a/apps/login/readme.md b/apps/login/readme.md index 190fcf60026..2aa09da2e49 100644 --- a/apps/login/readme.md +++ b/apps/login/readme.md @@ -116,7 +116,7 @@ If the user has set up an additional **single** second factor, it is redirected **NO MFA, FORCE MFA:** If no MFA method is available, and the settings force MFA, the user is sent to `/mfa/set` which prompts to setup a second factor. -**PROMPT PASSKEY** If the settings do not enforce MFA, we check if passkeys are allowed with `loginSettings?.passkeysType === PasskeysType.ALLOWED` and redirect the user to `/passkey/set` if no passkeys are setup. This step can be skipped. +**PROMPT PASSKEY** If the settings do not enforce MFA, we check if passkeys are allowed with `loginSettings?.passkeysType == PasskeysType.ALLOWED` and redirect the user to `/passkey/set` if no passkeys are setup. This step can be skipped. If none of the previous conditions apply, we continue to sign in. @@ -386,3 +386,10 @@ In future, self service options to jump to are shown below, like: - logout > NOTE: This page has to be explicitly enabled or act as a fallback if no default redirect is set. + +## Currently NOT Supported + +- loginSettings.disableLoginWithEmail +- loginSettings.disableLoginWithPhone +- loginSettings.allowExternalIdp - this will be deprecated with the new login as it can be determined by the available IDPs +- loginSettings.forceMfaLocalOnly diff --git a/apps/login/src/app/(login)/accounts/page.tsx b/apps/login/src/app/(login)/accounts/page.tsx index d8813fada0c..c3944a37688 100644 --- a/apps/login/src/app/(login)/accounts/page.tsx +++ b/apps/login/src/app/(login)/accounts/page.tsx @@ -20,11 +20,10 @@ async function loadSessions() { } } -export default async function Page({ - searchParams, -}: { - searchParams: Record; +export default async function Page(props: { + searchParams: Promise>; }) { + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "accounts" }); diff --git a/apps/login/src/app/(login)/authenticator/set/page.tsx b/apps/login/src/app/(login)/authenticator/set/page.tsx index 78a06ab3296..1c4422327ff 100644 --- a/apps/login/src/app/(login)/authenticator/set/page.tsx +++ b/apps/login/src/app/(login)/authenticator/set/page.tsx @@ -15,11 +15,10 @@ import { import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page({ - searchParams, -}: { - searchParams: Record; +export default async function Page(props: { + searchParams: Promise>; }) { + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "authenticator" }); const tError = await getTranslations({ locale, namespace: "error" }); diff --git a/apps/login/src/app/(login)/idp/[provider]/failure/page.tsx b/apps/login/src/app/(login)/idp/[provider]/failure/page.tsx index 42dcba25fab..a8bc6d9cb50 100644 --- a/apps/login/src/app/(login)/idp/[provider]/failure/page.tsx +++ b/apps/login/src/app/(login)/idp/[provider]/failure/page.tsx @@ -12,13 +12,11 @@ const PROVIDER_NAME_MAPPING: { [IdentityProviderType.AZURE_AD]: "Microsoft", }; -export default async function Page({ - searchParams, - params, -}: { - searchParams: Record; - params: { provider: string }; +export default async function Page(props: { + searchParams: Promise>; + params: Promise<{ provider: string }>; }) { + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "idp" }); diff --git a/apps/login/src/app/(login)/idp/[provider]/success/page.tsx b/apps/login/src/app/(login)/idp/[provider]/success/page.tsx index c7a5f06ca92..48a035f34e1 100644 --- a/apps/login/src/app/(login)/idp/[provider]/success/page.tsx +++ b/apps/login/src/app/(login)/idp/[provider]/success/page.tsx @@ -29,13 +29,12 @@ async function loginFailed(branding?: BrandingSettings) { ); } -export default async function Page({ - searchParams, - params, -}: { - searchParams: Record; - params: { provider: string }; +export default async function Page(props: { + searchParams: Promise>; + params: Promise<{ provider: string }>; }) { + const params = await props.params; + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "idp" }); const { id, token, authRequestId, organization } = searchParams; diff --git a/apps/login/src/app/(login)/idp/page.tsx b/apps/login/src/app/(login)/idp/page.tsx index ee43d5582c6..d11bd8c20a0 100644 --- a/apps/login/src/app/(login)/idp/page.tsx +++ b/apps/login/src/app/(login)/idp/page.tsx @@ -12,11 +12,10 @@ function getIdentityProviders(orgId?: string) { }); } -export default async function Page({ - searchParams, -}: { - searchParams: Record; +export default async function Page(props: { + searchParams: Promise>; }) { + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "idp" }); diff --git a/apps/login/src/app/(login)/invite/page.tsx b/apps/login/src/app/(login)/invite/page.tsx index 83beb9d9bf5..18c60eb993a 100644 --- a/apps/login/src/app/(login)/invite/page.tsx +++ b/apps/login/src/app/(login)/invite/page.tsx @@ -9,11 +9,10 @@ import { } from "@/lib/zitadel"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page({ - searchParams, -}: { - searchParams: Record; +export default async function Page(props: { + searchParams: Promise>; }) { + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "invite" }); diff --git a/apps/login/src/app/(login)/invite/success/page.tsx b/apps/login/src/app/(login)/invite/success/page.tsx index 2cb564580ec..96c49841593 100644 --- a/apps/login/src/app/(login)/invite/success/page.tsx +++ b/apps/login/src/app/(login)/invite/success/page.tsx @@ -7,11 +7,10 @@ import { HumanUser, User } from "@zitadel/proto/zitadel/user/v2/user_pb"; import { getLocale, getTranslations } from "next-intl/server"; import Link from "next/link"; -export default async function Page({ - searchParams, -}: { - searchParams: Record; +export default async function Page(props: { + searchParams: Promise>; }) { + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "invite" }); diff --git a/apps/login/src/app/(login)/layout.tsx b/apps/login/src/app/(login)/layout.tsx index 75820d79905..936c7e17e48 100644 --- a/apps/login/src/app/(login)/layout.tsx +++ b/apps/login/src/app/(login)/layout.tsx @@ -1,54 +1,61 @@ import "@/styles/globals.scss"; +import { LanguageProvider } from "@/components/language-provider"; import { LanguageSwitcher } from "@/components/language-switcher"; +import { Skeleton } from "@/components/skeleton"; import { Theme } from "@/components/theme"; import { ThemeProvider } from "@/components/theme-provider"; import { Analytics } from "@vercel/analytics/react"; -import { NextIntlClientProvider } from "next-intl"; -import { getLocale, getMessages } from "next-intl/server"; import { Lato } from "next/font/google"; -import { ReactNode } from "react"; +import { ReactNode, Suspense } from "react"; const lato = Lato({ weight: ["400", "700", "900"], subsets: ["latin"], }); -export const revalidate = 60; // revalidate every minute - export default async function RootLayout({ children, }: { children: ReactNode; }) { - const locale = await getLocale(); - const messages = await getMessages(); - return ( - + - -
-
- {children} -
- - + +
+ +
+
+
+ +
-
- - - + } + > + +
+
+ {children} +
+ + +
+
+
+
+ + ); diff --git a/apps/login/src/app/(login)/loginname/page.tsx b/apps/login/src/app/(login)/loginname/page.tsx index 68928755d33..55a6682ce16 100644 --- a/apps/login/src/app/(login)/loginname/page.tsx +++ b/apps/login/src/app/(login)/loginname/page.tsx @@ -19,11 +19,10 @@ function getIdentityProviders(orgId?: string) { }); } -export default async function Page({ - searchParams, -}: { - searchParams: Record; +export default async function Page(props: { + searchParams: Promise>; }) { + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "loginname" }); diff --git a/apps/login/src/app/(login)/mfa/page.tsx b/apps/login/src/app/(login)/mfa/page.tsx index f61aa4d988f..071806db04a 100644 --- a/apps/login/src/app/(login)/mfa/page.tsx +++ b/apps/login/src/app/(login)/mfa/page.tsx @@ -12,11 +12,10 @@ import { } from "@/lib/zitadel"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page({ - searchParams, -}: { - searchParams: Record; +export default async function Page(props: { + searchParams: Promise>; }) { + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "mfa" }); const tError = await getTranslations({ locale, namespace: "error" }); diff --git a/apps/login/src/app/(login)/mfa/set/page.tsx b/apps/login/src/app/(login)/mfa/set/page.tsx index 80ea4638d37..dce54618dc1 100644 --- a/apps/login/src/app/(login)/mfa/set/page.tsx +++ b/apps/login/src/app/(login)/mfa/set/page.tsx @@ -32,11 +32,10 @@ function isSessionValid(session: Partial): { return { valid, verifiedAt }; } -export default async function Page({ - searchParams, -}: { - searchParams: Record; +export default async function Page(props: { + searchParams: Promise>; }) { + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "mfa" }); const tError = await getTranslations({ locale, namespace: "error" }); diff --git a/apps/login/src/app/(login)/otp/[method]/page.tsx b/apps/login/src/app/(login)/otp/[method]/page.tsx index 7109d58f115..9c91b3edd26 100644 --- a/apps/login/src/app/(login)/otp/[method]/page.tsx +++ b/apps/login/src/app/(login)/otp/[method]/page.tsx @@ -3,16 +3,15 @@ import { DynamicTheme } from "@/components/dynamic-theme"; import { LoginOTP } from "@/components/login-otp"; import { UserAvatar } from "@/components/user-avatar"; import { loadMostRecentSession } from "@/lib/session"; -import { getBrandingSettings } from "@/lib/zitadel"; +import { getBrandingSettings, getLoginSettings } from "@/lib/zitadel"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page({ - searchParams, - params, -}: { - searchParams: Record; - params: Record; +export default async function Page(props: { + searchParams: Promise>; + params: Promise>; }) { + const params = await props.params; + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "otp" }); const tError = await getTranslations({ locale, namespace: "error" }); @@ -29,6 +28,8 @@ export default async function Page({ const branding = await getBrandingSettings(organization); + const loginSettings = await getLoginSettings(organization); + return (
@@ -65,6 +66,7 @@ export default async function Page({ authRequestId={authRequestId} organization={organization} method={method} + loginSettings={loginSettings} > )}
diff --git a/apps/login/src/app/(login)/otp/[method]/set/page.tsx b/apps/login/src/app/(login)/otp/[method]/set/page.tsx index b08a1facdee..e64b4debe0f 100644 --- a/apps/login/src/app/(login)/otp/[method]/set/page.tsx +++ b/apps/login/src/app/(login)/otp/[method]/set/page.tsx @@ -9,6 +9,7 @@ import { addOTPEmail, addOTPSMS, getBrandingSettings, + getLoginSettings, registerTOTP, } from "@/lib/zitadel"; import { RegisterTOTPResponse } from "@zitadel/proto/zitadel/user/v2/user_service_pb"; @@ -16,13 +17,12 @@ import { getLocale, getTranslations } from "next-intl/server"; import Link from "next/link"; import { redirect } from "next/navigation"; -export default async function Page({ - searchParams, - params, -}: { - searchParams: Record; - params: Record; +export default async function Page(props: { + searchParams: Promise>; + params: Promise>; }) { + const params = await props.params; + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "otp" }); const tError = await getTranslations({ locale, namespace: "error" }); @@ -32,6 +32,8 @@ export default async function Page({ const { method } = params; const branding = await getBrandingSettings(organization); + const loginSettings = await getLoginSettings(organization); + const session = await loadMostRecentSession({ loginName, organization, @@ -137,6 +139,7 @@ export default async function Page({ authRequestId={authRequestId} organization={organization} checkAfter={checkAfter === "true"} + loginSettings={loginSettings} >
{" "} diff --git a/apps/login/src/app/(login)/passkey/page.tsx b/apps/login/src/app/(login)/passkey/page.tsx index fc0f701e805..0804f3ce2ea 100644 --- a/apps/login/src/app/(login)/passkey/page.tsx +++ b/apps/login/src/app/(login)/passkey/page.tsx @@ -4,14 +4,17 @@ import { LoginPasskey } from "@/components/login-passkey"; import { UserAvatar } from "@/components/user-avatar"; import { getSessionCookieById } from "@/lib/cookies"; import { loadMostRecentSession } from "@/lib/session"; -import { getBrandingSettings, getSession } from "@/lib/zitadel"; +import { + getBrandingSettings, + getLoginSettings, + getSession, +} from "@/lib/zitadel"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page({ - searchParams, -}: { - searchParams: Record; +export default async function Page(props: { + searchParams: Promise>; }) { + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "passkey" }); const tError = await getTranslations({ locale, namespace: "error" }); @@ -37,6 +40,8 @@ export default async function Page({ const branding = await getBrandingSettings(organization); + const loginSettings = await getLoginSettings(organization); + return (
@@ -61,6 +66,7 @@ export default async function Page({ authRequestId={authRequestId} altPassword={altPassword === "true"} organization={organization} + loginSettings={loginSettings} /> )}
diff --git a/apps/login/src/app/(login)/passkey/set/page.tsx b/apps/login/src/app/(login)/passkey/set/page.tsx index 45ea1d78035..26a2de24284 100644 --- a/apps/login/src/app/(login)/passkey/set/page.tsx +++ b/apps/login/src/app/(login)/passkey/set/page.tsx @@ -6,11 +6,10 @@ import { loadMostRecentSession } from "@/lib/session"; import { getBrandingSettings } from "@/lib/zitadel"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page({ - searchParams, -}: { - searchParams: Record; +export default async function Page(props: { + searchParams: Promise>; }) { + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "passkey" }); const tError = await getTranslations({ locale, namespace: "error" }); diff --git a/apps/login/src/app/(login)/password/change/page.tsx b/apps/login/src/app/(login)/password/change/page.tsx index 55b8c0ad49d..1ba48a589dc 100644 --- a/apps/login/src/app/(login)/password/change/page.tsx +++ b/apps/login/src/app/(login)/password/change/page.tsx @@ -10,11 +10,10 @@ import { } from "@/lib/zitadel"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page({ - searchParams, -}: { - searchParams: Record; +export default async function Page(props: { + searchParams: Promise>; }) { + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "password" }); const tError = await getTranslations({ locale, namespace: "error" }); diff --git a/apps/login/src/app/(login)/password/page.tsx b/apps/login/src/app/(login)/password/page.tsx index 9731e4030e8..a2c10c32380 100644 --- a/apps/login/src/app/(login)/password/page.tsx +++ b/apps/login/src/app/(login)/password/page.tsx @@ -12,11 +12,10 @@ import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb"; import { PasskeysType } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page({ - searchParams, -}: { - searchParams: Record; +export default async function Page(props: { + searchParams: Promise>; }) { + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "password" }); const tError = await getTranslations({ locale, namespace: "error" }); @@ -83,7 +82,7 @@ export default async function Page({ organization={organization} // stick to "organization" as we still want to do user discovery based on the searchParams not the default organization, later the organization is determined by the found user loginSettings={loginSettings} promptPasswordless={ - loginSettings?.passkeysType === PasskeysType.ALLOWED + loginSettings?.passkeysType == PasskeysType.ALLOWED } isAlternative={alt === "true"} /> diff --git a/apps/login/src/app/(login)/password/set/page.tsx b/apps/login/src/app/(login)/password/set/page.tsx index b7cd7c0d1bd..d60ac7023c2 100644 --- a/apps/login/src/app/(login)/password/set/page.tsx +++ b/apps/login/src/app/(login)/password/set/page.tsx @@ -13,11 +13,10 @@ import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb"; import { HumanUser, User } from "@zitadel/proto/zitadel/user/v2/user_pb"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page({ - searchParams, -}: { - searchParams: Record; +export default async function Page(props: { + searchParams: Promise>; }) { + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "password" }); const tError = await getTranslations({ locale, namespace: "error" }); diff --git a/apps/login/src/app/(login)/register/page.tsx b/apps/login/src/app/(login)/register/page.tsx index f23582ae3f7..2cd1c353466 100644 --- a/apps/login/src/app/(login)/register/page.tsx +++ b/apps/login/src/app/(login)/register/page.tsx @@ -1,20 +1,19 @@ import { DynamicTheme } from "@/components/dynamic-theme"; -import { RegisterFormWithoutPassword } from "@/components/register-form-without-password"; -import { SetRegisterPasswordForm } from "@/components/set-register-password-form"; +import { RegisterForm } from "@/components/register-form"; import { getBrandingSettings, getDefaultOrg, getLegalAndSupportSettings, + getLoginSettings, getPasswordComplexitySettings, } from "@/lib/zitadel"; import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page({ - searchParams, -}: { - searchParams: Record; +export default async function Page(props: { + searchParams: Promise>; }) { + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "register" }); @@ -28,47 +27,41 @@ export default async function Page({ } } - const setPassword = !!(firstname && lastname && email); - const legal = await getLegalAndSupportSettings(organization); const passwordComplexitySettings = await getPasswordComplexitySettings(organization); const branding = await getBrandingSettings(organization); - return setPassword ? ( - -
-

{t("password.title")}

-

{t("description")}

+ const loginSettings = await getLoginSettings(organization); - {legal && passwordComplexitySettings && ( - - )} -
-
- ) : ( + if (!loginSettings?.allowRegister) { + return ( + +
+

{t("disabled.title")}

+

{t("disabled.description")}

+
+
+ ); + } + + return (

{t("title")}

{t("description")}

{legal && passwordComplexitySettings && ( - + loginSettings={loginSettings} + > )}
diff --git a/apps/login/src/app/(login)/register/password/page.tsx b/apps/login/src/app/(login)/register/password/page.tsx new file mode 100644 index 00000000000..48e454c3128 --- /dev/null +++ b/apps/login/src/app/(login)/register/password/page.tsx @@ -0,0 +1,73 @@ +import { DynamicTheme } from "@/components/dynamic-theme"; +import { SetRegisterPasswordForm } from "@/components/set-register-password-form"; +import { + getBrandingSettings, + getDefaultOrg, + getLegalAndSupportSettings, + getLoginSettings, + getPasswordComplexitySettings, +} from "@/lib/zitadel"; +import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb"; +import { getLocale, getTranslations } from "next-intl/server"; + +export default async function Page(props: { + searchParams: Promise>; +}) { + const searchParams = await props.searchParams; + const locale = getLocale(); + const t = await getTranslations({ locale, namespace: "register" }); + + let { firstname, lastname, email, organization, authRequestId } = + searchParams; + + if (!organization) { + const org: Organization | null = await getDefaultOrg(); + if (org) { + organization = org.id; + } + } + + const missingData = !firstname || !lastname || !email; + + const legal = await getLegalAndSupportSettings(organization); + const passwordComplexitySettings = + await getPasswordComplexitySettings(organization); + + const branding = await getBrandingSettings(organization); + + const loginSettings = await getLoginSettings(organization); + + return missingData ? ( + +
+

{t("missingdata.title")}

+

{t("missingdata.description")}

+
+
+ ) : loginSettings?.allowRegister && loginSettings.allowUsernamePassword ? ( + +
+

{t("password.title")}

+

{t("description")}

+ + {legal && passwordComplexitySettings && ( + + )} +
+
+ ) : ( + +
+

{t("disabled.title")}

+

{t("disabled.description")}

+
+
+ ); +} diff --git a/apps/login/src/app/(login)/signedin/page.tsx b/apps/login/src/app/(login)/signedin/page.tsx index b2274478ea5..4fc9ac85464 100644 --- a/apps/login/src/app/(login)/signedin/page.tsx +++ b/apps/login/src/app/(login)/signedin/page.tsx @@ -1,14 +1,21 @@ +import { Button, ButtonVariants } from "@/components/button"; import { DynamicTheme } from "@/components/dynamic-theme"; import { SelfServiceMenu } from "@/components/self-service-menu"; import { UserAvatar } from "@/components/user-avatar"; import { getMostRecentCookieWithLoginname } from "@/lib/cookies"; -import { createCallback, getBrandingSettings, getSession } from "@/lib/zitadel"; +import { + createCallback, + getBrandingSettings, + getLoginSettings, + getSession, +} from "@/lib/zitadel"; import { create } from "@zitadel/client"; import { CreateCallbackRequestSchema, SessionSchema, } from "@zitadel/proto/zitadel/oidc/v2/oidc_service_pb"; import { getLocale, getTranslations } from "next-intl/server"; +import Link from "next/link"; import { redirect } from "next/navigation"; async function loadSession(loginName: string, authRequestId?: string) { @@ -39,7 +46,8 @@ async function loadSession(loginName: string, authRequestId?: string) { ); } -export default async function Page({ searchParams }: { searchParams: any }) { +export default async function Page(props: { searchParams: Promise }) { + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "signedin" }); @@ -48,6 +56,11 @@ export default async function Page({ searchParams }: { searchParams: any }) { const branding = await getBrandingSettings(organization); + let loginSettings; + if (!authRequestId) { + loginSettings = await getLoginSettings(organization); + } + return (
@@ -66,6 +79,22 @@ export default async function Page({ searchParams }: { searchParams: any }) { {sessionFactors?.id && ( )} + + {loginSettings?.defaultRedirectUri && ( +
+ + + + + +
+ )}
); diff --git a/apps/login/src/app/(login)/u2f/page.tsx b/apps/login/src/app/(login)/u2f/page.tsx index 36fef6d7869..e4dd2bd8d20 100644 --- a/apps/login/src/app/(login)/u2f/page.tsx +++ b/apps/login/src/app/(login)/u2f/page.tsx @@ -7,11 +7,10 @@ import { loadMostRecentSession } from "@/lib/session"; import { getBrandingSettings, getSession } from "@/lib/zitadel"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page({ - searchParams, -}: { - searchParams: Record; +export default async function Page(props: { + searchParams: Promise>; }) { + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "u2f" }); const tError = await getTranslations({ locale, namespace: "error" }); diff --git a/apps/login/src/app/(login)/u2f/set/page.tsx b/apps/login/src/app/(login)/u2f/set/page.tsx index d35bcd4ddb0..f9f3daeaba2 100644 --- a/apps/login/src/app/(login)/u2f/set/page.tsx +++ b/apps/login/src/app/(login)/u2f/set/page.tsx @@ -6,11 +6,10 @@ import { loadMostRecentSession } from "@/lib/session"; import { getBrandingSettings } from "@/lib/zitadel"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page({ - searchParams, -}: { - searchParams: Record; +export default async function Page(props: { + searchParams: Promise>; }) { + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "u2f" }); const tError = await getTranslations({ locale, namespace: "error" }); diff --git a/apps/login/src/app/(login)/verify/page.tsx b/apps/login/src/app/(login)/verify/page.tsx index ed216ea317f..fc11f459219 100644 --- a/apps/login/src/app/(login)/verify/page.tsx +++ b/apps/login/src/app/(login)/verify/page.tsx @@ -12,7 +12,8 @@ import { HumanUser, User } from "@zitadel/proto/zitadel/user/v2/user_pb"; import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page({ searchParams }: { searchParams: any }) { +export default async function Page(props: { searchParams: Promise }) { + const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "verify" }); const tError = await getTranslations({ locale, namespace: "error" }); diff --git a/apps/login/src/components/authentication-method-radio.tsx b/apps/login/src/components/authentication-method-radio.tsx index 9e0af959215..1b2af2d167f 100644 --- a/apps/login/src/components/authentication-method-radio.tsx +++ b/apps/login/src/components/authentication-method-radio.tsx @@ -1,16 +1,16 @@ "use client"; import { RadioGroup } from "@headlessui/react"; +import { useTranslations } from "next-intl"; + +export enum AuthenticationMethod { + Passkey = "passkey", + Password = "password", +} export const methods = [ - { - name: "Passkeys", - description: "Authenticate with your device.", - }, - { - name: "Password", - description: "Authenticate with a password", - }, + AuthenticationMethod.Passkey, + AuthenticationMethod.Password, ]; export function AuthenticationMethodRadio({ @@ -20,58 +20,68 @@ export function AuthenticationMethodRadio({ selected: any; selectionChanged: (value: any) => void; }) { + const t = useTranslations("register"); + return (
Server size -
+
{methods.map((method) => ( `${ active - ? "h-full ring-2 ring-opacity-60 ring-primary-light-500 dark:ring-white/20" - : "h-full " + ? "ring-2 ring-opacity-60 ring-primary-light-500 dark:ring-white/20" + : "" } ${ checked - ? "bg-background-light-400 dark:bg-background-dark-400" + ? "bg-background-light-400 dark:bg-background-dark-400 ring-2 ring-primary-light-500 dark:ring-primary-dark-500" : "bg-background-light-400 dark:bg-background-dark-400" } - relative border boder-divider-light dark:border-divider-dark flex cursor-pointer rounded-lg px-5 py-4 focus:outline-none hover:shadow-lg dark:hover:bg-white/10` + h-full flex-1 relative border boder-divider-light dark:border-divider-dark flex cursor-pointer rounded-lg px-5 py-4 focus:outline-none hover:shadow-lg dark:hover:bg-white/10` } > {({ active, checked }) => ( <> -
-
-
- - {method.name} - - - {method.description} - {" "} - -
-
- {checked && ( -
- -
+
+ {method === "passkey" && ( + + + )} + {method === "password" && ( + + form-textbox-password + + + )} + + {t(`methods.${method}`)} +
)} @@ -83,24 +93,3 @@ export function AuthenticationMethodRadio({
); } - -function CheckIcon(props: any) { - return ( - - - - - ); -} diff --git a/apps/login/src/components/change-password-form.tsx b/apps/login/src/components/change-password-form.tsx index c2e891ffb80..e43e71f7528 100644 --- a/apps/login/src/components/change-password-form.tsx +++ b/apps/login/src/components/change-password-form.tsx @@ -12,7 +12,6 @@ import { create } from "@zitadel/client"; import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb"; import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb"; import { useTranslations } from "next-intl"; -import { redirect } from "next/navigation"; import { useState } from "react"; import { FieldValues, useForm } from "react-hook-form"; import { Alert } from "./alert"; @@ -65,6 +64,7 @@ export function ChangePasswordForm({ }) .catch(() => { setError("Could not change password"); + return; }) .finally(() => { setLoading(false); @@ -107,10 +107,6 @@ export function ChangePasswordForm({ return; } - if (passwordResponse && passwordResponse.nextStep) { - return redirect(passwordResponse.nextStep); - } - return; } diff --git a/apps/login/src/components/choose-authenticator-to-setup.tsx b/apps/login/src/components/choose-authenticator-to-setup.tsx index 25ca69e7768..9075e3286e7 100644 --- a/apps/login/src/components/choose-authenticator-to-setup.tsx +++ b/apps/login/src/components/choose-authenticator-to-setup.tsx @@ -25,7 +25,7 @@ export function ChooseAuthenticatorToSetup({ } else { return ( <> - {loginSettings.passkeysType === PasskeysType.NOT_ALLOWED && + {loginSettings.passkeysType == PasskeysType.NOT_ALLOWED && !loginSettings.allowUsernamePassword && ( {t("noMethodsAvailable")} )} @@ -35,7 +35,7 @@ export function ChooseAuthenticatorToSetup({ loginSettings.allowUsernamePassword && PASSWORD(false, "/password/set?" + params)} {!authMethods.includes(AuthenticationMethodType.PASSKEY) && - loginSettings.passkeysType === PasskeysType.ALLOWED && + loginSettings.passkeysType == PasskeysType.ALLOWED && PASSKEYS(false, "/passkey/set?" + params)}
diff --git a/apps/login/src/components/idp-signin.tsx b/apps/login/src/components/idp-signin.tsx index dfed09839f4..6613e7bffda 100644 --- a/apps/login/src/components/idp-signin.tsx +++ b/apps/login/src/components/idp-signin.tsx @@ -35,30 +35,18 @@ export function IdpSignin({ }, authRequestId, }) - .then((session) => { - if (authRequestId && session && session.id) { - return router.push( - `/login?` + - new URLSearchParams({ - sessionId: session.id, - authRequest: authRequestId, - }), - ); - } else { - const params = new URLSearchParams({}); - if (session.factors?.user?.loginName) { - params.set("loginName", session.factors?.user?.loginName); - } + .then((response) => { + if (response && "error" in response && response?.error) { + setError(response?.error); + return; + } - if (authRequestId) { - params.set("authRequestId", authRequestId); - } - - return router.push(`/signedin?` + params); + if (response && "redirect" in response && response?.redirect) { + return router.push(response.redirect); } }) - .catch((error) => { - setError(error.message); + .catch(() => { + setError("An internal error occurred"); return; }) .finally(() => { diff --git a/apps/login/src/components/input.tsx b/apps/login/src/components/input.tsx index f1c88a2deeb..0cb9e584678 100644 --- a/apps/login/src/components/input.tsx +++ b/apps/login/src/components/input.tsx @@ -1,4 +1,5 @@ "use client"; + import { CheckCircleIcon } from "@heroicons/react/24/solid"; import { clsx } from "clsx"; import { @@ -64,6 +65,7 @@ export const TextInput = forwardRef( {label} {required && "*"} + {children} + + ); +} diff --git a/apps/login/src/components/login-otp.tsx b/apps/login/src/components/login-otp.tsx index 971920606ef..27fa187c7d3 100644 --- a/apps/login/src/components/login-otp.tsx +++ b/apps/login/src/components/login-otp.tsx @@ -1,9 +1,11 @@ "use client"; +import { getNextUrl } from "@/lib/client"; import { updateSession } from "@/lib/server/session"; import { create } from "@zitadel/client"; import { RequestChallengesSchema } from "@zitadel/proto/zitadel/session/v2/challenge_pb"; import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb"; +import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb"; import { useTranslations } from "next-intl"; import { useRouter } from "next/navigation"; import { useEffect, useRef, useState } from "react"; @@ -22,6 +24,7 @@ type Props = { organization?: string; method: string; code?: string; + loginSettings?: LoginSettings; }; type Inputs = { @@ -35,6 +38,7 @@ export function LoginOTP({ organization, method, code, + loginSettings, }: Props) { const t = useTranslations("otp"); @@ -59,6 +63,7 @@ export function LoginOTP({ updateSessionForOTPChallenge() .catch((error) => { setError(error); + return; }) .finally(() => { setLoading(false); @@ -91,6 +96,7 @@ export function LoginOTP({ }) .catch((error) => { setError(error.message ?? "Could not request OTP challenge"); + return; }) .finally(() => { setLoading(false); @@ -152,41 +158,30 @@ export function LoginOTP({ } function setCodeAndContinue(values: Inputs, organization?: string) { - return submitCode(values, organization).then((response) => { + return submitCode(values, organization).then(async (response) => { if (response) { - if (authRequestId && response && response.sessionId) { - const params = new URLSearchParams({ - sessionId: response.sessionId, - authRequest: authRequestId, - }); + const url = + authRequestId && response.sessionId + ? await getNextUrl( + { + sessionId: response.sessionId, + authRequestId: authRequestId, + organization: response.factors?.user?.organizationId, + }, + loginSettings?.defaultRedirectUri, + ) + : response.factors?.user + ? await getNextUrl( + { + loginName: response.factors.user.loginName, + organization: response.factors?.user?.organizationId, + }, + loginSettings?.defaultRedirectUri, + ) + : null; - if (organization) { - params.append("organization", organization); - } - - if (authRequestId) { - params.append("authRequest", authRequestId); - } - - if (sessionId) { - params.append("sessionId", sessionId); - } - - return router.push(`/login?` + params); - } else { - const params = new URLSearchParams(); - if (response?.factors?.user?.loginName) { - params.append("loginName", response.factors.user.loginName); - } - if (authRequestId) { - params.append("authRequestId", authRequestId); - } - - if (organization) { - params.append("organization", organization); - } - - return router.push(`/signedin?` + params); + if (url) { + router.push(url); } } }); @@ -209,6 +204,7 @@ export function LoginOTP({ updateSessionForOTPChallenge() .catch((error) => { setError(error); + return; }) .finally(() => { setLoading(false); diff --git a/apps/login/src/components/login-passkey.tsx b/apps/login/src/components/login-passkey.tsx index c19450b42fd..d72749e7572 100644 --- a/apps/login/src/components/login-passkey.tsx +++ b/apps/login/src/components/login-passkey.tsx @@ -1,6 +1,7 @@ "use client"; import { coerceToArrayBuffer, coerceToBase64Url } from "@/helpers/base64"; +import { getNextUrl } from "@/lib/client"; import { updateSession } from "@/lib/server/session"; import { create } from "@zitadel/client"; import { @@ -8,6 +9,7 @@ import { UserVerificationRequirement, } from "@zitadel/proto/zitadel/session/v2/challenge_pb"; import { Checks } from "@zitadel/proto/zitadel/session/v2/session_service_pb"; +import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb"; import { useTranslations } from "next-intl"; import { useRouter } from "next/navigation"; import { useEffect, useRef, useState } from "react"; @@ -24,6 +26,7 @@ type Props = { altPassword: boolean; login?: boolean; organization?: string; + loginSettings?: LoginSettings; }; export function LoginPasskey({ @@ -33,6 +36,7 @@ export function LoginPasskey({ altPassword, organization, login = true, + loginSettings, }: Props) { const t = useTranslations("passkey"); @@ -63,6 +67,7 @@ export function LoginPasskey({ return submitLoginAndContinue(pK) .catch((error) => { setError(error); + return; }) .finally(() => { setLoading(false); @@ -70,6 +75,7 @@ export function LoginPasskey({ }) .catch((error) => { setError(error); + return; }) .finally(() => { setLoading(false); @@ -98,6 +104,7 @@ export function LoginPasskey({ }) .catch(() => { setError("Could not request passkey challenge"); + return; }) .finally(() => { setLoading(false); @@ -119,6 +126,7 @@ export function LoginPasskey({ }) .catch(() => { setError("Could not verify passkey"); + return; }) .finally(() => { setLoading(false); @@ -147,7 +155,6 @@ export function LoginPasskey({ }) .then((assertedCredential: any) => { if (!assertedCredential) { - setLoading(false); setError("An error on retrieving passkey"); return; } @@ -175,28 +182,34 @@ export function LoginPasskey({ }, }; - return submitLogin(data).then((resp) => { - if (authRequestId && resp && resp.sessionId) { - return router.push( - `/login?` + - new URLSearchParams({ - sessionId: resp.sessionId, - authRequest: authRequestId, - }), - ); - } else { - const params = new URLSearchParams({}); + return submitLogin(data).then(async (resp) => { + const url = + authRequestId && resp?.sessionId + ? await getNextUrl( + { + sessionId: resp.sessionId, + authRequestId: authRequestId, + organization: organization, + }, + loginSettings?.defaultRedirectUri, + ) + : resp?.factors?.user?.loginName + ? await getNextUrl( + { + loginName: resp.factors.user.loginName, + organization: organization, + }, + loginSettings?.defaultRedirectUri, + ) + : null; - if (authRequestId) { - params.set("authRequestId", authRequestId); - } - if (resp?.factors?.user?.loginName) { - params.set("loginName", resp.factors.user.loginName); - } - - return router.push(`/signedin?` + params); + if (url) { + router.push(url); } }); + }) + .finally(() => { + setLoading(false); }); } @@ -268,6 +281,7 @@ export function LoginPasskey({ return submitLoginAndContinue(pK) .catch((error) => { setError(error); + return; }) .finally(() => { setLoading(false); diff --git a/apps/login/src/components/password-form.tsx b/apps/login/src/components/password-form.tsx index 5885ecc6d44..6f810ac30f8 100644 --- a/apps/login/src/components/password-form.tsx +++ b/apps/login/src/components/password-form.tsx @@ -74,8 +74,8 @@ export function PasswordForm({ return; } - if (response && response.nextStep) { - return router.push(response.nextStep); + if (response && "redirect" in response && response.redirect) { + return router.push(response.redirect); } } diff --git a/apps/login/src/components/register-form-without-password.tsx b/apps/login/src/components/register-form.tsx similarity index 74% rename from apps/login/src/components/register-form-without-password.tsx rename to apps/login/src/components/register-form.tsx index 7e6fa273d80..c336b836c4d 100644 --- a/apps/login/src/components/register-form-without-password.tsx +++ b/apps/login/src/components/register-form.tsx @@ -2,12 +2,17 @@ import { registerUser } from "@/lib/server/register"; import { LegalAndSupportSettings } from "@zitadel/proto/zitadel/settings/v2/legal_settings_pb"; +import { + LoginSettings, + PasskeysType, +} from "@zitadel/proto/zitadel/settings/v2/login_settings_pb"; import { useTranslations } from "next-intl"; import { useRouter } from "next/navigation"; import { useState } from "react"; import { FieldValues, useForm } from "react-hook-form"; import { Alert } from "./alert"; import { + AuthenticationMethod, AuthenticationMethodRadio, methods, } from "./authentication-method-radio"; @@ -32,15 +37,17 @@ type Props = { email?: string; organization?: string; authRequestId?: string; + loginSettings?: LoginSettings; }; -export function RegisterFormWithoutPassword({ +export function RegisterForm({ legal, email, firstname, lastname, organization, authRequestId, + loginSettings, }: Props) { const t = useTranslations("register"); @@ -54,7 +61,7 @@ export function RegisterFormWithoutPassword({ }); const [loading, setLoading] = useState(false); - const [selected, setSelected] = useState(methods[0]); + const [selected, setSelected] = useState(methods[0]); const [error, setError] = useState(""); const router = useRouter(); @@ -76,11 +83,15 @@ export function RegisterFormWithoutPassword({ setLoading(false); }); - if (response && "error" in response) { + if (response && "error" in response && response.error) { setError(response.error); return; } + if (response && "redirect" in response && response.redirect) { + return router.push(response.redirect); + } + return response; } @@ -98,8 +109,11 @@ export function RegisterFormWithoutPassword({ registerParams.authRequestId = authRequestId; } + // redirect user to /register/password if password is chosen if (withPassword) { - return router.push(`/register?` + new URLSearchParams(registerParams)); + return router.push( + `/register/password?` + new URLSearchParams(registerParams), + ); } else { return submitAndRegister(value); } @@ -108,7 +122,6 @@ export function RegisterFormWithoutPassword({ const { errors } = formState; const [tosAndPolicyAccepted, setTosAndPolicyAccepted] = useState(false); - return (
@@ -146,38 +159,45 @@ export function RegisterFormWithoutPassword({ />
- {legal && ( )} -

{t("selectMethod")}

- -
- -
+ {/* show chooser if both methods are allowed */} + {loginSettings && + loginSettings.allowUsernamePassword && + loginSettings.passkeysType == PasskeysType.ALLOWED && ( +
+ +
+ )} {error && (
{error}
)} -
); } diff --git a/apps/login/src/components/sessions-list.tsx b/apps/login/src/components/sessions-list.tsx index 85c67e4b023..63b8fa11020 100644 --- a/apps/login/src/components/sessions-list.tsx +++ b/apps/login/src/components/sessions-list.tsx @@ -1,5 +1,6 @@ "use client"; +import { timestampMs } from "@zitadel/client"; import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb"; import { useTranslations } from "next-intl"; import { useState } from "react"; @@ -11,6 +12,14 @@ type Props = { authRequestId?: string; }; +function sortFc(a: Session, b: Session) { + if (a.changeDate && b.changeDate) { + return timestampMs(a.changeDate) - timestampMs(b.changeDate); + } else { + return 0; + } +} + export function SessionsList({ sessions, authRequestId }: Props) { const t = useTranslations("accounts"); const [list, setList] = useState(sessions); @@ -18,6 +27,7 @@ export function SessionsList({ sessions, authRequestId }: Props) {
{list .filter((session) => session?.factors?.user?.loginName) + .sort(sortFc) .map((session, index) => { return ( (false); const [error, setError] = useState(""); + const router = useRouter(); + async function submitPassword(values: Inputs) { setLoading(true); let payload: { userId: string; password: string; code?: string } = { @@ -127,8 +129,12 @@ export function SetPasswordForm({ return; } - if (passwordResponse && passwordResponse.nextStep) { - return redirect(passwordResponse.nextStep); + if ( + passwordResponse && + "redirect" in passwordResponse && + passwordResponse.redirect + ) { + return router.push(passwordResponse.redirect); } return; diff --git a/apps/login/src/components/set-register-password-form.tsx b/apps/login/src/components/set-register-password-form.tsx index 21ad533854b..19bab38e10b 100644 --- a/apps/login/src/components/set-register-password-form.tsx +++ b/apps/login/src/components/set-register-password-form.tsx @@ -9,6 +9,7 @@ import { import { registerUser } from "@/lib/server/register"; import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb"; import { useTranslations } from "next-intl"; +import { useRouter } from "next/navigation"; import { useState } from "react"; import { FieldValues, useForm } from "react-hook-form"; import { Alert } from "./alert"; @@ -56,6 +57,8 @@ export function SetRegisterPasswordForm({ const [loading, setLoading] = useState(false); const [error, setError] = useState(""); + const router = useRouter(); + async function submitRegister(values: Inputs) { setLoading(true); const response = await registerUser({ @@ -68,15 +71,20 @@ export function SetRegisterPasswordForm({ }) .catch(() => { setError("Could not register user"); + return; }) .finally(() => { setLoading(false); }); - if (response && "error" in response) { + if (response && "error" in response && response.error) { setError(response.error); return; } + + if (response && "redirect" in response && response.redirect) { + return router.push(response.redirect); + } } const { errors } = formState; diff --git a/apps/login/src/components/sign-in-with-idp.tsx b/apps/login/src/components/sign-in-with-idp.tsx index 90520d449bc..bab837d9d8a 100644 --- a/apps/login/src/components/sign-in-with-idp.tsx +++ b/apps/login/src/components/sign-in-with-idp.tsx @@ -56,22 +56,14 @@ export function SignInWithIdp({ }) .catch(() => { setError("Could not start IDP flow"); + return; }) .finally(() => { setLoading(false); }); - return response; - } - - async function navigateToAuthUrl(id: string, type: IdentityProviderType) { - const startFlowResponse = await startFlow(id, idpTypeToSlug(type)); - if ( - startFlowResponse && - startFlowResponse.nextStep.case === "authUrl" && - startFlowResponse?.nextStep.value - ) { - router.push(startFlowResponse.nextStep.value); + if (response && "redirect" in response && response?.redirect) { + return router.push(response.redirect); } } @@ -86,7 +78,7 @@ export function SignInWithIdp({ key={`idp-${i}`} name={idp.name} onClick={() => - navigateToAuthUrl(idp.id, IdentityProviderType.APPLE) + startFlow(idp.id, idpTypeToSlug(IdentityProviderType.APPLE)) } > ); @@ -96,7 +88,7 @@ export function SignInWithIdp({ key={`idp-${i}`} name={idp.name} onClick={() => - navigateToAuthUrl(idp.id, IdentityProviderType.OAUTH) + startFlow(idp.id, idpTypeToSlug(IdentityProviderType.OAUTH)) } > ); @@ -106,7 +98,7 @@ export function SignInWithIdp({ key={`idp-${i}`} name={idp.name} onClick={() => - navigateToAuthUrl(idp.id, IdentityProviderType.OIDC) + startFlow(idp.id, idpTypeToSlug(IdentityProviderType.OIDC)) } > ); @@ -116,7 +108,10 @@ export function SignInWithIdp({ key={`idp-${i}`} name={idp.name} onClick={() => - navigateToAuthUrl(idp.id, IdentityProviderType.GITHUB) + startFlow( + idp.id, + idpTypeToSlug(IdentityProviderType.GITHUB), + ) } > ); @@ -126,7 +121,10 @@ export function SignInWithIdp({ key={`idp-${i}`} name={idp.name} onClick={() => - navigateToAuthUrl(idp.id, IdentityProviderType.GITHUB_ES) + startFlow( + idp.id, + idpTypeToSlug(IdentityProviderType.GITHUB_ES), + ) } > ); @@ -136,7 +134,10 @@ export function SignInWithIdp({ key={`idp-${i}`} name={idp.name} onClick={() => - navigateToAuthUrl(idp.id, IdentityProviderType.AZURE_AD) + startFlow( + idp.id, + idpTypeToSlug(IdentityProviderType.AZURE_AD), + ) } > ); @@ -147,7 +148,10 @@ export function SignInWithIdp({ e2e="google" name={idp.name} onClick={() => - navigateToAuthUrl(idp.id, IdentityProviderType.GOOGLE) + startFlow( + idp.id, + idpTypeToSlug(IdentityProviderType.GOOGLE), + ) } > ); @@ -157,7 +161,10 @@ export function SignInWithIdp({ key={`idp-${i}`} name={idp.name} onClick={() => - navigateToAuthUrl(idp.id, IdentityProviderType.GITLAB) + startFlow( + idp.id, + idpTypeToSlug(IdentityProviderType.GITLAB), + ) } > ); @@ -167,9 +174,9 @@ export function SignInWithIdp({ key={`idp-${i}`} name={idp.name} onClick={() => - navigateToAuthUrl( + startFlow( idp.id, - IdentityProviderType.GITLAB_SELF_HOSTED, + idpTypeToSlug(IdentityProviderType.GITLAB_SELF_HOSTED), ) } > diff --git a/apps/login/src/components/skeleton.tsx b/apps/login/src/components/skeleton.tsx new file mode 100644 index 00000000000..548953d278c --- /dev/null +++ b/apps/login/src/components/skeleton.tsx @@ -0,0 +1,9 @@ +import { ReactNode } from "react"; + +export function Skeleton({ children }: { children?: ReactNode }) { + return ( +
+ {children} +
+ ); +} diff --git a/apps/login/src/components/totp-register.tsx b/apps/login/src/components/totp-register.tsx index 6aa515a1190..e3b5985aea2 100644 --- a/apps/login/src/components/totp-register.tsx +++ b/apps/login/src/components/totp-register.tsx @@ -1,5 +1,7 @@ "use client"; +import { getNextUrl } from "@/lib/client"; import { verifyTOTP } from "@/lib/server-actions"; +import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb"; import { useTranslations } from "next-intl"; import Link from "next/link"; import { useRouter } from "next/navigation"; @@ -24,6 +26,7 @@ type Props = { authRequestId?: string; organization?: string; checkAfter?: boolean; + loginSettings?: LoginSettings; }; export function TotpRegister({ uri, @@ -33,6 +36,7 @@ export function TotpRegister({ authRequestId, organization, checkAfter, + loginSettings, }: Props) { const t = useTranslations("otp"); @@ -50,7 +54,7 @@ export function TotpRegister({ async function continueWithCode(values: Inputs) { setLoading(true); return verifyTOTP(values.code, loginName, organization) - .then((response) => { + .then(async () => { // if attribute is set, validate MFA after it is setup, otherwise proceed as usual (when mfa is enforced to login) if (checkAfter) { const params = new URLSearchParams({}); @@ -67,35 +71,34 @@ export function TotpRegister({ return router.push(`/otp/time-based?` + params); } else { - if (authRequestId && sessionId) { - const params = new URLSearchParams({ - sessionId: sessionId, - authRequest: authRequestId, - }); + const url = + authRequestId && sessionId + ? await getNextUrl( + { + sessionId: sessionId, + authRequestId: authRequestId, + organization: organization, + }, + loginSettings?.defaultRedirectUri, + ) + : loginName + ? await getNextUrl( + { + loginName: loginName, + organization: organization, + }, + loginSettings?.defaultRedirectUri, + ) + : null; - if (organization) { - params.append("organization", organization); - } - - return router.push(`/login?` + params); - } else if (loginName) { - const params = new URLSearchParams({ - loginName, - }); - - if (authRequestId) { - params.append("authRequestId", authRequestId); - } - if (organization) { - params.append("organization", organization); - } - - return router.push(`/signedin?` + params); + if (url) { + return router.push(url); } } }) .catch((e) => { setError(e.message); + return; }) .finally(() => { setLoading(false); diff --git a/apps/login/src/components/username-form.tsx b/apps/login/src/components/username-form.tsx index 3d686a78136..7d18623aba2 100644 --- a/apps/login/src/components/username-form.tsx +++ b/apps/login/src/components/username-form.tsx @@ -55,13 +55,19 @@ export function UsernameForm({ }) .catch(() => { setError("An internal error occurred"); + return; }) .finally(() => { setLoading(false); }); + if (res?.redirect) { + return router.push(res.redirect); + } + if (res?.error) { setError(res.error); + return; } return res; diff --git a/apps/login/src/components/verify-form.tsx b/apps/login/src/components/verify-form.tsx index 54976ac32a7..377d5b9cfc3 100644 --- a/apps/login/src/components/verify-form.tsx +++ b/apps/login/src/components/verify-form.tsx @@ -3,6 +3,7 @@ import { Alert } from "@/components/alert"; import { resendVerification, sendVerification } from "@/lib/server/email"; import { useTranslations } from "next-intl"; +import { useRouter } from "next/navigation"; import { useCallback, useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { Button, ButtonVariants } from "./button"; @@ -23,6 +24,8 @@ type Props = { export function VerifyForm({ userId, code, isInvite, params }: Props) { const t = useTranslations("verify"); + const router = useRouter(); + const { register, handleSubmit, formState } = useForm({ mode: "onBlur", defaultValues: { @@ -59,7 +62,7 @@ export function VerifyForm({ userId, code, isInvite, params }: Props) { ): Promise { setLoading(true); - await sendVerification({ + const response = await sendVerification({ code: value.code, userId, isInvite: isInvite, @@ -71,6 +74,15 @@ export function VerifyForm({ userId, code, isInvite, params }: Props) { .finally(() => { setLoading(false); }); + + if (response?.error) { + setError(response.error); + return; + } + + if (response?.redirect) { + return router.push(response?.redirect); + } }, [isInvite, userId], ); diff --git a/apps/login/src/i18n/request.ts b/apps/login/src/i18n/request.ts index ed4ba250546..2641c0fa262 100644 --- a/apps/login/src/i18n/request.ts +++ b/apps/login/src/i18n/request.ts @@ -5,7 +5,7 @@ import { cookies } from "next/headers"; export default getRequestConfig(async () => { const fallback = "en"; - const cookiesList = cookies(); + const cookiesList = await cookies(); const locale: string = cookiesList.get(LANGUAGE_COOKIE_NAME)?.value ?? "en"; const userMessages = (await import(`../../locales/${locale}.json`)).default; diff --git a/apps/login/src/lib/client.ts b/apps/login/src/lib/client.ts new file mode 100644 index 00000000000..7dc2b83cbb0 --- /dev/null +++ b/apps/login/src/lib/client.ts @@ -0,0 +1,38 @@ +type FinishFlowCommand = + | { + sessionId: string; + authRequestId: string; + } + | { loginName: string }; + +/** + * for client: redirects user back to OIDC application or to a success page when using authRequestId, check if a default redirect and redirect to it, or just redirect to a success page with the loginName + * @param command + * @returns + */ +export async function getNextUrl( + command: FinishFlowCommand & { organization?: string }, + defaultRedirectUri?: string, +): Promise { + if ("sessionId" in command && "authRequestId" in command) { + const url = + `/login?` + + new URLSearchParams({ + sessionId: command.sessionId, + authRequest: command.authRequestId, + }); + return url; + } + + if (defaultRedirectUri) { + return defaultRedirectUri; + } + + const signedInUrl = + `/signedin?` + + new URLSearchParams({ + loginName: command.loginName, + }); + + return signedInUrl; +} diff --git a/apps/login/src/lib/cookies.ts b/apps/login/src/lib/cookies.ts index c6afb507971..00540653505 100644 --- a/apps/login/src/lib/cookies.ts +++ b/apps/login/src/lib/cookies.ts @@ -20,8 +20,8 @@ export type Cookie = { type SessionCookie = Cookie & T; -function setSessionHttpOnlyCookie(sessions: SessionCookie[]) { - const cookiesList = cookies(); +async function setSessionHttpOnlyCookie(sessions: SessionCookie[]) { + const cookiesList = await cookies(); return cookiesList.set({ name: "sessions", @@ -32,7 +32,7 @@ function setSessionHttpOnlyCookie(sessions: SessionCookie[]) { } export async function setLanguageCookie(language: string) { - const cookiesList = cookies(); + const cookiesList = await cookies(); await cookiesList.set({ name: LANGUAGE_COOKIE_NAME, @@ -46,7 +46,7 @@ export async function addSessionToCookie( session: SessionCookie, cleanup: boolean = false, ): Promise { - const cookiesList = cookies(); + const cookiesList = await cookies(); const stringifiedCookie = cookiesList.get("sessions"); let currentSessions: SessionCookie[] = stringifiedCookie?.value @@ -90,7 +90,7 @@ export async function updateSessionCookie( session: SessionCookie, cleanup: boolean = false, ): Promise { - const cookiesList = cookies(); + const cookiesList = await cookies(); const stringifiedCookie = cookiesList.get("sessions"); const sessions: SessionCookie[] = stringifiedCookie?.value @@ -121,7 +121,7 @@ export async function removeSessionFromCookie( session: SessionCookie, cleanup: boolean = false, ): Promise { - const cookiesList = cookies(); + const cookiesList = await cookies(); const stringifiedCookie = cookiesList.get("sessions"); const sessions: SessionCookie[] = stringifiedCookie?.value @@ -143,7 +143,7 @@ export async function removeSessionFromCookie( } export async function getMostRecentSessionCookie(): Promise { - const cookiesList = cookies(); + const cookiesList = await cookies(); const stringifiedCookie = cookiesList.get("sessions"); if (stringifiedCookie?.value) { @@ -166,7 +166,7 @@ export async function getSessionCookieById({ sessionId: string; organization?: string; }): Promise> { - const cookiesList = cookies(); + const cookiesList = await cookies(); const stringifiedCookie = cookiesList.get("sessions"); if (stringifiedCookie?.value) { @@ -194,7 +194,7 @@ export async function getSessionCookieByLoginName({ loginName?: string; organization?: string; }): Promise> { - const cookiesList = cookies(); + const cookiesList = await cookies(); const stringifiedCookie = cookiesList.get("sessions"); if (stringifiedCookie?.value) { @@ -222,7 +222,7 @@ export async function getSessionCookieByLoginName({ export async function getAllSessionCookieIds( cleanup: boolean = false, ): Promise { - const cookiesList = cookies(); + const cookiesList = await cookies(); const stringifiedCookie = cookiesList.get("sessions"); if (stringifiedCookie?.value) { @@ -253,7 +253,7 @@ export async function getAllSessionCookieIds( export async function getAllSessions( cleanup: boolean = false, ): Promise[]> { - const cookiesList = cookies(); + const cookiesList = await cookies(); const stringifiedCookie = cookiesList.get("sessions"); if (stringifiedCookie?.value) { @@ -287,7 +287,7 @@ export async function getMostRecentCookieWithLoginname({ loginName?: string; organization?: string; }): Promise { - const cookiesList = cookies(); + const cookiesList = await cookies(); const stringifiedCookie = cookiesList.get("sessions"); if (stringifiedCookie?.value) { diff --git a/apps/login/src/lib/server/cookie.ts b/apps/login/src/lib/server/cookie.ts index 17be3844aa6..ab1513ac691 100644 --- a/apps/login/src/lib/server/cookie.ts +++ b/apps/login/src/lib/server/cookie.ts @@ -7,7 +7,7 @@ import { getSession, setSession, } from "@/lib/zitadel"; -import { timestampMs } from "@zitadel/client"; +import { Duration, timestampMs } from "@zitadel/client"; import { Challenges, RequestChallenges, @@ -30,6 +30,7 @@ export async function createSessionAndUpdateCookie( checks: Checks, challenges: RequestChallenges | undefined, authRequestId: string | undefined, + lifetime?: Duration, ): Promise { const createdSession = await createSessionFromChecks(checks, challenges); @@ -82,10 +83,12 @@ export async function createSessionForIdpAndUpdateCookie( idpIntentToken?: string | undefined; }, authRequestId: string | undefined, + lifetime?: Duration, ): Promise { const createdSession = await createSessionForUserIdAndIdpIntent( userId, idpIntent, + lifetime, ); if (createdSession) { @@ -140,12 +143,14 @@ export async function setSessionAndUpdateCookie( checks?: Checks, challenges?: RequestChallenges, authRequestId?: string, + lifetime?: Duration, ) { return setSession( recentCookie.id, recentCookie.token, challenges, checks, + lifetime, ).then((updatedSession) => { if (updatedSession) { const sessionCookie: CustomCookieData = { diff --git a/apps/login/src/lib/server/email.ts b/apps/login/src/lib/server/email.ts index d2ab8496c34..e5a1529660f 100644 --- a/apps/login/src/lib/server/email.ts +++ b/apps/login/src/lib/server/email.ts @@ -10,7 +10,6 @@ import { } from "@/lib/zitadel"; import { create } from "@zitadel/client"; import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb"; -import { redirect } from "next/navigation"; import { createSessionAndUpdateCookie } from "./cookie"; type VerifyUserByEmailCommand = { @@ -74,7 +73,7 @@ export async function sendVerification(command: VerifyUserByEmailCommand) { if (session.factors?.user?.loginName) { params.set("loginName", session.factors?.user?.loginName); } - return redirect(`/authenticator/set?${params}`); + return { redirect: `/authenticator/set?${params}` }; } } @@ -134,6 +133,6 @@ export async function sendVerificationRedirectWithoutCheck(command: { if (session.factors?.user?.loginName) { params.set("loginName", session.factors?.user?.loginName); } - return redirect(`/authenticator/set?${params}`); + return { redirect: `/authenticator/set?${params}` }; } } diff --git a/apps/login/src/lib/server/idp.ts b/apps/login/src/lib/server/idp.ts index be00840626b..0c5d26d45c5 100644 --- a/apps/login/src/lib/server/idp.ts +++ b/apps/login/src/lib/server/idp.ts @@ -15,5 +15,13 @@ export async function startIDPFlow(command: StartIDPFlowCommand) { successUrl: command.successUrl, failureUrl: command.failureUrl, }, + }).then((response) => { + if ( + response && + response.nextStep.case === "authUrl" && + response?.nextStep.value + ) { + return { redirect: response.nextStep.value }; + } }); } diff --git a/apps/login/src/lib/server/invite.ts b/apps/login/src/lib/server/invite.ts index 14b9e8ef9ed..3c68587898a 100644 --- a/apps/login/src/lib/server/invite.ts +++ b/apps/login/src/lib/server/invite.ts @@ -20,7 +20,7 @@ export type RegisterUserResponse = { }; export async function inviteUser(command: InviteUserCommand) { - const host = headers().get("host"); + const host = (await headers()).get("host"); const human = await addHumanUser({ email: command.email, diff --git a/apps/login/src/lib/server/loginname.ts b/apps/login/src/lib/server/loginname.ts index 7081be4d886..918202065b4 100644 --- a/apps/login/src/lib/server/loginname.ts +++ b/apps/login/src/lib/server/loginname.ts @@ -5,7 +5,6 @@ import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_ import { UserState } from "@zitadel/proto/zitadel/user/v2/user_pb"; import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb"; import { headers } from "next/headers"; -import { redirect } from "next/navigation"; import { idpTypeToIdentityProviderType, idpTypeToSlug } from "../idp"; import { @@ -44,7 +43,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { }); if (identityProviders.length === 1) { - const host = headers().get("host"); + const host = (await headers()).get("host"); const identityProviderType = identityProviders[0].type; const provider = idpTypeToSlug(identityProviderType); @@ -70,7 +69,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { }); if (resp?.nextStep.case === "authUrl") { - return redirect(resp.nextStep.value); + return { redirect: resp.nextStep.value }; } } }; @@ -81,7 +80,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { }); if (identityProviders.length === 1) { - const host = headers().get("host"); + const host = (await headers()).get("host"); const identityProviderId = identityProviders[0].idpId; const idp = await getIDPByID(identityProviderId); @@ -115,7 +114,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { }); if (resp?.nextStep.case === "authUrl") { - return redirect(resp.nextStep.value); + return { redirect: resp.nextStep.value }; } } }; @@ -154,7 +153,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { params.append("authRequestid", command.authRequestId); } - return redirect("/password/set?" + params); + return { redirect: "/password/set?" + params }; } const methods = await listAuthenticationMethodTypes( @@ -170,6 +169,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { const paramsVerify = new URLSearchParams({ loginName: session.factors?.user?.loginName, userId: session.factors?.user?.id, // verify needs user id + invite: "true", // TODO: check - set this to true as we dont expect old email verification method here }); if (command.organization || session.factors?.user?.organizationId) { @@ -183,7 +183,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { paramsVerify.append("authRequestId", command.authRequestId); } - redirect("/verify?" + paramsVerify); + return { redirect: "/verify?" + paramsVerify }; } const paramsAuthenticatorSetup = new URLSearchParams({ @@ -202,7 +202,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { paramsAuthenticatorSetup.append("authRequestId", command.authRequestId); } - redirect("/authenticator/set?" + paramsAuthenticatorSetup); + return { redirect: "/authenticator/set?" + paramsAuthenticatorSetup }; } if (methods.authMethodTypes.length == 1) { @@ -224,7 +224,10 @@ export async function sendLoginname(command: SendLoginnameCommand) { paramsPassword.authRequestId = command.authRequestId; } - return redirect("/password?" + new URLSearchParams(paramsPassword)); + return { + redirect: "/password?" + new URLSearchParams(paramsPassword), + }; + case AuthenticationMethodType.PASSKEY: // AuthenticationMethodType.AUTHENTICATION_METHOD_TYPE_PASSKEY const paramsPasskey: any = { loginName: command.loginName }; if (command.authRequestId) { @@ -236,7 +239,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { command.organization ?? session.factors?.user?.organizationId; } - return redirect("/passkey?" + new URLSearchParams(paramsPasskey)); + return { redirect: "/passkey?" + new URLSearchParams(paramsPasskey) }; } } else { // prefer passkey in favor of other methods @@ -255,7 +258,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { command.organization ?? session.factors?.user?.organizationId; } - return redirect("/passkey?" + new URLSearchParams(passkeyParams)); + return { redirect: "/passkey?" + new URLSearchParams(passkeyParams) }; } else if ( methods.authMethodTypes.includes(AuthenticationMethodType.IDP) ) { @@ -275,9 +278,9 @@ export async function sendLoginname(command: SendLoginnameCommand) { command.organization ?? session.factors?.user?.organizationId; } - return redirect( - "/password?" + new URLSearchParams(paramsPasswordDefault), - ); + return { + redirect: "/password?" + new URLSearchParams(paramsPasswordDefault), + }; } } } @@ -325,7 +328,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { params.set("loginName", command.loginName); } - return redirect("/register?" + params); + return { redirect: "/register?" + params }; } } @@ -342,7 +345,7 @@ export async function sendLoginname(command: SendLoginnameCommand) { paramsPasswordDefault.append("organization", command.organization); } - return redirect("/password?" + paramsPasswordDefault); + return { redirect: "/password?" + paramsPasswordDefault }; } // fallbackToPassword diff --git a/apps/login/src/lib/server/otp.ts b/apps/login/src/lib/server/otp.ts index 07aea40be28..b91d8eac7c1 100644 --- a/apps/login/src/lib/server/otp.ts +++ b/apps/login/src/lib/server/otp.ts @@ -12,6 +12,7 @@ import { getSessionCookieById, getSessionCookieByLoginName, } from "../cookies"; +import { getLoginSettings } from "../zitadel"; export type SetOTPCommand = { loginName?: string; @@ -23,49 +24,52 @@ export type SetOTPCommand = { }; export async function setOTP(command: SetOTPCommand) { - const recentPromise = command.sessionId - ? getSessionCookieById({ sessionId: command.sessionId }).catch((error) => { - return Promise.reject(error); - }) + const recentSession = command.sessionId + ? await getSessionCookieById({ sessionId: command.sessionId }).catch( + (error) => { + return Promise.reject(error); + }, + ) : command.loginName - ? getSessionCookieByLoginName({ + ? await getSessionCookieByLoginName({ loginName: command.loginName, organization: command.organization, }).catch((error) => { return Promise.reject(error); }) - : getMostRecentSessionCookie().catch((error) => { + : await getMostRecentSessionCookie().catch((error) => { return Promise.reject(error); }); - return recentPromise.then((recent) => { - const checks = create(ChecksSchema, {}); + const checks = create(ChecksSchema, {}); - if (command.method === "time-based") { - checks.totp = create(CheckTOTPSchema, { - code: command.code, - }); - } else if (command.method === "sms") { - checks.otpSms = create(CheckOTPSchema, { - code: command.code, - }); - } else if (command.method === "email") { - checks.otpEmail = create(CheckOTPSchema, { - code: command.code, - }); - } - - return setSessionAndUpdateCookie( - recent, - checks, - undefined, - command.authRequestId, - ).then((session) => { - return { - sessionId: session.id, - factors: session.factors, - challenges: session.challenges, - }; + if (command.method === "time-based") { + checks.totp = create(CheckTOTPSchema, { + code: command.code, }); + } else if (command.method === "sms") { + checks.otpSms = create(CheckOTPSchema, { + code: command.code, + }); + } else if (command.method === "email") { + checks.otpEmail = create(CheckOTPSchema, { + code: command.code, + }); + } + + const loginSettings = await getLoginSettings(command.organization); + + return setSessionAndUpdateCookie( + recentSession, + checks, + undefined, + command.authRequestId, + loginSettings?.secondFactorCheckLifetime, + ).then((session) => { + return { + sessionId: session.id, + factors: session.factors, + challenges: session.challenges, + }; }); } diff --git a/apps/login/src/lib/server/passkeys.ts b/apps/login/src/lib/server/passkeys.ts index 366c54295a8..181962cae11 100644 --- a/apps/login/src/lib/server/passkeys.ts +++ b/apps/login/src/lib/server/passkeys.ts @@ -37,7 +37,7 @@ export async function registerPasskeyLink( sessionToken: sessionCookie.token, }); - const host = headers().get("host"); + const host = (await headers()).get("host"); if (!host) { throw new Error("Could not get domain"); @@ -73,7 +73,7 @@ export async function verifyPasskey(command: VerifyPasskeyCommand) { // if no name is provided, try to generate one from the user agent let passkeyName = command.passkeyName; if (!!!passkeyName) { - const headersList = headers(); + const headersList = await headers(); const userAgentStructure = { headers: headersList }; const { browser, device, os } = userAgent(userAgentStructure); diff --git a/apps/login/src/lib/server/password.ts b/apps/login/src/lib/server/password.ts index 5731229a1c2..59afca50a5e 100644 --- a/apps/login/src/lib/server/password.ts +++ b/apps/login/src/lib/server/password.ts @@ -5,6 +5,7 @@ import { setSessionAndUpdateCookie, } from "@/lib/server/cookie"; import { + getLoginSettings, getUserByID, listAuthenticationMethodTypes, listUsers, @@ -16,10 +17,11 @@ import { Checks, ChecksSchema, } from "@zitadel/proto/zitadel/session/v2/session_service_pb"; +import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb"; import { User, UserState } from "@zitadel/proto/zitadel/user/v2/user_pb"; import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb"; import { headers } from "next/headers"; -import { redirect } from "next/navigation"; +import { getNextUrl } from "../client"; import { getSessionCookieByLoginName } from "../cookies"; type ResetPasswordCommand = { @@ -28,7 +30,7 @@ type ResetPasswordCommand = { }; export async function resetPassword(command: ResetPasswordCommand) { - const host = headers().get("host"); + const host = (await headers()).get("host"); const users = await listUsers({ loginName: command.loginName, @@ -65,6 +67,8 @@ export async function sendPassword(command: UpdateSessionCommand) { let session; let user: User; + let loginSettings: LoginSettings | undefined; + if (!sessionCookie) { const users = await listUsers({ loginName: command.loginName, @@ -79,10 +83,13 @@ export async function sendPassword(command: UpdateSessionCommand) { password: { password: command.checks.password?.password }, }); + loginSettings = await getLoginSettings(command.organization); + session = await createSessionAndUpdateCookie( checks, undefined, command.authRequestId, + loginSettings?.passwordCheckLifetime, ); } @@ -94,6 +101,7 @@ export async function sendPassword(command: UpdateSessionCommand) { command.checks, undefined, command.authRequestId, + loginSettings?.passwordCheckLifetime, ); if (!session?.factors?.user?.id) { @@ -109,6 +117,12 @@ export async function sendPassword(command: UpdateSessionCommand) { user = userResponse.user; } + if (!loginSettings) { + loginSettings = await getLoginSettings( + command.organization ?? session.factors?.user?.organizationId, + ); + } + if (!session?.factors?.user?.id || !sessionCookie) { return { error: "Could not create session for user" }; } @@ -153,13 +167,13 @@ export async function sendPassword(command: UpdateSessionCommand) { const factor = availableSecondFactors[0]; // if passwordless is other method, but user selected password as alternative, perform a login if (factor === AuthenticationMethodType.TOTP) { - return redirect(`/otp/time-based?` + params); + return { redirect: `/otp/time-based?` + params }; } else if (factor === AuthenticationMethodType.OTP_SMS) { - return redirect(`/otp/sms?` + params); + return { redirect: `/otp/sms?` + params }; } else if (factor === AuthenticationMethodType.OTP_EMAIL) { - return redirect(`/otp/email?` + params); + return { redirect: `/otp/email?` + params }; } else if (factor === AuthenticationMethodType.U2F) { - return redirect(`/u2f?` + params); + return { redirect: `/u2f?` + params }; } } else if (availableSecondFactors?.length >= 1) { const params = new URLSearchParams({ @@ -177,7 +191,7 @@ export async function sendPassword(command: UpdateSessionCommand) { ); } - return redirect(`/mfa?` + params); + return { redirect: `/mfa?` + params }; } else if (user.state === UserState.INITIAL) { const params = new URLSearchParams({ loginName: session.factors.user.loginName, @@ -194,7 +208,7 @@ export async function sendPassword(command: UpdateSessionCommand) { ); } - return redirect(`/password/change?` + params); + return { redirect: `/password/change?` + params }; } else if (command.forceMfa && !availableSecondFactors.length) { const params = new URLSearchParams({ loginName: session.factors.user.loginName, @@ -214,7 +228,7 @@ export async function sendPassword(command: UpdateSessionCommand) { } // TODO: provide a way to setup passkeys on mfa page? - return redirect(`/mfa/set?` + params); + return { redirect: `/mfa/set?` + params }; } // TODO: implement passkey setup @@ -240,41 +254,28 @@ export async function sendPassword(command: UpdateSessionCommand) { // return router.push(`/passkey/set?` + params); // } else if (command.authRequestId && session.id) { - const params = new URLSearchParams({ - sessionId: session.id, - authRequest: command.authRequestId, - }); + const nextUrl = await getNextUrl( + { + sessionId: session.id, + authRequestId: command.authRequestId, + organization: + command.organization ?? session.factors?.user?.organizationId, + }, + loginSettings?.defaultRedirectUri, + ); - if (command.organization || session.factors?.user?.organizationId) { - params.append( - "organization", - command.organization ?? session.factors?.user?.organizationId, - ); - } - - return { nextStep: `/login?${params}` }; + return { redirect: nextUrl }; } - // without OIDC flow - const params = new URLSearchParams( - command.authRequestId - ? { - loginName: session.factors.user.loginName, - authRequestId: command.authRequestId, - } - : { - loginName: session.factors.user.loginName, - }, + const url = await getNextUrl( + { + loginName: session.factors.user.loginName, + organization: session.factors?.user?.organizationId, + }, + loginSettings?.defaultRedirectUri, ); - if (command.organization || session.factors?.user?.organizationId) { - params.append( - "organization", - command.organization ?? session.factors?.user?.organizationId, - ); - } - - return redirect(`/signedin?` + params); + return { redirect: url }; } export async function changePassword(command: { diff --git a/apps/login/src/lib/server/register.ts b/apps/login/src/lib/server/register.ts index a6d8e406437..01ddb0d8c8a 100644 --- a/apps/login/src/lib/server/register.ts +++ b/apps/login/src/lib/server/register.ts @@ -1,14 +1,14 @@ "use server"; import { createSessionAndUpdateCookie } from "@/lib/server/cookie"; -import { addHumanUser } from "@/lib/zitadel"; +import { addHumanUser, getLoginSettings } from "@/lib/zitadel"; import { create } from "@zitadel/client"; import { Factors } from "@zitadel/proto/zitadel/session/v2/session_pb"; import { ChecksJson, ChecksSchema, } from "@zitadel/proto/zitadel/session/v2/session_service_pb"; -import { redirect } from "next/navigation"; +import { getNextUrl } from "../client"; type RegisterUserCommand = { email: string; @@ -37,6 +37,8 @@ export async function registerUser(command: RegisterUserCommand) { return { error: "Could not create user" }; } + const loginSettings = await getLoginSettings(command.organization); + let checkPayload: any = { user: { search: { case: "userId", value: human.userId } }, }; @@ -54,6 +56,7 @@ export async function registerUser(command: RegisterUserCommand) { checks, undefined, command.authRequestId, + command.password ? loginSettings?.passwordCheckLifetime : undefined, ); if (!session || !session.factors?.user) { @@ -70,20 +73,22 @@ export async function registerUser(command: RegisterUserCommand) { params.append("authRequestId", command.authRequestId); } - return redirect("/passkey/set?" + params); + return { redirect: "/passkey/set?" + params }; } else { - const params = new URLSearchParams({ - loginName: session.factors.user.loginName, - organization: session.factors.user.organizationId, - }); + const url = await getNextUrl( + command.authRequestId && session.id + ? { + sessionId: session.id, + authRequestId: command.authRequestId, + organization: session.factors.user.organizationId, + } + : { + loginName: session.factors.user.loginName, + organization: session.factors.user.organizationId, + }, + loginSettings?.defaultRedirectUri, + ); - if (command.authRequestId && session.factors.user.id) { - params.append("authRequest", command.authRequestId); - params.append("sessionId", session.id); - - return redirect("/login?" + params); - } else { - return redirect("/signedin?" + params); - } + return { redirect: url }; } } diff --git a/apps/login/src/lib/server/session.ts b/apps/login/src/lib/server/session.ts index 4c0836879d5..9726ce84e42 100644 --- a/apps/login/src/lib/server/session.ts +++ b/apps/login/src/lib/server/session.ts @@ -4,9 +4,19 @@ import { createSessionForIdpAndUpdateCookie, setSessionAndUpdateCookie, } from "@/lib/server/cookie"; -import { deleteSession, listAuthenticationMethodTypes } from "@/lib/zitadel"; +import { + deleteSession, + getLoginSettings, + getUserByID, + listAuthenticationMethodTypes, +} from "@/lib/zitadel"; +import { Duration } from "@zitadel/client"; import { RequestChallenges } from "@zitadel/proto/zitadel/session/v2/challenge_pb"; +import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb"; import { Checks } from "@zitadel/proto/zitadel/session/v2/session_service_pb"; +import { headers } from "next/headers"; +import { redirect } from "next/navigation"; +import { getNextUrl } from "../client"; import { getMostRecentSessionCookie, getSessionCookieById, @@ -31,7 +41,75 @@ export async function createNewSessionForIdp(options: CreateNewSessionCommand) { if (!userId || !idpIntent) { throw new Error("No userId or loginName provided"); } - return createSessionForIdpAndUpdateCookie(userId, idpIntent, authRequestId); + + const user = await getUserByID(userId); + + if (!user) { + return { error: "Could not find user" }; + } + + const loginSettings = await getLoginSettings(user.details?.resourceOwner); + + const session = await createSessionForIdpAndUpdateCookie( + userId, + idpIntent, + authRequestId, + loginSettings?.externalLoginCheckLifetime, + ); + + if (!session || !session.factors?.user) { + return { error: "Could not create session" }; + } + + const url = await getNextUrl( + authRequestId && session.id + ? { + sessionId: session.id, + authRequestId: authRequestId, + organization: session.factors.user.organizationId, + } + : { + loginName: session.factors.user.loginName, + organization: session.factors.user.organizationId, + }, + loginSettings?.defaultRedirectUri, + ); + + if (url) { + return { redirect: url }; + } +} + +export async function continueWithSession({ + authRequestId, + ...session +}: Session & { authRequestId?: string }) { + const loginSettings = await getLoginSettings( + session.factors?.user?.organizationId, + ); + + const url = + authRequestId && session.id && session.factors?.user + ? await getNextUrl( + { + sessionId: session.id, + authRequestId: authRequestId, + organization: session.factors.user.organizationId, + }, + loginSettings?.defaultRedirectUri, + ) + : session.factors?.user + ? await getNextUrl( + { + loginName: session.factors.user.loginName, + organization: session.factors.user.organizationId, + }, + loginSettings?.defaultRedirectUri, + ) + : null; + if (url) { + return redirect(url); + } } export type UpdateSessionCommand = { @@ -41,6 +119,7 @@ export type UpdateSessionCommand = { checks?: Checks; authRequestId?: string; challenges?: RequestChallenges; + lifetime?: Duration; }; export async function updateSession(options: UpdateSessionCommand) { @@ -52,22 +131,21 @@ export async function updateSession(options: UpdateSessionCommand) { authRequestId, challenges, } = options; - const sessionPromise = sessionId - ? getSessionCookieById({ sessionId }).catch((error) => { + const recentSession = sessionId + ? await getSessionCookieById({ sessionId }).catch((error) => { return Promise.reject(error); }) : loginName - ? getSessionCookieByLoginName({ loginName, organization }).catch( + ? await getSessionCookieByLoginName({ loginName, organization }).catch( (error) => { return Promise.reject(error); }, ) - : getMostRecentSessionCookie().catch((error) => { + : await getMostRecentSessionCookie().catch((error) => { return Promise.reject(error); }); - // TODO remove ports from host header for URL with port - const host = "localhost"; + const host = (await headers()).get("host"); if ( host && @@ -76,16 +154,24 @@ export async function updateSession(options: UpdateSessionCommand) { !challenges.webAuthN.domain ) { const [hostname, port] = host.split(":"); + challenges.webAuthN.domain = hostname; } - const recent = await sessionPromise; + const loginSettings = await getLoginSettings(organization); + + const lifetime = checks?.webAuthN + ? loginSettings?.multiFactorCheckLifetime // TODO different lifetime for webauthn u2f/passkey + : checks?.otpEmail || checks?.otpSms + ? loginSettings?.secondFactorCheckLifetime + : undefined; const session = await setSessionAndUpdateCookie( - recent, + recentSession, checks, challenges, authRequestId, + lifetime, ); // if password, check if user has MFA methods diff --git a/apps/login/src/lib/server/u2f.ts b/apps/login/src/lib/server/u2f.ts index eb0bccf5afc..a174d0bc563 100644 --- a/apps/login/src/lib/server/u2f.ts +++ b/apps/login/src/lib/server/u2f.ts @@ -32,7 +32,7 @@ export async function addU2F(command: RegisterU2FCommand) { sessionToken: sessionCookie.token, }); - const domain = headers().get("host"); + const domain = (await headers()).get("host"); if (!domain) { return { error: "Could not get domain" }; @@ -54,7 +54,7 @@ export async function addU2F(command: RegisterU2FCommand) { export async function verifyU2F(command: VerifyU2FCommand) { let passkeyName = command.passkeyName; if (!!!passkeyName) { - const headersList = headers(); + const headersList = await headers(); const userAgentStructure = { headers: headersList }; const { browser, device, os } = userAgent(userAgentStructure); diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts index 161353ccd51..be410551fb7 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -18,17 +18,11 @@ import { VerifyU2FRegistrationRequest, } from "@zitadel/proto/zitadel/user/v2/user_service_pb"; -import { create, fromJson, toJson } from "@zitadel/client"; +import { create, Duration } from "@zitadel/client"; import { TextQueryMethod } from "@zitadel/proto/zitadel/object/v2/object_pb"; import { CreateCallbackRequest } from "@zitadel/proto/zitadel/oidc/v2/oidc_service_pb"; import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb"; -import { BrandingSettingsSchema } from "@zitadel/proto/zitadel/settings/v2/branding_settings_pb"; -import { LegalAndSupportSettingsSchema } from "@zitadel/proto/zitadel/settings/v2/legal_settings_pb"; -import { - IdentityProviderType, - LoginSettingsSchema, -} from "@zitadel/proto/zitadel/settings/v2/login_settings_pb"; -import { PasswordComplexitySettingsSchema } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb"; +import { IdentityProviderType } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb"; import type { RedirectURLsJson } from "@zitadel/proto/zitadel/user/v2/idp_pb"; import { NotificationType, @@ -43,15 +37,9 @@ import { User, UserState, } from "@zitadel/proto/zitadel/user/v2/user_pb"; -import { unstable_cache } from "next/cache"; +import { unstable_cacheLife as cacheLife } from "next/cache"; import { PROVIDER_MAPPING } from "./idp"; -const SESSION_LIFETIME_S = 3600; // TODO load from oidc settings -const CACHE_REVALIDATION_INTERVAL_IN_SECONDS = process.env - .CACHE_REVALIDATION_INTERVAL_IN_SECONDS - ? Number(process.env.CACHE_REVALIDATION_INTERVAL_IN_SECONDS) - : 3600; - const transport = createServerTransport( process.env.ZITADEL_SERVICE_USER_TOKEN!, { baseUrl: process.env.ZITADEL_API_URL! }, @@ -62,47 +50,31 @@ export const userService = createUserServiceClient(transport); export const oidcService = createOIDCServiceClient(transport); export const idpService = createIdpServiceClient(transport); export const orgService = createOrganizationServiceClient(transport); - export const settingsService = createSettingsServiceClient(transport); +const useCache = process.env.DEBUG !== "true"; + +async function cacheWrapper(callback: Promise) { + "use cache"; + cacheLife("hours"); + + return callback; +} + export async function getBrandingSettings(organization?: string) { - return unstable_cache( - async () => { - return await settingsService - .getBrandingSettings({ ctx: makeReqCtx(organization) }, {}) - .then((resp) => - resp.settings - ? toJson(BrandingSettingsSchema, resp.settings) - : undefined, - ); - }, - ["brandingSettings", organization ?? "default"], - { - revalidate: CACHE_REVALIDATION_INTERVAL_IN_SECONDS, - tags: ["brandingSettings"], - }, - )().then((resp) => - resp ? fromJson(BrandingSettingsSchema, resp) : undefined, - ); + const callback = settingsService + .getBrandingSettings({ ctx: makeReqCtx(organization) }, {}) + .then((resp) => (resp.settings ? resp.settings : undefined)); + + return useCache ? cacheWrapper(callback) : callback; } export async function getLoginSettings(orgId?: string) { - return unstable_cache( - async () => { - return await settingsService - .getLoginSettings({ ctx: makeReqCtx(orgId) }, {}) - .then((resp) => - resp.settings - ? toJson(LoginSettingsSchema, resp.settings) - : undefined, - ); - }, - ["loginSettings", orgId ?? "default"], - { - revalidate: CACHE_REVALIDATION_INTERVAL_IN_SECONDS, - tags: ["loginSettings"], - }, - )().then((resp) => (resp ? fromJson(LoginSettingsSchema, resp) : undefined)); + const callback = settingsService + .getLoginSettings({ ctx: makeReqCtx(orgId) }, {}) + .then((resp) => (resp.settings ? resp.settings : undefined)); + + return useCache ? cacheWrapper(callback) : callback; } export async function listIDPLinks(userId: string) { @@ -132,65 +104,39 @@ export async function registerTOTP(userId: string) { } export async function getGeneralSettings() { - return settingsService + const callback = settingsService .getGeneralSettings({}, {}) .then((resp) => resp.supportedLanguages); + + return useCache ? cacheWrapper(callback) : callback; } export async function getLegalAndSupportSettings(organization?: string) { - return unstable_cache( - async () => { - return await settingsService - .getLegalAndSupportSettings({ ctx: makeReqCtx(organization) }, {}) - .then((resp) => - resp.settings - ? toJson(LegalAndSupportSettingsSchema, resp.settings) - : undefined, - ); - }, - ["legalAndSupportSettings", organization ?? "default"], - { - revalidate: CACHE_REVALIDATION_INTERVAL_IN_SECONDS, - tags: ["legalAndSupportSettings"], - }, - )().then((resp) => - resp ? fromJson(LegalAndSupportSettingsSchema, resp) : undefined, - ); + const callback = settingsService + .getLegalAndSupportSettings({ ctx: makeReqCtx(organization) }, {}) + .then((resp) => (resp.settings ? resp.settings : undefined)); + + return useCache ? cacheWrapper(callback) : callback; } export async function getPasswordComplexitySettings(organization?: string) { - return unstable_cache( - async () => { - return await settingsService - .getPasswordComplexitySettings({ ctx: makeReqCtx(organization) }) - .then((resp) => - resp.settings - ? toJson(PasswordComplexitySettingsSchema, resp.settings) - : undefined, - ); - }, - ["complexitySettings", organization ?? "default"], - { - revalidate: CACHE_REVALIDATION_INTERVAL_IN_SECONDS, - tags: ["complexitySettings"], - }, - )().then((resp) => - resp ? fromJson(PasswordComplexitySettingsSchema, resp) : undefined, - ); + const callback = settingsService + .getPasswordComplexitySettings({ ctx: makeReqCtx(organization) }) + .then((resp) => (resp.settings ? resp.settings : undefined)); + + return useCache ? cacheWrapper(callback) : callback; } export async function createSessionFromChecks( checks: Checks, challenges: RequestChallenges | undefined, + lifetime?: Duration, ) { return sessionService.createSession( { checks: checks, challenges, - lifetime: { - seconds: BigInt(SESSION_LIFETIME_S), - nanos: 0, - }, + lifetime, }, {}, ); @@ -202,6 +148,7 @@ export async function createSessionForUserIdAndIdpIntent( idpIntentId?: string | undefined; idpIntentToken?: string | undefined; }, + lifetime?: Duration, ) { return sessionService.createSession({ checks: { @@ -213,10 +160,7 @@ export async function createSessionForUserIdAndIdpIntent( }, idpIntent, }, - // lifetime: { - // seconds: 300, - // nanos: 0, - // }, + lifetime, }); } @@ -225,6 +169,7 @@ export async function setSession( sessionToken: string, challenges: RequestChallenges | undefined, checks?: Checks, + lifetime?: Duration, ) { return sessionService.setSession( { @@ -233,6 +178,7 @@ export async function setSession( challenges, checks: checks ? checks : {}, metadata: {}, + lifetime, }, {}, ); diff --git a/apps/login/src/styles/globals.scss b/apps/login/src/styles/globals.scss index 89bb258c703..cfce853bc7a 100755 --- a/apps/login/src/styles/globals.scss +++ b/apps/login/src/styles/globals.scss @@ -1,5 +1,5 @@ // include styles from the ui package -@import "./vars.scss"; +@use "./vars.scss"; @tailwind base; @tailwind components; @@ -24,3 +24,42 @@ html { .form-checkbox:checked { background-image: url("/checkbox.svg"); } + +.skeleton { + --accents-2: var(--theme-light-background-400); + --accents-1: var(--theme-light-background-500); + + background-image: linear-gradient( + 270deg, + var(--accents-1), + var(--accents-2), + var(--accents-2), + var(--accents-1) + ); + background-size: 400% 100%; + animation: skeleton_loading 8s ease-in-out infinite; +} + +.dark .skeleton { + --accents-2: var(--theme-dark-background-400); + --accents-1: var(--theme-dark-background-500); + + background-image: linear-gradient( + 270deg, + var(--accents-1), + var(--accents-2), + var(--accents-2), + var(--accents-1) + ); + background-size: 400% 100%; + animation: skeleton_loading 8s ease-in-out infinite; +} + +@keyframes skeleton_loading { + 0% { + background-position: 200% 0; + } + 100% { + background-position: -200% 0; + } +} diff --git a/apps/login/tailwind.config.mjs b/apps/login/tailwind.config.mjs index 705398ceb64..8acc7da4580 100644 --- a/apps/login/tailwind.config.mjs +++ b/apps/login/tailwind.config.mjs @@ -1,4 +1,4 @@ -const sharedConfig = require("zitadel-tailwind-config/tailwind.config.mjs"); +import sharedConfig from "zitadel-tailwind-config/tailwind.config.mjs"; let colors = { background: { light: { contrast: {} }, dark: { contrast: {} } }, @@ -35,7 +35,7 @@ types.forEach((type) => { }); /** @type {import('tailwindcss').Config} */ -module.exports = { +export default { presets: [sharedConfig], darkMode: "class", content: ["./src/**/*.{js,ts,jsx,tsx}"], diff --git a/package.json b/package.json index 670c3501416..2b2b8399580 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,9 @@ }, "pnpm": { "overrides": { - "@typescript-eslint/parser": "^7.9.0" + "@typescript-eslint/parser": "^7.9.0", + "@types/react": "npm:types-react@19.0.0-rc.1", + "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1" } }, "devDependencies": { diff --git a/packages/eslint-config-zitadel/index.js b/packages/eslint-config-zitadel/index.js index 6024e8d6351..6a53b2a5e62 100644 --- a/packages/eslint-config-zitadel/index.js +++ b/packages/eslint-config-zitadel/index.js @@ -1,6 +1,13 @@ module.exports = { + parser: "@babel/eslint-parser", extends: ["next", "turbo", "prettier"], rules: { "@next/next/no-html-link-for-pages": "off", }, + parserOptions: { + requireConfigFile: false, + babelOptions: { + presets: ["next/babel"], + }, + }, }; diff --git a/packages/eslint-config-zitadel/package.json b/packages/eslint-config-zitadel/package.json index 261744ce007..b733284b2b6 100644 --- a/packages/eslint-config-zitadel/package.json +++ b/packages/eslint-config-zitadel/package.json @@ -7,10 +7,11 @@ "access": "public" }, "dependencies": { - "eslint-config-next": "^14.2.3", "@typescript-eslint/parser": "^7.9.0", + "eslint-config-next": "^14.2.18", "eslint-config-prettier": "^9.1.0", + "eslint-config-turbo": "^2.0.9", "eslint-plugin-react": "^7.34.1", - "eslint-config-turbo": "^2.0.9" + "@babel/eslint-parser": "^7.25.9" } } diff --git a/packages/zitadel-client/src/index.ts b/packages/zitadel-client/src/index.ts index dd677643fca..7cf14163bf1 100644 --- a/packages/zitadel-client/src/index.ts +++ b/packages/zitadel-client/src/index.ts @@ -4,4 +4,4 @@ export { NewAuthorizationBearerInterceptor } from "./interceptors"; // TODO: Move this to `./protobuf.ts` and export it from there export { create, fromJson, toJson } from "@bufbuild/protobuf"; export { TimestampSchema, timestampDate, timestampFromDate, timestampFromMs, timestampMs } from "@bufbuild/protobuf/wkt"; -export type { Timestamp } from "@bufbuild/protobuf/wkt"; +export type { Duration, Timestamp } from "@bufbuild/protobuf/wkt"; diff --git a/packages/zitadel-tailwind-config/tailwind.config.mjs b/packages/zitadel-tailwind-config/tailwind.config.mjs index f1a2eccf994..4a9a437cb7d 100644 --- a/packages/zitadel-tailwind-config/tailwind.config.mjs +++ b/packages/zitadel-tailwind-config/tailwind.config.mjs @@ -1,12 +1,8 @@ -const colors = require("tailwindcss/colors"); +import colors from "tailwindcss/colors"; /** @type {import('tailwindcss').Config} */ -module.exports = { - content: [ - "./app/**/*.{js,ts,jsx,tsx}", - "./page/**/*.{js,ts,jsx,tsx}", - "./ui/**/*.{js,ts,jsx,tsx}", - ], +export default { + content: ["./app/**/*.{js,ts,jsx,tsx}", "./page/**/*.{js,ts,jsx,tsx}", "./ui/**/*.{js,ts,jsx,tsx}"], future: { hoverOnlyWhenSupported: true, }, @@ -48,10 +44,10 @@ module.exports = { }, backgroundImage: ({ theme }) => ({ "dark-vc-border-gradient": `radial-gradient(at left top, ${theme( - "colors.gray.800" + "colors.gray.800", )}, 50px, ${theme("colors.gray.800")} 50%)`, "vc-border-gradient": `radial-gradient(at left top, ${theme( - "colors.gray.200" + "colors.gray.200", )}, 50px, ${theme("colors.gray.300")} 50%)`, }), keyframes: ({ theme }) => ({ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f326d64a999..e35075ac472 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,6 +6,8 @@ settings: overrides: '@typescript-eslint/parser': ^7.9.0 + '@types/react': npm:types-react@19.0.0-rc.1 + '@types/react-dom': npm:types-react-dom@19.0.0-rc.1 importers: @@ -64,16 +66,16 @@ importers: dependencies: '@headlessui/react': specifier: ^2.1.9 - version: 2.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 2.1.9(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106) '@heroicons/react': specifier: 2.1.3 - version: 2.1.3(react@18.3.1) + version: 2.1.3(react@19.0.0-rc-66855b96-20241106) '@tailwindcss/forms': specifier: 0.5.7 version: 0.5.7(tailwindcss@3.4.14) '@vercel/analytics': specifier: ^1.2.2 - version: 1.3.1(next@14.2.14(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.7))(react@18.3.1) + version: 1.3.1(next@15.0.4-canary.23(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)(sass@1.80.7))(react@19.0.0-rc-66855b96-20241106) '@zitadel/client': specifier: workspace:* version: link:../../packages/zitadel-client @@ -96,32 +98,32 @@ importers: specifier: ^2.29.4 version: 2.30.1 next: - specifier: 14.2.14 - version: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.7) + specifier: 15.0.4-canary.23 + version: 15.0.4-canary.23(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)(sass@1.80.7) next-intl: - specifier: ^3.20.0 - version: 3.20.0(next@14.2.14(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.7))(react@18.3.1) + specifier: ^3.25.1 + version: 3.25.1(next@15.0.4-canary.23(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)(sass@1.80.7))(react@19.0.0-rc-66855b96-20241106) next-themes: specifier: ^0.2.1 - version: 0.2.1(next@14.2.14(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.7))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 0.2.1(next@15.0.4-canary.23(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)(sass@1.80.7))(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106) nice-grpc: specifier: 2.0.1 version: 2.0.1 qrcode.react: specifier: ^3.1.0 - version: 3.1.0(react@18.3.1) + version: 3.1.0(react@19.0.0-rc-66855b96-20241106) react: - specifier: ^18.3.1 - version: 18.3.1 + specifier: 19.0.0-rc-66855b96-20241106 + version: 19.0.0-rc-66855b96-20241106 react-dom: - specifier: 18.3.1 - version: 18.3.1(react@18.3.1) + specifier: 19.0.0-rc-66855b96-20241106 + version: 19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106) react-hook-form: specifier: 7.39.5 - version: 7.39.5(react@18.3.1) + version: 7.39.5(react@19.0.0-rc-66855b96-20241106) swr: specifier: ^2.2.0 - version: 2.2.5(react@18.3.1) + version: 2.2.5(react@19.0.0-rc-66855b96-20241106) tinycolor2: specifier: 1.4.2 version: 1.4.2 @@ -134,7 +136,7 @@ importers: version: 6.6.3 '@testing-library/react': specifier: ^16.0.1 - version: 16.0.1(@testing-library/dom@10.4.0)(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 16.0.1(@testing-library/dom@10.4.0)(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)(types-react-dom@19.0.0-rc.1)(types-react@19.0.0-rc.1) '@types/ms': specifier: 0.7.34 version: 0.7.34 @@ -142,11 +144,11 @@ importers: specifier: 22.9.0 version: 22.9.0 '@types/react': - specifier: 18.3.12 - version: 18.3.12 + specifier: npm:types-react@19.0.0-rc.1 + version: types-react@19.0.0-rc.1 '@types/react-dom': - specifier: 18.3.1 - version: 18.3.1 + specifier: npm:types-react-dom@19.0.0-rc.1 + version: types-react-dom@19.0.0-rc.1 '@types/tinycolor2': specifier: 1.4.3 version: 1.4.3 @@ -222,12 +224,15 @@ importers: packages/eslint-config-zitadel: dependencies: + '@babel/eslint-parser': + specifier: ^7.25.9 + version: 7.25.9(@babel/core@7.26.0)(eslint@8.57.1) '@typescript-eslint/parser': specifier: ^7.9.0 version: 7.18.0(eslint@8.57.1)(typescript@5.6.3) eslint-config-next: - specifier: ^14.2.3 - version: 14.2.7(eslint@8.57.1)(typescript@5.6.3) + specifier: ^14.2.18 + version: 14.2.18(eslint@8.57.1)(typescript@5.6.3) eslint-config-prettier: specifier: ^9.1.0 version: 9.1.0(eslint@8.57.1) @@ -336,6 +341,13 @@ packages: resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} engines: {node: '>=6.9.0'} + '@babel/eslint-parser@7.25.9': + resolution: {integrity: sha512-5UXfgpK0j0Xr/xIdgdLEhOFxaDZ0bRPWJJchRpqOSur/3rZoPbqqki5mm0p4NE2cs28krBEiSM2MB7//afRSQQ==} + engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} + peerDependencies: + '@babel/core': ^7.11.0 + eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 + '@babel/generator@7.26.2': resolution: {integrity: sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==} engines: {node: '>=6.9.0'} @@ -412,79 +424,79 @@ packages: engines: {node: '>=6.9.0'} '@bufbuild/buf-darwin-arm64@1.46.0': - resolution: {integrity: sha512-lSmTKyRhg+71acXp9QeX/wm+vjkf0J3n38wph7KOwMfCEeK4A2AkqsGOkoXSiaIvidA2pRU9RJRQYfryzCA9Pg==, tarball: https://registry.npmjs.org/@bufbuild/buf-darwin-arm64/-/buf-darwin-arm64-1.46.0.tgz} + resolution: {integrity: sha512-lSmTKyRhg+71acXp9QeX/wm+vjkf0J3n38wph7KOwMfCEeK4A2AkqsGOkoXSiaIvidA2pRU9RJRQYfryzCA9Pg==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] '@bufbuild/buf-darwin-arm64@1.47.2': - resolution: {integrity: sha512-74WerFn06y+azgVfsnzhfbI5wla/OLPDnIvaNJBWHaqya/3bfascJkDylW2GVNHmwG1K/cscpmcc/RJPaO7ntQ==, tarball: https://registry.npmjs.org/@bufbuild/buf-darwin-arm64/-/buf-darwin-arm64-1.47.2.tgz} + resolution: {integrity: sha512-74WerFn06y+azgVfsnzhfbI5wla/OLPDnIvaNJBWHaqya/3bfascJkDylW2GVNHmwG1K/cscpmcc/RJPaO7ntQ==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] '@bufbuild/buf-darwin-x64@1.46.0': - resolution: {integrity: sha512-Oa9XTLJshsEjzowyt2mH9XrXW38DRFdz7ml+IYKXVQPotNLr04ix7QES7A1eOBJtxLwuTiri4ScXuBLQGNX8+A==, tarball: https://registry.npmjs.org/@bufbuild/buf-darwin-x64/-/buf-darwin-x64-1.46.0.tgz} + resolution: {integrity: sha512-Oa9XTLJshsEjzowyt2mH9XrXW38DRFdz7ml+IYKXVQPotNLr04ix7QES7A1eOBJtxLwuTiri4ScXuBLQGNX8+A==} engines: {node: '>=12'} cpu: [x64] os: [darwin] '@bufbuild/buf-darwin-x64@1.47.2': - resolution: {integrity: sha512-adAiOacOQe8Ym/YXPCEiq9mrPeKRmDtF2TgqPWTcDy6mF7TqR7hMJINkEEuMd1EeACmXnzMOnXlm9ICtvdYgPg==, tarball: https://registry.npmjs.org/@bufbuild/buf-darwin-x64/-/buf-darwin-x64-1.47.2.tgz} + resolution: {integrity: sha512-adAiOacOQe8Ym/YXPCEiq9mrPeKRmDtF2TgqPWTcDy6mF7TqR7hMJINkEEuMd1EeACmXnzMOnXlm9ICtvdYgPg==} engines: {node: '>=12'} cpu: [x64] os: [darwin] '@bufbuild/buf-linux-aarch64@1.46.0': - resolution: {integrity: sha512-CbxbLH5sQCRjEKVEcWJySvCKyAPAUhX0vCTifT/eQyZ70FUsqCJKJ6+dKl6Ajk0CgUHqf8jkU/wX/+aQFYXyaA==, tarball: https://registry.npmjs.org/@bufbuild/buf-linux-aarch64/-/buf-linux-aarch64-1.46.0.tgz} + resolution: {integrity: sha512-CbxbLH5sQCRjEKVEcWJySvCKyAPAUhX0vCTifT/eQyZ70FUsqCJKJ6+dKl6Ajk0CgUHqf8jkU/wX/+aQFYXyaA==} engines: {node: '>=12'} cpu: [arm64] os: [linux] '@bufbuild/buf-linux-aarch64@1.47.2': - resolution: {integrity: sha512-52vY+Owffr5diw2PyfQJqH+Fld6zW6NhNZak4zojvc2MjZKubWM0TfNyM9jXz2YrwyB+cyxkabE60nBI80m37w==, tarball: https://registry.npmjs.org/@bufbuild/buf-linux-aarch64/-/buf-linux-aarch64-1.47.2.tgz} + resolution: {integrity: sha512-52vY+Owffr5diw2PyfQJqH+Fld6zW6NhNZak4zojvc2MjZKubWM0TfNyM9jXz2YrwyB+cyxkabE60nBI80m37w==} engines: {node: '>=12'} cpu: [arm64] os: [linux] '@bufbuild/buf-linux-armv7@1.47.2': - resolution: {integrity: sha512-g9KtpObDeHZ/VG/0b5ZCieOao7L/WYZ0fPqFSs4N07D3APgEDhJG6vLyUcDgJMDgyLcgkNjNz0+XdYQb/tXyQw==, tarball: https://registry.npmjs.org/@bufbuild/buf-linux-armv7/-/buf-linux-armv7-1.47.2.tgz} + resolution: {integrity: sha512-g9KtpObDeHZ/VG/0b5ZCieOao7L/WYZ0fPqFSs4N07D3APgEDhJG6vLyUcDgJMDgyLcgkNjNz0+XdYQb/tXyQw==} engines: {node: '>=12'} cpu: [arm] os: [linux] '@bufbuild/buf-linux-x64@1.46.0': - resolution: {integrity: sha512-bMqp+Q+16KPbuwX34/OLDeiimnwt5sfvHqyeMeRz4LLwLshbmM3m+8dGCSHZRo3Lr+4gW1PfunrfaEmcGqPHLQ==, tarball: https://registry.npmjs.org/@bufbuild/buf-linux-x64/-/buf-linux-x64-1.46.0.tgz} + resolution: {integrity: sha512-bMqp+Q+16KPbuwX34/OLDeiimnwt5sfvHqyeMeRz4LLwLshbmM3m+8dGCSHZRo3Lr+4gW1PfunrfaEmcGqPHLQ==} engines: {node: '>=12'} cpu: [x64] os: [linux] '@bufbuild/buf-linux-x64@1.47.2': - resolution: {integrity: sha512-MODCK2BzD1Mgoyr+5Sp8xA8qMNdytj8hYheyhA5NnCGTkQf8sfqAjpBSAAmKk6Zar8HOlVXML6tzE/ioDFFGwQ==, tarball: https://registry.npmjs.org/@bufbuild/buf-linux-x64/-/buf-linux-x64-1.47.2.tgz} + resolution: {integrity: sha512-MODCK2BzD1Mgoyr+5Sp8xA8qMNdytj8hYheyhA5NnCGTkQf8sfqAjpBSAAmKk6Zar8HOlVXML6tzE/ioDFFGwQ==} engines: {node: '>=12'} cpu: [x64] os: [linux] '@bufbuild/buf-win32-arm64@1.46.0': - resolution: {integrity: sha512-geVYXp1PWJiAAFpwhgP8Cnct0+Rdr89BF/WZoIh5WwFGYITGiu5Hb1Ui9DTrEYwDzahPCyPxgIVwzzW6kPWSag==, tarball: https://registry.npmjs.org/@bufbuild/buf-win32-arm64/-/buf-win32-arm64-1.46.0.tgz} + resolution: {integrity: sha512-geVYXp1PWJiAAFpwhgP8Cnct0+Rdr89BF/WZoIh5WwFGYITGiu5Hb1Ui9DTrEYwDzahPCyPxgIVwzzW6kPWSag==} engines: {node: '>=12'} cpu: [arm64] os: [win32] '@bufbuild/buf-win32-arm64@1.47.2': - resolution: {integrity: sha512-563YKYWJl3LrCY3G3+zuhb8HwOs6DzWslwGPFkKV2hwHyWyvd1DR1JjiLvw9zX64IKNctQ0HempSqc3kcboaqQ==, tarball: https://registry.npmjs.org/@bufbuild/buf-win32-arm64/-/buf-win32-arm64-1.47.2.tgz} + resolution: {integrity: sha512-563YKYWJl3LrCY3G3+zuhb8HwOs6DzWslwGPFkKV2hwHyWyvd1DR1JjiLvw9zX64IKNctQ0HempSqc3kcboaqQ==} engines: {node: '>=12'} cpu: [arm64] os: [win32] '@bufbuild/buf-win32-x64@1.46.0': - resolution: {integrity: sha512-6nsxkzj5a1L41NOJFKjli8j6GB/NkPHLIr0T/b27Y3GfprVYQawOComYD5HfojvBLuAiE2cD/kEQIWKK1YRcng==, tarball: https://registry.npmjs.org/@bufbuild/buf-win32-x64/-/buf-win32-x64-1.46.0.tgz} + resolution: {integrity: sha512-6nsxkzj5a1L41NOJFKjli8j6GB/NkPHLIr0T/b27Y3GfprVYQawOComYD5HfojvBLuAiE2cD/kEQIWKK1YRcng==} engines: {node: '>=12'} cpu: [x64] os: [win32] '@bufbuild/buf-win32-x64@1.47.2': - resolution: {integrity: sha512-Sqcdv7La2xBDh3bTdEYb2f4UTMMqCcYe/D0RELhvQ5wDn6I35V3/2YT1OF5fRuf0BZLCo0OdO37S9L47uHSz2g==, tarball: https://registry.npmjs.org/@bufbuild/buf-win32-x64/-/buf-win32-x64-1.47.2.tgz} + resolution: {integrity: sha512-Sqcdv7La2xBDh3bTdEYb2f4UTMMqCcYe/D0RELhvQ5wDn6I35V3/2YT1OF5fRuf0BZLCo0OdO37S9L47uHSz2g==} engines: {node: '>=12'} cpu: [x64] os: [win32] @@ -495,7 +507,7 @@ packages: hasBin: true '@bufbuild/buf@1.47.2': - resolution: {integrity: sha512-glY5kCAoO4+a7HvDb+BLOdoHSdCk4mdXdkp53H8JFz7maOnkxCiHHXgRX+taFyEu25N8ybn7NjZFrZSdRwq2sA==, tarball: https://registry.npmjs.org/@bufbuild/buf/-/buf-1.47.2.tgz} + resolution: {integrity: sha512-glY5kCAoO4+a7HvDb+BLOdoHSdCk4mdXdkp53H8JFz7maOnkxCiHHXgRX+taFyEu25N8ybn7NjZFrZSdRwq2sA==} engines: {node: '>=12'} hasBin: true @@ -503,7 +515,7 @@ packages: resolution: {integrity: sha512-+imAQkHf7U/Rwvu0wk1XWgsP3WnpCWmK7B48f0XqSNzgk64+grljTKC7pnO/xBiEMUziF7vKRfbBnOQhg126qQ==} '@bufbuild/protobuf@2.2.2': - resolution: {integrity: sha512-UNtPCbrwrenpmrXuRwn9jYpPoweNXj8X5sMvYgsqYyaH8jQ6LfUJSk3dJLnBK+6sfYPrF4iAIo5sd5HQ+tg75A==, tarball: https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.2.2.tgz} + resolution: {integrity: sha512-UNtPCbrwrenpmrXuRwn9jYpPoweNXj8X5sMvYgsqYyaH8jQ6LfUJSk3dJLnBK+6sfYPrF4iAIo5sd5HQ+tg75A==} '@bufbuild/protocompile@0.0.1': resolution: {integrity: sha512-cOTMtjcWLcbjF17dPYgeMtVC5jZyS0bSjz3jy8kDPjOgjgSYMD2u2It7w8aCc2z23hTPIKl/2SNdMnz0Jzu3Xg==} @@ -566,24 +578,24 @@ packages: resolution: {integrity: sha512-kDxDrPNpUgsjDbWBvUo27PzKX4gqeKOlhibaOXDJA6kuBisGqNHv/HwGJrAu8U/dSf8ZEFIeHIPtvSlZI1kULw==} '@colors/colors@1.5.0': - resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==, tarball: https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz} + resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} '@connectrpc/connect-node@2.0.0': - resolution: {integrity: sha512-DoI5T+SUvlS/8QBsxt2iDoUg15dSxqhckegrgZpWOtADtmGohBIVbx1UjtWmjLBrP4RdD0FeBw+XyRUSbpKnJQ==, tarball: https://registry.npmjs.org/@connectrpc/connect-node/-/connect-node-2.0.0.tgz} + resolution: {integrity: sha512-DoI5T+SUvlS/8QBsxt2iDoUg15dSxqhckegrgZpWOtADtmGohBIVbx1UjtWmjLBrP4RdD0FeBw+XyRUSbpKnJQ==} engines: {node: '>=18.14.1'} peerDependencies: '@bufbuild/protobuf': ^2.2.0 '@connectrpc/connect': 2.0.0 '@connectrpc/connect-web@2.0.0': - resolution: {integrity: sha512-oeCxqHXLXlWJdmcvp9L3scgAuK+FjNSn+twyhUxc8yvDbTumnt5Io+LnBzSYxAdUdYqTw5yHfTSCJ4hj0QID0g==, tarball: https://registry.npmjs.org/@connectrpc/connect-web/-/connect-web-2.0.0.tgz} + resolution: {integrity: sha512-oeCxqHXLXlWJdmcvp9L3scgAuK+FjNSn+twyhUxc8yvDbTumnt5Io+LnBzSYxAdUdYqTw5yHfTSCJ4hj0QID0g==} peerDependencies: '@bufbuild/protobuf': ^2.2.0 '@connectrpc/connect': 2.0.0 '@connectrpc/connect@2.0.0': - resolution: {integrity: sha512-Usm8jgaaULANJU8vVnhWssSA6nrZ4DJEAbkNtXSoZay2YD5fDyMukCxu8NEhCvFzfHvrhxhcjttvgpyhOM7xAQ==, tarball: https://registry.npmjs.org/@connectrpc/connect/-/connect-2.0.0.tgz} + resolution: {integrity: sha512-Usm8jgaaULANJU8vVnhWssSA6nrZ4DJEAbkNtXSoZay2YD5fDyMukCxu8NEhCvFzfHvrhxhcjttvgpyhOM7xAQ==} peerDependencies: '@bufbuild/protobuf': ^2.2.0 @@ -594,284 +606,287 @@ packages: '@cypress/xvfb@1.2.4': resolution: {integrity: sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==} + '@emnapi/runtime@1.3.1': + resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} + '@esbuild/aix-ppc64@0.21.5': - resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==, tarball: https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz} + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} engines: {node: '>=12'} cpu: [ppc64] os: [aix] '@esbuild/aix-ppc64@0.24.0': - resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==, tarball: https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz} + resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] '@esbuild/android-arm64@0.21.5': - resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==, tarball: https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz} + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} engines: {node: '>=12'} cpu: [arm64] os: [android] '@esbuild/android-arm64@0.24.0': - resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==, tarball: https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz} + resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==} engines: {node: '>=18'} cpu: [arm64] os: [android] '@esbuild/android-arm@0.21.5': - resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==, tarball: https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz} + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} engines: {node: '>=12'} cpu: [arm] os: [android] '@esbuild/android-arm@0.24.0': - resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==, tarball: https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz} + resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==} engines: {node: '>=18'} cpu: [arm] os: [android] '@esbuild/android-x64@0.21.5': - resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==, tarball: https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz} + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} engines: {node: '>=12'} cpu: [x64] os: [android] '@esbuild/android-x64@0.24.0': - resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==, tarball: https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz} + resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==} engines: {node: '>=18'} cpu: [x64] os: [android] '@esbuild/darwin-arm64@0.21.5': - resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==, tarball: https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz} + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] '@esbuild/darwin-arm64@0.24.0': - resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==, tarball: https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz} + resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] '@esbuild/darwin-x64@0.21.5': - resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==, tarball: https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz} + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} engines: {node: '>=12'} cpu: [x64] os: [darwin] '@esbuild/darwin-x64@0.24.0': - resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==, tarball: https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz} + resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] '@esbuild/freebsd-arm64@0.21.5': - resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==, tarball: https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz} + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] '@esbuild/freebsd-arm64@0.24.0': - resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==, tarball: https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz} + resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] '@esbuild/freebsd-x64@0.21.5': - resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==, tarball: https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz} + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] '@esbuild/freebsd-x64@0.24.0': - resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==, tarball: https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz} + resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] '@esbuild/linux-arm64@0.21.5': - resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==, tarball: https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz} + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} engines: {node: '>=12'} cpu: [arm64] os: [linux] '@esbuild/linux-arm64@0.24.0': - resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==, tarball: https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz} + resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==} engines: {node: '>=18'} cpu: [arm64] os: [linux] '@esbuild/linux-arm@0.21.5': - resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==, tarball: https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz} + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} engines: {node: '>=12'} cpu: [arm] os: [linux] '@esbuild/linux-arm@0.24.0': - resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==, tarball: https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz} + resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==} engines: {node: '>=18'} cpu: [arm] os: [linux] '@esbuild/linux-ia32@0.21.5': - resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==, tarball: https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz} + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} engines: {node: '>=12'} cpu: [ia32] os: [linux] '@esbuild/linux-ia32@0.24.0': - resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==, tarball: https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz} + resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==} engines: {node: '>=18'} cpu: [ia32] os: [linux] '@esbuild/linux-loong64@0.21.5': - resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==, tarball: https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz} + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} engines: {node: '>=12'} cpu: [loong64] os: [linux] '@esbuild/linux-loong64@0.24.0': - resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==, tarball: https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz} + resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==} engines: {node: '>=18'} cpu: [loong64] os: [linux] '@esbuild/linux-mips64el@0.21.5': - resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==, tarball: https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz} + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] '@esbuild/linux-mips64el@0.24.0': - resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==, tarball: https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz} + resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] '@esbuild/linux-ppc64@0.21.5': - resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==, tarball: https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz} + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] '@esbuild/linux-ppc64@0.24.0': - resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==, tarball: https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz} + resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] '@esbuild/linux-riscv64@0.21.5': - resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==, tarball: https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz} + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] '@esbuild/linux-riscv64@0.24.0': - resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==, tarball: https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz} + resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] '@esbuild/linux-s390x@0.21.5': - resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==, tarball: https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz} + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} engines: {node: '>=12'} cpu: [s390x] os: [linux] '@esbuild/linux-s390x@0.24.0': - resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==, tarball: https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz} + resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==} engines: {node: '>=18'} cpu: [s390x] os: [linux] '@esbuild/linux-x64@0.21.5': - resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==, tarball: https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz} + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} engines: {node: '>=12'} cpu: [x64] os: [linux] '@esbuild/linux-x64@0.24.0': - resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==, tarball: https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz} + resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==} engines: {node: '>=18'} cpu: [x64] os: [linux] '@esbuild/netbsd-x64@0.21.5': - resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==, tarball: https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz} + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] '@esbuild/netbsd-x64@0.24.0': - resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==, tarball: https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz} + resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] '@esbuild/openbsd-arm64@0.24.0': - resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==, tarball: https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz} + resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] '@esbuild/openbsd-x64@0.21.5': - resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==, tarball: https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz} + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] '@esbuild/openbsd-x64@0.24.0': - resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==, tarball: https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz} + resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] '@esbuild/sunos-x64@0.21.5': - resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==, tarball: https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz} + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} engines: {node: '>=12'} cpu: [x64] os: [sunos] '@esbuild/sunos-x64@0.24.0': - resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==, tarball: https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz} + resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] '@esbuild/win32-arm64@0.21.5': - resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==, tarball: https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz} + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} engines: {node: '>=12'} cpu: [arm64] os: [win32] '@esbuild/win32-arm64@0.24.0': - resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==, tarball: https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz} + resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==} engines: {node: '>=18'} cpu: [arm64] os: [win32] '@esbuild/win32-ia32@0.21.5': - resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==, tarball: https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz} + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} engines: {node: '>=12'} cpu: [ia32] os: [win32] '@esbuild/win32-ia32@0.24.0': - resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==, tarball: https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz} + resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==} engines: {node: '>=18'} cpu: [ia32] os: [win32] '@esbuild/win32-x64@0.21.5': - resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==, tarball: https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz} + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} engines: {node: '>=12'} cpu: [x64] os: [win32] '@esbuild/win32-x64@0.24.0': - resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==, tarball: https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz} + resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -882,10 +897,20 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/eslint-utils@4.4.1': + resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/regexpp@4.11.1': resolution: {integrity: sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint/eslintrc@2.1.4': resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -915,21 +940,24 @@ packages: '@floating-ui/utils@0.2.8': resolution: {integrity: sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==} - '@formatjs/ecma402-abstract@2.1.0': - resolution: {integrity: sha512-SE2V2PE03K9U/YQZ3nxEOysRkQ/CfSwLHR789Uk9N0PTiWT6I+17UTDI97zYEwC1mbnjefqmtjbL8nunjPwGjw==} + '@formatjs/ecma402-abstract@2.2.4': + resolution: {integrity: sha512-lFyiQDVvSbQOpU+WFd//ILolGj4UgA/qXrKeZxdV14uKiAUiPAtX6XAn7WBCRi7Mx6I7EybM9E5yYn4BIpZWYg==} - '@formatjs/fast-memoize@2.2.0': - resolution: {integrity: sha512-hnk/nY8FyrL5YxwP9e4r9dqeM6cAbo8PeU9UjyXojZMNvVad2Z06FAVHyR3Ecw6fza+0GH7vdJgiKIVXTMbSBA==} + '@formatjs/fast-memoize@2.2.3': + resolution: {integrity: sha512-3jeJ+HyOfu8osl3GNSL4vVHUuWFXR03Iz9jjgI7RwjG6ysu/Ymdr0JRCPHfF5yGbTE6JCrd63EpvX1/WybYRbA==} - '@formatjs/icu-messageformat-parser@2.7.9': - resolution: {integrity: sha512-9Z5buDRMsTbplXknvRlDmnpWhZrayNVcVvkH0+SSz8Ll4XD/7Tcn8m1IjxM3iBJSwQbxwxb7/g0Fkx3d4j2osw==} + '@formatjs/icu-messageformat-parser@2.9.4': + resolution: {integrity: sha512-Tbvp5a9IWuxUcpWNIW6GlMQYEc4rwNHR259uUFoKWNN1jM9obf9Ul0e+7r7MvFOBNcN+13K7NuKCKqQiAn1QEg==} - '@formatjs/icu-skeleton-parser@1.8.3': - resolution: {integrity: sha512-TsKAP013ayZFbWWR2KWy+f9QVZh0yDFTPK3yE4OqU2gnzafvmKTodRtJLVpfZmpXWJ5y7BWD1AsyT14mcbLzig==} + '@formatjs/icu-skeleton-parser@1.8.8': + resolution: {integrity: sha512-vHwK3piXwamFcx5YQdCdJxUQ1WdTl6ANclt5xba5zLGDv5Bsur7qz8AD7BevaKxITwpgDeU0u8My3AIibW9ywA==} '@formatjs/intl-localematcher@0.5.4': resolution: {integrity: sha512-zTwEpWOzZ2CiKcB93BLngUX59hQkuZjT2+SAQEscSm52peDW/getsawMcWF1rGRpMCX6D7nSJA3CzJ8gn13N/g==} + '@formatjs/intl-localematcher@0.5.8': + resolution: {integrity: sha512-I+WDNWWJFZie+jkfkiK5Mp4hEDyRSEvmyfYadflOno/mmKJKcB17fEpEH0oJu/OWhhCJ8kJBDz2YMd/6cDl7Mg==} + '@grpc/grpc-js@1.11.1': resolution: {integrity: sha512-gyt/WayZrVPH2w/UTLansS7F9Nwld472JxxaETamrM8HNlsa+jSLNyKAZmhxI2Me4c3mQHFiS1wWHDY1g1Kthw==} engines: {node: '>=12.10.0'} @@ -970,6 +998,111 @@ packages: resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} deprecated: Use @eslint/object-schema instead + '@img/sharp-darwin-arm64@0.33.5': + resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.33.5': + resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.0.4': + resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.0.4': + resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.0.4': + resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.0.5': + resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.0.4': + resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.0.4': + resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.33.5': + resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.33.5': + resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-s390x@0.33.5': + resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.33.5': + resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.33.5': + resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.33.5': + resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.33.5': + resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-ia32@0.33.5': + resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.33.5': + resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -1005,66 +1138,63 @@ packages: resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} hasBin: true - '@next/env@14.2.14': - resolution: {integrity: sha512-/0hWQfiaD5//LvGNgc8PjvyqV50vGK0cADYzaoOOGN8fxzBn3iAiaq3S0tCRnFBldq0LVveLcxCTi41ZoYgAgg==} + '@next/env@15.0.4-canary.23': + resolution: {integrity: sha512-NfBMRPa10yaEzQ693kGEsgHL58Y27jSbGCDbyXy14dx3z6UeQZQfEVRAwJ4iG1V6gND9+CzzugtiXvJZfSlC9A==} - '@next/eslint-plugin-next@14.2.7': - resolution: {integrity: sha512-+7xh142AdhZGjY9/L0iFo7mqRBMJHe+q+uOL+hto1Lfo9DeWCGcR6no4StlFbVSVcA6fQLKEX6y6qhMsSKbgNQ==} + '@next/eslint-plugin-next@14.2.18': + resolution: {integrity: sha512-KyYTbZ3GQwWOjX3Vi1YcQbekyGP0gdammb7pbmmi25HBUCINzDReyrzCMOJIeZisK1Q3U6DT5Rlc4nm2/pQeXA==} - '@next/swc-darwin-arm64@14.2.14': - resolution: {integrity: sha512-bsxbSAUodM1cjYeA4o6y7sp9wslvwjSkWw57t8DtC8Zig8aG8V6r+Yc05/9mDzLKcybb6EN85k1rJDnMKBd9Gw==, tarball: https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.14.tgz} + '@next/swc-darwin-arm64@15.0.4-canary.23': + resolution: {integrity: sha512-sX3MaDUiFiMT14KSx5mJz6B+IH9k7+buNniNrDP7iz4YG28jssm9e8uHbiWXsbn9jnkQUJu8PHoUOLhgjZgtsQ==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@14.2.14': - resolution: {integrity: sha512-cC9/I+0+SK5L1k9J8CInahduTVWGMXhQoXFeNvF0uNs3Bt1Ub0Azb8JzTU9vNCr0hnaMqiWu/Z0S1hfKc3+dww==, tarball: https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.14.tgz} + '@next/swc-darwin-x64@15.0.4-canary.23': + resolution: {integrity: sha512-KJRSDVvEPuvjRKe9IY3YMAv9KMOmB/U5+7g0c3OTT/50x1KL0XOlgnc+Af2GdZKIrkKiAdTFG54AHaSD584yHg==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@14.2.14': - resolution: {integrity: sha512-RMLOdA2NU4O7w1PQ3Z9ft3PxD6Htl4uB2TJpocm+4jcllHySPkFaUIFacQ3Jekcg6w+LBaFvjSPthZHiPmiAUg==, tarball: https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.14.tgz} + '@next/swc-linux-arm64-gnu@15.0.4-canary.23': + resolution: {integrity: sha512-0EqeqGdlG0MPDYGE/cPtTvBLtBiWDAd7fSRgRhIga6CkuaRVFKuTeRrsjTa0v+51C2OawjQp2N3ww1zBLuBhcg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@14.2.14': - resolution: {integrity: sha512-WgLOA4hT9EIP7jhlkPnvz49iSOMdZgDJVvbpb8WWzJv5wBD07M2wdJXLkDYIpZmCFfo/wPqFsFR4JS4V9KkQ2A==, tarball: https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.14.tgz} + '@next/swc-linux-arm64-musl@15.0.4-canary.23': + resolution: {integrity: sha512-O06Gw8HU0z9f1b4TiGb0u1o87hgLa0yEW1odyLPE1d3+JKwhkh4L1Ug9uLpeqEUnxCoIrwVomEUyQBPGNQtq0Q==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@14.2.14': - resolution: {integrity: sha512-lbn7svjUps1kmCettV/R9oAvEW+eUI0lo0LJNFOXoQM5NGNxloAyFRNByYeZKL3+1bF5YE0h0irIJfzXBq9Y6w==, tarball: https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.14.tgz} + '@next/swc-linux-x64-gnu@15.0.4-canary.23': + resolution: {integrity: sha512-BvERc3hri6eyUHnasZgwcRCdR8WpfCdKKe/M12Q+ZAkTeJeVkLXNakznaZbBWdlCc77F/NeHz/OWoQWUTpKm3g==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@14.2.14': - resolution: {integrity: sha512-7TcQCvLQ/hKfQRgjxMN4TZ2BRB0P7HwrGAYL+p+m3u3XcKTraUFerVbV3jkNZNwDeQDa8zdxkKkw2els/S5onQ==, tarball: https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.14.tgz} + '@next/swc-linux-x64-musl@15.0.4-canary.23': + resolution: {integrity: sha512-FF5LNTdra/tHxdHjRR3lb+UxFgRVT+v3EMruueQg6BpOqpciodyCkkYQFrx2DitpADojQ6bBBFBDs6KIb8jB5w==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@14.2.14': - resolution: {integrity: sha512-8i0Ou5XjTLEje0oj0JiI0Xo9L/93ghFtAUYZ24jARSeTMXLUx8yFIdhS55mTExq5Tj4/dC2fJuaT4e3ySvXU1A==, tarball: https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.14.tgz} + '@next/swc-win32-arm64-msvc@15.0.4-canary.23': + resolution: {integrity: sha512-XnHD7fqQYZR1XCCuAf8+yAdkMpzAFz2pWmny2K6g5C7BalrwNuxWLsM5LycW1PTMzSqkzLJeXCG6AZu099u7/w==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-ia32-msvc@14.2.14': - resolution: {integrity: sha512-2u2XcSaDEOj+96eXpyjHjtVPLhkAFw2nlaz83EPeuK4obF+HmtDJHqgR1dZB7Gb6V/d55FL26/lYVd0TwMgcOQ==, tarball: https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.14.tgz} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - - '@next/swc-win32-x64-msvc@14.2.14': - resolution: {integrity: sha512-MZom+OvZ1NZxuRovKt1ApevjiUJTcU2PmdJKL66xUPaJeRywnbGGRWUlaAOwunD6dX+pm83vj979NTC8QXjGWg==, tarball: https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.14.tgz} + '@next/swc-win32-x64-msvc@15.0.4-canary.23': + resolution: {integrity: sha512-HGoW8LjYxbUhkND+vJ/21dWQ7sdv4SIUQDv2r/FpcdHFMzb5M/jgQVqcMFkqg2ibH65ZAcVBM0ICcUnTLlX7PQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] + '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': + resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1082,89 +1212,89 @@ packages: engines: {node: '>=12.4.0'} '@parcel/watcher-android-arm64@2.5.0': - resolution: {integrity: sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==, tarball: https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.0.tgz} + resolution: {integrity: sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [android] '@parcel/watcher-darwin-arm64@2.5.0': - resolution: {integrity: sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==, tarball: https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz} + resolution: {integrity: sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [darwin] '@parcel/watcher-darwin-x64@2.5.0': - resolution: {integrity: sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==, tarball: https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.0.tgz} + resolution: {integrity: sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [darwin] '@parcel/watcher-freebsd-x64@2.5.0': - resolution: {integrity: sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==, tarball: https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.0.tgz} + resolution: {integrity: sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [freebsd] '@parcel/watcher-linux-arm-glibc@2.5.0': - resolution: {integrity: sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==, tarball: https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.0.tgz} + resolution: {integrity: sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] '@parcel/watcher-linux-arm-musl@2.5.0': - resolution: {integrity: sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==, tarball: https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.0.tgz} + resolution: {integrity: sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] '@parcel/watcher-linux-arm64-glibc@2.5.0': - resolution: {integrity: sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==, tarball: https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.0.tgz} + resolution: {integrity: sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] '@parcel/watcher-linux-arm64-musl@2.5.0': - resolution: {integrity: sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==, tarball: https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.0.tgz} + resolution: {integrity: sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] '@parcel/watcher-linux-x64-glibc@2.5.0': - resolution: {integrity: sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==, tarball: https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz} + resolution: {integrity: sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] '@parcel/watcher-linux-x64-musl@2.5.0': - resolution: {integrity: sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==, tarball: https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz} + resolution: {integrity: sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] '@parcel/watcher-win32-arm64@2.5.0': - resolution: {integrity: sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==, tarball: https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.0.tgz} + resolution: {integrity: sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [win32] '@parcel/watcher-win32-ia32@2.5.0': - resolution: {integrity: sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==, tarball: https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.0.tgz} + resolution: {integrity: sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==} engines: {node: '>= 10.0.0'} cpu: [ia32] os: [win32] '@parcel/watcher-win32-x64@2.5.0': - resolution: {integrity: sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==, tarball: https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.0.tgz} + resolution: {integrity: sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [win32] '@parcel/watcher@2.5.0': - resolution: {integrity: sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==, tarball: https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz} + resolution: {integrity: sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==} engines: {node: '>= 10.0.0'} '@pkgjs/parseargs@0.11.0': - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==, tarball: https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz} + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} '@playwright/test@1.48.2': @@ -1234,92 +1364,92 @@ packages: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0 '@rollup/rollup-android-arm-eabi@4.25.0': - resolution: {integrity: sha512-CC/ZqFZwlAIbU1wUPisHyV/XRc5RydFrNLtgl3dGYskdwPZdt4HERtKm50a/+DtTlKeCq9IXFEWR+P6blwjqBA==, tarball: https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.25.0.tgz} + resolution: {integrity: sha512-CC/ZqFZwlAIbU1wUPisHyV/XRc5RydFrNLtgl3dGYskdwPZdt4HERtKm50a/+DtTlKeCq9IXFEWR+P6blwjqBA==} cpu: [arm] os: [android] '@rollup/rollup-android-arm64@4.25.0': - resolution: {integrity: sha512-/Y76tmLGUJqVBXXCfVS8Q8FJqYGhgH4wl4qTA24E9v/IJM0XvJCGQVSW1QZ4J+VURO9h8YCa28sTFacZXwK7Rg==, tarball: https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.25.0.tgz} + resolution: {integrity: sha512-/Y76tmLGUJqVBXXCfVS8Q8FJqYGhgH4wl4qTA24E9v/IJM0XvJCGQVSW1QZ4J+VURO9h8YCa28sTFacZXwK7Rg==} cpu: [arm64] os: [android] '@rollup/rollup-darwin-arm64@4.25.0': - resolution: {integrity: sha512-YVT6L3UrKTlC0FpCZd0MGA7NVdp7YNaEqkENbWQ7AOVOqd/7VzyHpgIpc1mIaxRAo1ZsJRH45fq8j4N63I/vvg==, tarball: https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.25.0.tgz} + resolution: {integrity: sha512-YVT6L3UrKTlC0FpCZd0MGA7NVdp7YNaEqkENbWQ7AOVOqd/7VzyHpgIpc1mIaxRAo1ZsJRH45fq8j4N63I/vvg==} cpu: [arm64] os: [darwin] '@rollup/rollup-darwin-x64@4.25.0': - resolution: {integrity: sha512-ZRL+gexs3+ZmmWmGKEU43Bdn67kWnMeWXLFhcVv5Un8FQcx38yulHBA7XR2+KQdYIOtD0yZDWBCudmfj6lQJoA==, tarball: https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.25.0.tgz} + resolution: {integrity: sha512-ZRL+gexs3+ZmmWmGKEU43Bdn67kWnMeWXLFhcVv5Un8FQcx38yulHBA7XR2+KQdYIOtD0yZDWBCudmfj6lQJoA==} cpu: [x64] os: [darwin] '@rollup/rollup-freebsd-arm64@4.25.0': - resolution: {integrity: sha512-xpEIXhiP27EAylEpreCozozsxWQ2TJbOLSivGfXhU4G1TBVEYtUPi2pOZBnvGXHyOdLAUUhPnJzH3ah5cqF01g==, tarball: https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.25.0.tgz} + resolution: {integrity: sha512-xpEIXhiP27EAylEpreCozozsxWQ2TJbOLSivGfXhU4G1TBVEYtUPi2pOZBnvGXHyOdLAUUhPnJzH3ah5cqF01g==} cpu: [arm64] os: [freebsd] '@rollup/rollup-freebsd-x64@4.25.0': - resolution: {integrity: sha512-sC5FsmZGlJv5dOcURrsnIK7ngc3Kirnx3as2XU9uER+zjfyqIjdcMVgzy4cOawhsssqzoAX19qmxgJ8a14Qrqw==, tarball: https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.25.0.tgz} + resolution: {integrity: sha512-sC5FsmZGlJv5dOcURrsnIK7ngc3Kirnx3as2XU9uER+zjfyqIjdcMVgzy4cOawhsssqzoAX19qmxgJ8a14Qrqw==} cpu: [x64] os: [freebsd] '@rollup/rollup-linux-arm-gnueabihf@4.25.0': - resolution: {integrity: sha512-uD/dbLSs1BEPzg564TpRAQ/YvTnCds2XxyOndAO8nJhaQcqQGFgv/DAVko/ZHap3boCvxnzYMa3mTkV/B/3SWA==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.25.0.tgz} + resolution: {integrity: sha512-uD/dbLSs1BEPzg564TpRAQ/YvTnCds2XxyOndAO8nJhaQcqQGFgv/DAVko/ZHap3boCvxnzYMa3mTkV/B/3SWA==} cpu: [arm] os: [linux] '@rollup/rollup-linux-arm-musleabihf@4.25.0': - resolution: {integrity: sha512-ZVt/XkrDlQWegDWrwyC3l0OfAF7yeJUF4fq5RMS07YM72BlSfn2fQQ6lPyBNjt+YbczMguPiJoCfaQC2dnflpQ==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.25.0.tgz} + resolution: {integrity: sha512-ZVt/XkrDlQWegDWrwyC3l0OfAF7yeJUF4fq5RMS07YM72BlSfn2fQQ6lPyBNjt+YbczMguPiJoCfaQC2dnflpQ==} cpu: [arm] os: [linux] '@rollup/rollup-linux-arm64-gnu@4.25.0': - resolution: {integrity: sha512-qboZ+T0gHAW2kkSDPHxu7quaFaaBlynODXpBVnPxUgvWYaE84xgCKAPEYE+fSMd3Zv5PyFZR+L0tCdYCMAtG0A==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.25.0.tgz} + resolution: {integrity: sha512-qboZ+T0gHAW2kkSDPHxu7quaFaaBlynODXpBVnPxUgvWYaE84xgCKAPEYE+fSMd3Zv5PyFZR+L0tCdYCMAtG0A==} cpu: [arm64] os: [linux] '@rollup/rollup-linux-arm64-musl@4.25.0': - resolution: {integrity: sha512-ndWTSEmAaKr88dBuogGH2NZaxe7u2rDoArsejNslugHZ+r44NfWiwjzizVS1nUOHo+n1Z6qV3X60rqE/HlISgw==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.25.0.tgz} + resolution: {integrity: sha512-ndWTSEmAaKr88dBuogGH2NZaxe7u2rDoArsejNslugHZ+r44NfWiwjzizVS1nUOHo+n1Z6qV3X60rqE/HlISgw==} cpu: [arm64] os: [linux] '@rollup/rollup-linux-powerpc64le-gnu@4.25.0': - resolution: {integrity: sha512-BVSQvVa2v5hKwJSy6X7W1fjDex6yZnNKy3Kx1JGimccHft6HV0THTwNtC2zawtNXKUu+S5CjXslilYdKBAadzA==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.25.0.tgz} + resolution: {integrity: sha512-BVSQvVa2v5hKwJSy6X7W1fjDex6yZnNKy3Kx1JGimccHft6HV0THTwNtC2zawtNXKUu+S5CjXslilYdKBAadzA==} cpu: [ppc64] os: [linux] '@rollup/rollup-linux-riscv64-gnu@4.25.0': - resolution: {integrity: sha512-G4hTREQrIdeV0PE2JruzI+vXdRnaK1pg64hemHq2v5fhv8C7WjVaeXc9P5i4Q5UC06d/L+zA0mszYIKl+wY8oA==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.25.0.tgz} + resolution: {integrity: sha512-G4hTREQrIdeV0PE2JruzI+vXdRnaK1pg64hemHq2v5fhv8C7WjVaeXc9P5i4Q5UC06d/L+zA0mszYIKl+wY8oA==} cpu: [riscv64] os: [linux] '@rollup/rollup-linux-s390x-gnu@4.25.0': - resolution: {integrity: sha512-9T/w0kQ+upxdkFL9zPVB6zy9vWW1deA3g8IauJxojN4bnz5FwSsUAD034KpXIVX5j5p/rn6XqumBMxfRkcHapQ==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.25.0.tgz} + resolution: {integrity: sha512-9T/w0kQ+upxdkFL9zPVB6zy9vWW1deA3g8IauJxojN4bnz5FwSsUAD034KpXIVX5j5p/rn6XqumBMxfRkcHapQ==} cpu: [s390x] os: [linux] '@rollup/rollup-linux-x64-gnu@4.25.0': - resolution: {integrity: sha512-ThcnU0EcMDn+J4B9LD++OgBYxZusuA7iemIIiz5yzEcFg04VZFzdFjuwPdlURmYPZw+fgVrFzj4CA64jSTG4Ig==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.25.0.tgz} + resolution: {integrity: sha512-ThcnU0EcMDn+J4B9LD++OgBYxZusuA7iemIIiz5yzEcFg04VZFzdFjuwPdlURmYPZw+fgVrFzj4CA64jSTG4Ig==} cpu: [x64] os: [linux] '@rollup/rollup-linux-x64-musl@4.25.0': - resolution: {integrity: sha512-zx71aY2oQxGxAT1JShfhNG79PnjYhMC6voAjzpu/xmMjDnKNf6Nl/xv7YaB/9SIa9jDYf8RBPWEnjcdlhlv1rQ==, tarball: https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.25.0.tgz} + resolution: {integrity: sha512-zx71aY2oQxGxAT1JShfhNG79PnjYhMC6voAjzpu/xmMjDnKNf6Nl/xv7YaB/9SIa9jDYf8RBPWEnjcdlhlv1rQ==} cpu: [x64] os: [linux] '@rollup/rollup-win32-arm64-msvc@4.25.0': - resolution: {integrity: sha512-JT8tcjNocMs4CylWY/CxVLnv8e1lE7ff1fi6kbGocWwxDq9pj30IJ28Peb+Y8yiPNSF28oad42ApJB8oUkwGww==, tarball: https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.25.0.tgz} + resolution: {integrity: sha512-JT8tcjNocMs4CylWY/CxVLnv8e1lE7ff1fi6kbGocWwxDq9pj30IJ28Peb+Y8yiPNSF28oad42ApJB8oUkwGww==} cpu: [arm64] os: [win32] '@rollup/rollup-win32-ia32-msvc@4.25.0': - resolution: {integrity: sha512-dRLjLsO3dNOfSN6tjyVlG+Msm4IiZnGkuZ7G5NmpzwF9oOc582FZG05+UdfTbz5Jd4buK/wMb6UeHFhG18+OEg==, tarball: https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.25.0.tgz} + resolution: {integrity: sha512-dRLjLsO3dNOfSN6tjyVlG+Msm4IiZnGkuZ7G5NmpzwF9oOc582FZG05+UdfTbz5Jd4buK/wMb6UeHFhG18+OEg==} cpu: [ia32] os: [win32] '@rollup/rollup-win32-x64-msvc@4.25.0': - resolution: {integrity: sha512-/RqrIFtLB926frMhZD0a5oDa4eFIbyNEwLLloMTEjmqfwZWXywwVVOVmwTsuyhC9HKkVEZcOOi+KV4U9wmOdlg==, tarball: https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.25.0.tgz} + resolution: {integrity: sha512-/RqrIFtLB926frMhZD0a5oDa4eFIbyNEwLLloMTEjmqfwZWXywwVVOVmwTsuyhC9HKkVEZcOOi+KV4U9wmOdlg==} cpu: [x64] os: [win32] @@ -1342,6 +1472,9 @@ packages: '@swc/counter@0.1.3': resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + '@swc/helpers@0.5.13': + resolution: {integrity: sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==} + '@swc/helpers@0.5.5': resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==} @@ -1365,7 +1498,7 @@ packages: resolution: {integrity: sha512-1giLc4dzgEKLMx5pgKjL6HlG5fjZMgCjzlKAlpr7yoUtetVPELgER1NtephAI910nMwfPTHNyWKSFmJdHkz2Cw==} '@testing-library/dom@10.4.0': - resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==, tarball: https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz} + resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==} engines: {node: '>=18'} '@testing-library/jest-dom@6.6.3': @@ -1377,8 +1510,8 @@ packages: engines: {node: '>=18'} peerDependencies: '@testing-library/dom': ^10.0.0 - '@types/react': ^18.0.0 - '@types/react-dom': ^18.0.0 + '@types/react': npm:types-react@19.0.0-rc.1 + '@types/react-dom': npm:types-react-dom@19.0.0-rc.1 react: ^18.0.0 react-dom: ^18.0.0 peerDependenciesMeta: @@ -1388,7 +1521,7 @@ packages: optional: true '@types/aria-query@5.0.4': - resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==, tarball: https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz} + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -1420,9 +1553,6 @@ packages: '@types/prop-types@15.7.12': resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} - '@types/react-dom@18.3.1': - resolution: {integrity: sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==} - '@types/react@18.3.12': resolution: {integrity: sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==} @@ -1439,7 +1569,18 @@ packages: resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} '@types/yauzl@2.10.3': - resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==, tarball: https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz} + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + + '@typescript-eslint/eslint-plugin@8.15.0': + resolution: {integrity: sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^7.9.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true '@typescript-eslint/parser@7.18.0': resolution: {integrity: sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==} @@ -1455,10 +1596,28 @@ packages: resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==} engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/scope-manager@8.15.0': + resolution: {integrity: sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/type-utils@8.15.0': + resolution: {integrity: sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/types@7.18.0': resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/types@8.15.0': + resolution: {integrity: sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@7.18.0': resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==} engines: {node: ^18.18.0 || >=20.0.0} @@ -1468,10 +1627,33 @@ packages: typescript: optional: true + '@typescript-eslint/typescript-estree@8.15.0': + resolution: {integrity: sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/utils@8.15.0': + resolution: {integrity: sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/visitor-keys@7.18.0': resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/visitor-keys@8.15.0': + resolution: {integrity: sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} @@ -1580,7 +1762,7 @@ packages: engines: {node: '>=8'} ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==, tarball: https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz} + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} ansi-styles@6.2.1: @@ -1793,9 +1975,6 @@ packages: caniuse-lite@1.0.30001654: resolution: {integrity: sha512-wLJc602fW0OdrUR+PqsBUH3dgrjDcT+mWs/Kw86zPvgjiqOiI2TXMkBFK4KihYzZclmJxrFwgYhZDSEogFai/g==} - caniuse-lite@1.0.30001666: - resolution: {integrity: sha512-gD14ICmoV5ZZM1OdzPWmpx+q4GyefaK06zi8hmfHV5xe4/2nOQX3+Dw5o+fSqOws2xVwL9j+anOPFwHzdEdV4g==} - caniuse-lite@1.0.30001680: resolution: {integrity: sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==} @@ -1899,10 +2078,17 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + color-support@1.1.3: resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} hasBin: true + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} @@ -2111,7 +2297,7 @@ packages: engines: {node: '>=6.0.0'} dom-accessibility-api@0.5.16: - resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==, tarball: https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz} + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} dom-accessibility-api@0.6.3: resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} @@ -2231,8 +2417,8 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - eslint-config-next@14.2.7: - resolution: {integrity: sha512-ppmy+QdQ7qkuCHGDlPjWaoSbJvjGpWSBD4zEW8f1eWlxYXYpZK7QzBOer1EcHKT3uKhlY1JjUus9g7Kvv712rw==} + eslint-config-next@14.2.18: + resolution: {integrity: sha512-SuDRcpJY5VHBkhz5DijJ4iA4bVnBA0n48Rb+YSJSCDr+h7kKAcb1mZHusLbW+WA8LDB6edSolomXA55eG3eOVA==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 typescript: '>=3.3.1' @@ -2321,14 +2507,26 @@ packages: peerDependencies: eslint: '>6.6.0' + eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + eslint-scope@7.2.2: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-visitor-keys@2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint@8.57.1: resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2352,6 +2550,10 @@ packages: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} + estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} @@ -2517,12 +2719,12 @@ packages: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==, tarball: https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz} + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, tarball: https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz} + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] @@ -2759,8 +2961,8 @@ packages: resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} engines: {node: '>= 0.4'} - intl-messageformat@10.6.0: - resolution: {integrity: sha512-AYKl/DY1nl75pJU8EK681JOVL40uQTNJe3yEMXKfydDFoz+5hNrM/PqjchueSMKGKCZKBVgeexqZwy3uC2B36Q==} + intl-messageformat@10.7.7: + resolution: {integrity: sha512-F134jIoeYMro/3I0h08D0Yt4N9o9pjddU/4IIxMMURqbAtI2wu70X8hvG1V48W49zXHXv3RKSF/po+0fDfsGjA==} is-arguments@1.1.1: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} @@ -2770,6 +2972,9 @@ packages: resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} engines: {node: '>= 0.4'} + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + is-async-function@2.0.0: resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} engines: {node: '>= 0.4'} @@ -3132,7 +3337,7 @@ packages: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} lz-string@1.5.0: - resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==, tarball: https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz} + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true magic-string@0.30.12: @@ -3252,15 +3457,15 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + negotiator@1.0.0: + resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==} engines: {node: '>= 0.6'} - next-intl@3.20.0: - resolution: {integrity: sha512-0bCZcc38HfAZk/T+PNNcnJZknC+caS5rBK+WYRd1HsOL5O6puEu2H3kya8oT9s8piHjrTf7P0UHeahOFleOnrw==} + next-intl@3.25.1: + resolution: {integrity: sha512-Z2dJWn5f/b1sb8EmuJcuDhbQTIp4RG1KBFAILgRt/y27W0ifU7Ll/os3liphUY4InyRH89uShTAk7ItAlpr0uA==} peerDependencies: - next: ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 + next: ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 next-themes@0.2.1: resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==} @@ -3269,21 +3474,24 @@ packages: react: '*' react-dom: '*' - next@14.2.14: - resolution: {integrity: sha512-Q1coZG17MW0Ly5x76shJ4dkC23woLAhhnDnw+DfTc7EpZSGuWrlsZ3bZaO8t6u1Yu8FVfhkqJE+U8GC7E0GLPQ==} - engines: {node: '>=18.17.0'} + next@15.0.4-canary.23: + resolution: {integrity: sha512-xCjjBx4csWdG4MP9tKV/C25OIDbN0o+zovMC5zd4yvE4lrd43Y5tt+w171IGUueb6VbPLTSlDaXvqOtrxKJXzQ==} + engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} hasBin: true peerDependencies: '@opentelemetry/api': ^1.1.0 '@playwright/test': ^1.41.2 - react: ^18.2.0 - react-dom: ^18.2.0 + babel-plugin-react-compiler: '*' + react: ^18.2.0 || 19.0.0-rc-380f5d67-20241113 + react-dom: ^18.2.0 || 19.0.0-rc-380f5d67-20241113 sass: ^1.3.0 peerDependenciesMeta: '@opentelemetry/api': optional: true '@playwright/test': optional: true + babel-plugin-react-compiler: + optional: true sass: optional: true @@ -3698,7 +3906,7 @@ packages: engines: {node: '>=6'} pretty-format@27.5.1: - resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==, tarball: https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz} + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} process@0.11.10: @@ -3748,10 +3956,10 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - react-dom@18.3.1: - resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} + react-dom@19.0.0-rc-66855b96-20241106: + resolution: {integrity: sha512-D25vdaytZ1wFIRiwNU98NPQ/upS2P8Co4/oNoa02PzHbh8deWdepjm5qwZM/46OdSiGv4WSWwxP55RO9obqJEQ==} peerDependencies: - react: ^18.3.1 + react: 19.0.0-rc-66855b96-20241106 react-hook-form@7.39.5: resolution: {integrity: sha512-OE0HKyz5IPc6svN2wd+e+evidZrw4O4WZWAWYzQVZuHi+hYnHFSLnxOq0ddjbdmaLIsLHut/ab7j72y2QT3+KA==} @@ -3763,14 +3971,14 @@ packages: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} react-is@17.0.2: - resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==, tarball: https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz} + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} react-refresh@0.14.2: resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} engines: {node: '>=0.10.0'} - react@18.3.1: - resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + react@19.0.0-rc-66855b96-20241106: + resolution: {integrity: sha512-klH7xkT71SxRCx4hb1hly5FJB21Hz0ACyxbXYAECEqssUjtJeFUAaI2U1DgJAzkGEnvEm3DkxuBchMC/9K4ipg==} engines: {node: '>=0.10.0'} read-cache@1.0.0: @@ -3890,8 +4098,8 @@ packages: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} - scheduler@0.23.2: - resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + scheduler@0.25.0-rc-66855b96-20241106: + resolution: {integrity: sha512-HQXp/Mnp/MMRSXMQF7urNFla+gmtXW/Gr1KliuR0iboTit4KvZRY8KYaq5ccCTAOJiUqQh2rE2F3wgUekmgdlA==} semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} @@ -3916,6 +4124,10 @@ packages: resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} engines: {node: '>= 0.4'} + sharp@0.33.5: + resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + shebang-command@1.2.0: resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} engines: {node: '>=0.10.0'} @@ -3949,6 +4161,9 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + simple-update-notifier@2.0.0: resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} engines: {node: '>=10'} @@ -4089,13 +4304,13 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - styled-jsx@5.1.1: - resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} + styled-jsx@5.1.6: + resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} engines: {node: '>= 12.0.0'} peerDependencies: '@babel/core': '*' babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' + react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0' peerDependenciesMeta: '@babel/core': optional: true @@ -4242,6 +4457,12 @@ packages: peerDependencies: typescript: '>=4.2.0' + ts-api-utils@1.4.1: + resolution: {integrity: sha512-5RU2/lxTA3YUZxju61HO2U6EoZLvBLtmV2mbTvqyu4a/7s7RmJPT+1YekhMVsQhznRWk/czIwDUg+V8Q9ZuG4w==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + ts-error@1.0.6: resolution: {integrity: sha512-tLJxacIQUM82IR7JO1UUkKlYuUTmoY9HBJAmNWFzheSlDS5SPMcNIepejHJa4BpPQLAcbRhRf3GDJzyj6rbKvA==} @@ -4274,6 +4495,9 @@ packages: tslib@2.7.0: resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tsup@8.3.5: resolution: {integrity: sha512-Tunf6r6m6tnZsG9GYWndg0z8dEV7fD733VBFzFJ5Vcm1FtlXB8xBD/rtrBi2a3YKEV7hHtxiZtW5EAVADoe1pA==} engines: {node: '>=18'} @@ -4297,32 +4521,32 @@ packages: resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} turbo-darwin-64@2.2.3: - resolution: {integrity: sha512-Rcm10CuMKQGcdIBS3R/9PMeuYnv6beYIHqfZFeKWVYEWH69sauj4INs83zKMTUiZJ3/hWGZ4jet9AOwhsssLyg==, tarball: https://registry.npmjs.org/turbo-darwin-64/-/turbo-darwin-64-2.2.3.tgz} + resolution: {integrity: sha512-Rcm10CuMKQGcdIBS3R/9PMeuYnv6beYIHqfZFeKWVYEWH69sauj4INs83zKMTUiZJ3/hWGZ4jet9AOwhsssLyg==} cpu: [x64] os: [darwin] turbo-darwin-arm64@2.2.3: - resolution: {integrity: sha512-+EIMHkuLFqUdJYsA3roj66t9+9IciCajgj+DVek+QezEdOJKcRxlvDOS2BUaeN8kEzVSsNiAGnoysFWYw4K0HA==, tarball: https://registry.npmjs.org/turbo-darwin-arm64/-/turbo-darwin-arm64-2.2.3.tgz} + resolution: {integrity: sha512-+EIMHkuLFqUdJYsA3roj66t9+9IciCajgj+DVek+QezEdOJKcRxlvDOS2BUaeN8kEzVSsNiAGnoysFWYw4K0HA==} cpu: [arm64] os: [darwin] turbo-linux-64@2.2.3: - resolution: {integrity: sha512-UBhJCYnqtaeOBQLmLo8BAisWbc9v9daL9G8upLR+XGj6vuN/Nz6qUAhverN4Pyej1g4Nt1BhROnj6GLOPYyqxQ==, tarball: https://registry.npmjs.org/turbo-linux-64/-/turbo-linux-64-2.2.3.tgz} + resolution: {integrity: sha512-UBhJCYnqtaeOBQLmLo8BAisWbc9v9daL9G8upLR+XGj6vuN/Nz6qUAhverN4Pyej1g4Nt1BhROnj6GLOPYyqxQ==} cpu: [x64] os: [linux] turbo-linux-arm64@2.2.3: - resolution: {integrity: sha512-hJYT9dN06XCQ3jBka/EWvvAETnHRs3xuO/rb5bESmDfG+d9yQjeTMlhRXKrr4eyIMt6cLDt1LBfyi+6CQ+VAwQ==, tarball: https://registry.npmjs.org/turbo-linux-arm64/-/turbo-linux-arm64-2.2.3.tgz} + resolution: {integrity: sha512-hJYT9dN06XCQ3jBka/EWvvAETnHRs3xuO/rb5bESmDfG+d9yQjeTMlhRXKrr4eyIMt6cLDt1LBfyi+6CQ+VAwQ==} cpu: [arm64] os: [linux] turbo-windows-64@2.2.3: - resolution: {integrity: sha512-NPrjacrZypMBF31b4HE4ROg4P3nhMBPHKS5WTpMwf7wydZ8uvdEHpESVNMOtqhlp857zbnKYgP+yJF30H3N2dQ==, tarball: https://registry.npmjs.org/turbo-windows-64/-/turbo-windows-64-2.2.3.tgz} + resolution: {integrity: sha512-NPrjacrZypMBF31b4HE4ROg4P3nhMBPHKS5WTpMwf7wydZ8uvdEHpESVNMOtqhlp857zbnKYgP+yJF30H3N2dQ==} cpu: [x64] os: [win32] turbo-windows-arm64@2.2.3: - resolution: {integrity: sha512-fnNrYBCqn6zgKPKLHu4sOkihBI/+0oYFr075duRxqUZ+1aLWTAGfHZLgjVeLh3zR37CVzuerGIPWAEkNhkWEIw==, tarball: https://registry.npmjs.org/turbo-windows-arm64/-/turbo-windows-arm64-2.2.3.tgz} + resolution: {integrity: sha512-fnNrYBCqn6zgKPKLHu4sOkihBI/+0oYFr075duRxqUZ+1aLWTAGfHZLgjVeLh3zR37CVzuerGIPWAEkNhkWEIw==} cpu: [arm64] os: [win32] @@ -4361,6 +4585,12 @@ packages: resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} engines: {node: '>= 0.4'} + types-react-dom@19.0.0-rc.1: + resolution: {integrity: sha512-VSLZJl8VXCD0fAWp7DUTFUDCcZ8DVXOQmjhJMD03odgeFmu14ZQJHCXeETm3BEAhJqfgJaFkLnGkQv88sRx0fQ==} + + types-react@19.0.0-rc.1: + resolution: {integrity: sha512-RshndUfqTW6K3STLPis8BtAYCGOkMbtvYsi90gmVNDZBXUyUc5juf2PE9LfS/JmOlUIRO8cWTS/1MTnmhjDqyQ==} + typescript@5.6.3: resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} engines: {node: '>=14.17'} @@ -4406,10 +4636,10 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - use-intl@3.20.0: - resolution: {integrity: sha512-5WQs6yZVWI9K7vw3134P0bhKNp4mi8NbmqKOCuhD9nQUMTKdmpBXwjk62+axwvEbj4XrZxj4X93mQMLXU5ZsCg==} + use-intl@3.25.1: + resolution: {integrity: sha512-Xeyl0+BjlBf6fJr2h5W/CESZ2IQAH7jzXYK4c/ao+qR26jNPW3FXBLjg7eLRxdeI6QaLcYGLtH3WYhC9I0+6Yg==} peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 use-sync-external-store@1.2.2: resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==} @@ -4679,6 +4909,14 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/eslint-parser@7.25.9(@babel/core@7.26.0)(eslint@8.57.1)': + dependencies: + '@babel/core': 7.26.0 + '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 + eslint: 8.57.1 + eslint-visitor-keys: 2.1.0 + semver: 6.3.1 + '@babel/generator@7.26.2': dependencies: '@babel/parser': 7.26.2 @@ -5024,6 +5262,11 @@ snapshots: transitivePeerDependencies: - supports-color + '@emnapi/runtime@1.3.1': + dependencies: + tslib: 2.7.0 + optional: true + '@esbuild/aix-ppc64@0.21.5': optional: true @@ -5170,8 +5413,15 @@ snapshots: eslint: 8.57.1 eslint-visitor-keys: 3.4.3 + '@eslint-community/eslint-utils@4.4.1(eslint@8.57.1)': + dependencies: + eslint: 8.57.1 + eslint-visitor-keys: 3.4.3 + '@eslint-community/regexpp@4.11.1': {} + '@eslint-community/regexpp@4.12.1': {} + '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 @@ -5197,47 +5447,51 @@ snapshots: '@floating-ui/core': 1.6.8 '@floating-ui/utils': 0.2.8 - '@floating-ui/react-dom@2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@floating-ui/react-dom@2.1.2(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)': dependencies: '@floating-ui/dom': 1.6.11 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + react: 19.0.0-rc-66855b96-20241106 + react-dom: 19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106) - '@floating-ui/react@0.26.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@floating-ui/react@0.26.24(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)': dependencies: - '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@floating-ui/react-dom': 2.1.2(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106) '@floating-ui/utils': 0.2.8 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + react: 19.0.0-rc-66855b96-20241106 + react-dom: 19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106) tabbable: 6.2.0 '@floating-ui/utils@0.2.8': {} - '@formatjs/ecma402-abstract@2.1.0': + '@formatjs/ecma402-abstract@2.2.4': dependencies: - '@formatjs/fast-memoize': 2.2.0 - '@formatjs/intl-localematcher': 0.5.4 - tslib: 2.7.0 + '@formatjs/fast-memoize': 2.2.3 + '@formatjs/intl-localematcher': 0.5.8 + tslib: 2.8.1 - '@formatjs/fast-memoize@2.2.0': + '@formatjs/fast-memoize@2.2.3': dependencies: - tslib: 2.7.0 + tslib: 2.8.1 - '@formatjs/icu-messageformat-parser@2.7.9': + '@formatjs/icu-messageformat-parser@2.9.4': dependencies: - '@formatjs/ecma402-abstract': 2.1.0 - '@formatjs/icu-skeleton-parser': 1.8.3 - tslib: 2.7.0 + '@formatjs/ecma402-abstract': 2.2.4 + '@formatjs/icu-skeleton-parser': 1.8.8 + tslib: 2.8.1 - '@formatjs/icu-skeleton-parser@1.8.3': + '@formatjs/icu-skeleton-parser@1.8.8': dependencies: - '@formatjs/ecma402-abstract': 2.1.0 - tslib: 2.7.0 + '@formatjs/ecma402-abstract': 2.2.4 + tslib: 2.8.1 '@formatjs/intl-localematcher@0.5.4': dependencies: tslib: 2.7.0 + '@formatjs/intl-localematcher@0.5.8': + dependencies: + tslib: 2.8.1 + '@grpc/grpc-js@1.11.1': dependencies: '@grpc/proto-loader': 0.7.13 @@ -5256,18 +5510,18 @@ snapshots: dependencies: '@hapi/hoek': 9.3.0 - '@headlessui/react@2.1.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@headlessui/react@2.1.9(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)': dependencies: - '@floating-ui/react': 0.26.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-aria/focus': 3.18.3(react@18.3.1) - '@react-aria/interactions': 3.22.3(react@18.3.1) - '@tanstack/react-virtual': 3.10.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + '@floating-ui/react': 0.26.24(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106) + '@react-aria/focus': 3.18.3(react@19.0.0-rc-66855b96-20241106) + '@react-aria/interactions': 3.22.3(react@19.0.0-rc-66855b96-20241106) + '@tanstack/react-virtual': 3.10.6(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106) + react: 19.0.0-rc-66855b96-20241106 + react-dom: 19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106) - '@heroicons/react@2.1.3(react@18.3.1)': + '@heroicons/react@2.1.3(react@19.0.0-rc-66855b96-20241106)': dependencies: - react: 18.3.1 + react: 19.0.0-rc-66855b96-20241106 '@humanwhocodes/config-array@0.13.0': dependencies: @@ -5281,6 +5535,81 @@ snapshots: '@humanwhocodes/object-schema@2.0.3': {} + '@img/sharp-darwin-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.0.4 + optional: true + + '@img/sharp-darwin-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.0.4 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.0.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.0.5': + optional: true + + '@img/sharp-libvips-linux-s390x@1.0.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.0.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + optional: true + + '@img/sharp-linux-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.0.4 + optional: true + + '@img/sharp-linux-arm@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.0.5 + optional: true + + '@img/sharp-linux-s390x@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.0.4 + optional: true + + '@img/sharp-linux-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.0.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + optional: true + + '@img/sharp-wasm32@0.33.5': + dependencies: + '@emnapi/runtime': 1.3.1 + optional: true + + '@img/sharp-win32-ia32@0.33.5': + optional: true + + '@img/sharp-win32-x64@0.33.5': + optional: true + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -5340,38 +5669,39 @@ snapshots: - encoding - supports-color - '@next/env@14.2.14': {} + '@next/env@15.0.4-canary.23': {} - '@next/eslint-plugin-next@14.2.7': + '@next/eslint-plugin-next@14.2.18': dependencies: glob: 10.3.10 - '@next/swc-darwin-arm64@14.2.14': + '@next/swc-darwin-arm64@15.0.4-canary.23': optional: true - '@next/swc-darwin-x64@14.2.14': + '@next/swc-darwin-x64@15.0.4-canary.23': optional: true - '@next/swc-linux-arm64-gnu@14.2.14': + '@next/swc-linux-arm64-gnu@15.0.4-canary.23': optional: true - '@next/swc-linux-arm64-musl@14.2.14': + '@next/swc-linux-arm64-musl@15.0.4-canary.23': optional: true - '@next/swc-linux-x64-gnu@14.2.14': + '@next/swc-linux-x64-gnu@15.0.4-canary.23': optional: true - '@next/swc-linux-x64-musl@14.2.14': + '@next/swc-linux-x64-musl@15.0.4-canary.23': optional: true - '@next/swc-win32-arm64-msvc@14.2.14': + '@next/swc-win32-arm64-msvc@15.0.4-canary.23': optional: true - '@next/swc-win32-ia32-msvc@14.2.14': + '@next/swc-win32-x64-msvc@15.0.4-canary.23': optional: true - '@next/swc-win32-x64-msvc@14.2.14': - optional: true + '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': + dependencies: + eslint-scope: 5.1.1 '@nodelib/fs.scandir@2.1.5': dependencies: @@ -5478,45 +5808,45 @@ snapshots: '@protobufjs/utf8@1.1.0': {} - '@react-aria/focus@3.18.3(react@18.3.1)': + '@react-aria/focus@3.18.3(react@19.0.0-rc-66855b96-20241106)': dependencies: - '@react-aria/interactions': 3.22.3(react@18.3.1) - '@react-aria/utils': 3.25.3(react@18.3.1) - '@react-types/shared': 3.25.0(react@18.3.1) + '@react-aria/interactions': 3.22.3(react@19.0.0-rc-66855b96-20241106) + '@react-aria/utils': 3.25.3(react@19.0.0-rc-66855b96-20241106) + '@react-types/shared': 3.25.0(react@19.0.0-rc-66855b96-20241106) '@swc/helpers': 0.5.5 clsx: 2.1.1 - react: 18.3.1 + react: 19.0.0-rc-66855b96-20241106 - '@react-aria/interactions@3.22.3(react@18.3.1)': + '@react-aria/interactions@3.22.3(react@19.0.0-rc-66855b96-20241106)': dependencies: - '@react-aria/ssr': 3.9.6(react@18.3.1) - '@react-aria/utils': 3.25.3(react@18.3.1) - '@react-types/shared': 3.25.0(react@18.3.1) + '@react-aria/ssr': 3.9.6(react@19.0.0-rc-66855b96-20241106) + '@react-aria/utils': 3.25.3(react@19.0.0-rc-66855b96-20241106) + '@react-types/shared': 3.25.0(react@19.0.0-rc-66855b96-20241106) '@swc/helpers': 0.5.5 - react: 18.3.1 + react: 19.0.0-rc-66855b96-20241106 - '@react-aria/ssr@3.9.6(react@18.3.1)': + '@react-aria/ssr@3.9.6(react@19.0.0-rc-66855b96-20241106)': dependencies: '@swc/helpers': 0.5.5 - react: 18.3.1 + react: 19.0.0-rc-66855b96-20241106 - '@react-aria/utils@3.25.3(react@18.3.1)': + '@react-aria/utils@3.25.3(react@19.0.0-rc-66855b96-20241106)': dependencies: - '@react-aria/ssr': 3.9.6(react@18.3.1) - '@react-stately/utils': 3.10.4(react@18.3.1) - '@react-types/shared': 3.25.0(react@18.3.1) + '@react-aria/ssr': 3.9.6(react@19.0.0-rc-66855b96-20241106) + '@react-stately/utils': 3.10.4(react@19.0.0-rc-66855b96-20241106) + '@react-types/shared': 3.25.0(react@19.0.0-rc-66855b96-20241106) '@swc/helpers': 0.5.5 clsx: 2.1.1 - react: 18.3.1 + react: 19.0.0-rc-66855b96-20241106 - '@react-stately/utils@3.10.4(react@18.3.1)': + '@react-stately/utils@3.10.4(react@19.0.0-rc-66855b96-20241106)': dependencies: - '@swc/helpers': 0.5.5 - react: 18.3.1 + '@swc/helpers': 0.5.13 + react: 19.0.0-rc-66855b96-20241106 - '@react-types/shared@3.25.0(react@18.3.1)': + '@react-types/shared@3.25.0(react@19.0.0-rc-66855b96-20241106)': dependencies: - react: 18.3.1 + react: 19.0.0-rc-66855b96-20241106 '@rollup/rollup-android-arm-eabi@4.25.0': optional: true @@ -5586,6 +5916,10 @@ snapshots: '@swc/counter@0.1.3': {} + '@swc/helpers@0.5.13': + dependencies: + tslib: 2.7.0 + '@swc/helpers@0.5.5': dependencies: '@swc/counter': 0.1.3 @@ -5601,11 +5935,11 @@ snapshots: mini-svg-data-uri: 1.4.4 tailwindcss: 3.4.14 - '@tanstack/react-virtual@3.10.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@tanstack/react-virtual@3.10.6(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)': dependencies: '@tanstack/virtual-core': 3.10.6 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + react: 19.0.0-rc-66855b96-20241106 + react-dom: 19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106) '@tanstack/virtual-core@3.10.6': {} @@ -5630,15 +5964,15 @@ snapshots: lodash: 4.17.21 redent: 3.0.0 - '@testing-library/react@16.0.1(@testing-library/dom@10.4.0)(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@testing-library/react@16.0.1(@testing-library/dom@10.4.0)(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)(types-react-dom@19.0.0-rc.1)(types-react@19.0.0-rc.1)': dependencies: '@babel/runtime': 7.25.6 '@testing-library/dom': 10.4.0 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + react: 19.0.0-rc-66855b96-20241106 + react-dom: 19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106) optionalDependencies: - '@types/react': 18.3.12 - '@types/react-dom': 18.3.1 + '@types/react': types-react@19.0.0-rc.1 + '@types/react-dom': types-react-dom@19.0.0-rc.1 '@types/aria-query@5.0.4': {} @@ -5677,10 +6011,6 @@ snapshots: '@types/prop-types@15.7.12': {} - '@types/react-dom@18.3.1': - dependencies: - '@types/react': 18.3.12 - '@types/react@18.3.12': dependencies: '@types/prop-types': 15.7.12 @@ -5699,6 +6029,24 @@ snapshots: '@types/node': 22.9.0 optional: true + '@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/type-utils': 8.15.0(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/utils': 8.15.0(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/visitor-keys': 8.15.0 + eslint: 8.57.1 + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + ts-api-utils: 1.4.1(typescript@5.6.3) + optionalDependencies: + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3)': dependencies: '@typescript-eslint/scope-manager': 7.18.0 @@ -5717,8 +6065,27 @@ snapshots: '@typescript-eslint/types': 7.18.0 '@typescript-eslint/visitor-keys': 7.18.0 + '@typescript-eslint/scope-manager@8.15.0': + dependencies: + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/visitor-keys': 8.15.0 + + '@typescript-eslint/type-utils@8.15.0(eslint@8.57.1)(typescript@5.6.3)': + dependencies: + '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.6.3) + '@typescript-eslint/utils': 8.15.0(eslint@8.57.1)(typescript@5.6.3) + debug: 4.3.7(supports-color@5.5.0) + eslint: 8.57.1 + ts-api-utils: 1.4.1(typescript@5.6.3) + optionalDependencies: + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/types@7.18.0': {} + '@typescript-eslint/types@8.15.0': {} + '@typescript-eslint/typescript-estree@7.18.0(typescript@5.6.3)': dependencies: '@typescript-eslint/types': 7.18.0 @@ -5734,19 +6101,51 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.15.0(typescript@5.6.3)': + dependencies: + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/visitor-keys': 8.15.0 + debug: 4.3.7(supports-color@5.5.0) + fast-glob: 3.3.2 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.6.3 + ts-api-utils: 1.4.1(typescript@5.6.3) + optionalDependencies: + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.15.0(eslint@8.57.1)(typescript@5.6.3)': + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.6.3) + eslint: 8.57.1 + optionalDependencies: + typescript: 5.6.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/visitor-keys@7.18.0': dependencies: '@typescript-eslint/types': 7.18.0 eslint-visitor-keys: 3.4.3 + '@typescript-eslint/visitor-keys@8.15.0': + dependencies: + '@typescript-eslint/types': 8.15.0 + eslint-visitor-keys: 4.2.0 + '@ungap/structured-clone@1.2.0': {} - '@vercel/analytics@1.3.1(next@14.2.14(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.7))(react@18.3.1)': + '@vercel/analytics@1.3.1(next@15.0.4-canary.23(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)(sass@1.80.7))(react@19.0.0-rc-66855b96-20241106)': dependencies: server-only: 0.0.1 optionalDependencies: - next: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.7) - react: 18.3.1 + next: 15.0.4-canary.23(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)(sass@1.80.7) + react: 19.0.0-rc-66855b96-20241106 '@vercel/git-hooks@1.0.0': {} @@ -6085,8 +6484,6 @@ snapshots: caniuse-lite@1.0.30001654: {} - caniuse-lite@1.0.30001666: {} - caniuse-lite@1.0.30001680: {} case-anything@2.1.13: {} @@ -6185,8 +6582,20 @@ snapshots: color-name@1.1.4: {} + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + optional: true + color-support@1.1.3: {} + color@4.2.3: + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + optional: true + colorette@2.0.20: {} combined-stream@1.0.8: @@ -6652,10 +7061,11 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-next@14.2.7(eslint@8.57.1)(typescript@5.6.3): + eslint-config-next@14.2.18(eslint@8.57.1)(typescript@5.6.3): dependencies: - '@next/eslint-plugin-next': 14.2.7 + '@next/eslint-plugin-next': 14.2.18 '@rushstack/eslint-patch': 1.10.4 + '@typescript-eslint/eslint-plugin': 8.15.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3) '@typescript-eslint/parser': 7.18.0(eslint@8.57.1)(typescript@5.6.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 @@ -6694,7 +7104,7 @@ snapshots: debug: 4.3.7(supports-color@5.5.0) enhanced-resolve: 5.17.1 eslint: 8.57.1 - eslint-module-utils: 2.8.2(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.8.2(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) fast-glob: 3.3.2 get-tsconfig: 4.8.0 is-bun-module: 1.1.0 @@ -6707,7 +7117,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.2(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.1))(eslint@8.57.1): + eslint-module-utils@2.8.2(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1): dependencies: debug: 3.2.7(supports-color@8.1.1) optionalDependencies: @@ -6728,7 +7138,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.2(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.8.2(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 @@ -6796,13 +7206,22 @@ snapshots: dotenv: 16.0.3 eslint: 8.57.1 + eslint-scope@5.1.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + eslint-scope@7.2.2: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 + eslint-visitor-keys@2.1.0: {} + eslint-visitor-keys@3.4.3: {} + eslint-visitor-keys@4.2.0: {} + eslint@8.57.1: dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) @@ -6862,6 +7281,8 @@ snapshots: dependencies: estraverse: 5.3.0 + estraverse@4.3.0: {} + estraverse@5.3.0: {} estree-walker@3.0.3: @@ -7312,12 +7733,12 @@ snapshots: hasown: 2.0.2 side-channel: 1.0.6 - intl-messageformat@10.6.0: + intl-messageformat@10.7.7: dependencies: - '@formatjs/ecma402-abstract': 2.1.0 - '@formatjs/fast-memoize': 2.2.0 - '@formatjs/icu-messageformat-parser': 2.7.9 - tslib: 2.7.0 + '@formatjs/ecma402-abstract': 2.2.4 + '@formatjs/fast-memoize': 2.2.3 + '@formatjs/icu-messageformat-parser': 2.9.4 + tslib: 2.8.1 is-arguments@1.1.1: dependencies: @@ -7329,6 +7750,9 @@ snapshots: call-bind: 1.0.7 get-intrinsic: 1.2.4 + is-arrayish@0.3.2: + optional: true + is-async-function@2.0.0: dependencies: has-tostringtag: 1.0.2 @@ -7790,45 +8214,45 @@ snapshots: natural-compare@1.4.0: {} - negotiator@0.6.3: {} + negotiator@1.0.0: {} - next-intl@3.20.0(next@14.2.14(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.7))(react@18.3.1): + next-intl@3.25.1(next@15.0.4-canary.23(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)(sass@1.80.7))(react@19.0.0-rc-66855b96-20241106): dependencies: '@formatjs/intl-localematcher': 0.5.4 - negotiator: 0.6.3 - next: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.7) - react: 18.3.1 - use-intl: 3.20.0(react@18.3.1) + negotiator: 1.0.0 + next: 15.0.4-canary.23(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)(sass@1.80.7) + react: 19.0.0-rc-66855b96-20241106 + use-intl: 3.25.1(react@19.0.0-rc-66855b96-20241106) - next-themes@0.2.1(next@14.2.14(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.7))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next-themes@0.2.1(next@15.0.4-canary.23(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)(sass@1.80.7))(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106): dependencies: - next: 14.2.14(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.7) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) + next: 15.0.4-canary.23(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)(sass@1.80.7) + react: 19.0.0-rc-66855b96-20241106 + react-dom: 19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106) - next@14.2.14(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.80.7): + next@15.0.4-canary.23(@babel/core@7.26.0)(@playwright/test@1.48.2)(react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106))(react@19.0.0-rc-66855b96-20241106)(sass@1.80.7): dependencies: - '@next/env': 14.2.14 - '@swc/helpers': 0.5.5 + '@next/env': 15.0.4-canary.23 + '@swc/counter': 0.1.3 + '@swc/helpers': 0.5.13 busboy: 1.6.0 - caniuse-lite: 1.0.30001666 - graceful-fs: 4.2.11 + caniuse-lite: 1.0.30001680 postcss: 8.4.31 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - styled-jsx: 5.1.1(@babel/core@7.26.0)(react@18.3.1) + react: 19.0.0-rc-66855b96-20241106 + react-dom: 19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106) + styled-jsx: 5.1.6(@babel/core@7.26.0)(react@19.0.0-rc-66855b96-20241106) optionalDependencies: - '@next/swc-darwin-arm64': 14.2.14 - '@next/swc-darwin-x64': 14.2.14 - '@next/swc-linux-arm64-gnu': 14.2.14 - '@next/swc-linux-arm64-musl': 14.2.14 - '@next/swc-linux-x64-gnu': 14.2.14 - '@next/swc-linux-x64-musl': 14.2.14 - '@next/swc-win32-arm64-msvc': 14.2.14 - '@next/swc-win32-ia32-msvc': 14.2.14 - '@next/swc-win32-x64-msvc': 14.2.14 + '@next/swc-darwin-arm64': 15.0.4-canary.23 + '@next/swc-darwin-x64': 15.0.4-canary.23 + '@next/swc-linux-arm64-gnu': 15.0.4-canary.23 + '@next/swc-linux-arm64-musl': 15.0.4-canary.23 + '@next/swc-linux-x64-gnu': 15.0.4-canary.23 + '@next/swc-linux-x64-musl': 15.0.4-canary.23 + '@next/swc-win32-arm64-msvc': 15.0.4-canary.23 + '@next/swc-win32-x64-msvc': 15.0.4-canary.23 '@playwright/test': 1.48.2 sass: 1.80.7 + sharp: 0.33.5 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros @@ -8183,9 +8607,9 @@ snapshots: punycode@2.3.1: {} - qrcode.react@3.1.0(react@18.3.1): + qrcode.react@3.1.0(react@19.0.0-rc-66855b96-20241106): dependencies: - react: 18.3.1 + react: 19.0.0-rc-66855b96-20241106 qs@6.13.0: dependencies: @@ -8193,15 +8617,14 @@ snapshots: queue-microtask@1.2.3: {} - react-dom@18.3.1(react@18.3.1): + react-dom@19.0.0-rc-66855b96-20241106(react@19.0.0-rc-66855b96-20241106): dependencies: - loose-envify: 1.4.0 - react: 18.3.1 - scheduler: 0.23.2 + react: 19.0.0-rc-66855b96-20241106 + scheduler: 0.25.0-rc-66855b96-20241106 - react-hook-form@7.39.5(react@18.3.1): + react-hook-form@7.39.5(react@19.0.0-rc-66855b96-20241106): dependencies: - react: 18.3.1 + react: 19.0.0-rc-66855b96-20241106 react-is@16.13.1: {} @@ -8209,9 +8632,7 @@ snapshots: react-refresh@0.14.2: {} - react@18.3.1: - dependencies: - loose-envify: 1.4.0 + react@19.0.0-rc-66855b96-20241106: {} read-cache@1.0.0: dependencies: @@ -8365,9 +8786,7 @@ snapshots: dependencies: xmlchars: 2.2.0 - scheduler@0.23.2: - dependencies: - loose-envify: 1.4.0 + scheduler@0.25.0-rc-66855b96-20241106: {} semver@6.3.1: {} @@ -8393,6 +8812,33 @@ snapshots: functions-have-names: 1.2.3 has-property-descriptors: 1.0.2 + sharp@0.33.5: + dependencies: + color: 4.2.3 + detect-libc: 2.0.3 + semver: 7.6.3 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.33.5 + '@img/sharp-darwin-x64': 0.33.5 + '@img/sharp-libvips-darwin-arm64': 1.0.4 + '@img/sharp-libvips-darwin-x64': 1.0.4 + '@img/sharp-libvips-linux-arm': 1.0.5 + '@img/sharp-libvips-linux-arm64': 1.0.4 + '@img/sharp-libvips-linux-s390x': 1.0.4 + '@img/sharp-libvips-linux-x64': 1.0.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + '@img/sharp-linux-arm': 0.33.5 + '@img/sharp-linux-arm64': 0.33.5 + '@img/sharp-linux-s390x': 0.33.5 + '@img/sharp-linux-x64': 0.33.5 + '@img/sharp-linuxmusl-arm64': 0.33.5 + '@img/sharp-linuxmusl-x64': 0.33.5 + '@img/sharp-wasm32': 0.33.5 + '@img/sharp-win32-ia32': 0.33.5 + '@img/sharp-win32-x64': 0.33.5 + optional: true + shebang-command@1.2.0: dependencies: shebang-regex: 1.0.0 @@ -8420,6 +8866,11 @@ snapshots: signal-exit@4.1.0: {} + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + optional: true + simple-update-notifier@2.0.0: dependencies: semver: 7.6.3 @@ -8594,10 +9045,10 @@ snapshots: strip-json-comments@3.1.1: {} - styled-jsx@5.1.1(@babel/core@7.26.0)(react@18.3.1): + styled-jsx@5.1.6(@babel/core@7.26.0)(react@19.0.0-rc-66855b96-20241106): dependencies: client-only: 0.0.1 - react: 18.3.1 + react: 19.0.0-rc-66855b96-20241106 optionalDependencies: '@babel/core': 7.26.0 @@ -8625,11 +9076,11 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - swr@2.2.5(react@18.3.1): + swr@2.2.5(react@19.0.0-rc-66855b96-20241106): dependencies: client-only: 0.0.1 - react: 18.3.1 - use-sync-external-store: 1.2.2(react@18.3.1) + react: 19.0.0-rc-66855b96-20241106 + use-sync-external-store: 1.2.2(react@19.0.0-rc-66855b96-20241106) symbol-tree@3.2.4: {} @@ -8746,6 +9197,10 @@ snapshots: dependencies: typescript: 5.6.3 + ts-api-utils@1.4.1(typescript@5.6.3): + dependencies: + typescript: 5.6.3 + ts-error@1.0.6: {} ts-interface-checker@0.1.13: {} @@ -8778,6 +9233,8 @@ snapshots: tslib@2.7.0: {} + tslib@2.8.1: {} + tsup@8.3.5(jiti@1.21.6)(postcss@8.4.49)(typescript@5.6.3)(yaml@2.5.0): dependencies: bundle-require: 5.0.0(esbuild@0.24.0) @@ -8878,6 +9335,14 @@ snapshots: is-typed-array: 1.1.13 possible-typed-array-names: 1.0.0 + types-react-dom@19.0.0-rc.1: + dependencies: + '@types/react': 18.3.12 + + types-react@19.0.0-rc.1: + dependencies: + csstype: 3.1.3 + typescript@5.6.3: {} unbox-primitive@1.0.2: @@ -8915,15 +9380,15 @@ snapshots: dependencies: punycode: 2.3.1 - use-intl@3.20.0(react@18.3.1): + use-intl@3.25.1(react@19.0.0-rc-66855b96-20241106): dependencies: - '@formatjs/fast-memoize': 2.2.0 - intl-messageformat: 10.6.0 - react: 18.3.1 + '@formatjs/fast-memoize': 2.2.3 + intl-messageformat: 10.7.7 + react: 19.0.0-rc-66855b96-20241106 - use-sync-external-store@1.2.2(react@18.3.1): + use-sync-external-store@1.2.2(react@19.0.0-rc-66855b96-20241106): dependencies: - react: 18.3.1 + react: 19.0.0-rc-66855b96-20241106 util-deprecate@1.0.2: {}