From 050ef343fe5adb83102da8645af672300ed3c082 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Wed, 30 Oct 2024 13:59:03 +0100 Subject: [PATCH 01/40] session item rehaul, finish session util --- apps/login/src/components/idp-signin.tsx | 31 ++---------- apps/login/src/components/session-item.tsx | 57 +++++++--------------- apps/login/src/lib/login.ts | 32 ++++++++++++ apps/login/src/lib/server/password.ts | 28 +++-------- apps/login/src/lib/server/session.ts | 43 +++++++++++++++- 5 files changed, 102 insertions(+), 89 deletions(-) create mode 100644 apps/login/src/lib/login.ts diff --git a/apps/login/src/components/idp-signin.tsx b/apps/login/src/components/idp-signin.tsx index ebee13ae271..6a010f81dac 100644 --- a/apps/login/src/components/idp-signin.tsx +++ b/apps/login/src/components/idp-signin.tsx @@ -34,33 +34,10 @@ export function IdpSignin({ idpIntentToken, }, 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); - } - - if (authRequestId) { - params.set("authRequestId", authRequestId); - } - - return router.push(`/signedin?` + params); - } - }) - .catch((error) => { - setError(error.message); - return; - }); + }).catch((error) => { + setError(error.message); + return; + }); setLoading(false); }, []); diff --git a/apps/login/src/components/session-item.tsx b/apps/login/src/components/session-item.tsx index a2abfd897a6..7bc2e4cab35 100644 --- a/apps/login/src/components/session-item.tsx +++ b/apps/login/src/components/session-item.tsx @@ -1,11 +1,11 @@ "use client"; -import { cleanupSession } from "@/lib/server/session"; +import { sendLoginname } from "@/lib/server/loginname"; +import { cleanupSession, continueWithSession } from "@/lib/server/session"; import { XCircleIcon } from "@heroicons/react/24/outline"; import { Timestamp, timestampDate } from "@zitadel/client"; import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb"; import moment from "moment"; -import Link from "next/link"; import { useState } from "react"; import { Avatar } from "./avatar"; @@ -53,42 +53,21 @@ export function SessionItem({ const [error, setError] = useState(null); return ( - { + if (valid && session?.factors?.user) { + return continueWithSession({ + ...session, + authRequestId: authRequestId, + }); + } else if (session.factors?.user) { + return sendLoginname({ + loginName: session.factors?.user?.loginName, + organization: session.factors.user.organizationId, + authRequestId: authRequestId, + }); + } + }} className="group flex flex-row items-center bg-background-light-400 dark:bg-background-dark-400 border border-divider-light hover:shadow-lg dark:hover:bg-white/10 py-2 px-4 rounded-md transition-all" >
@@ -129,6 +108,6 @@ export function SessionItem({ }} />
- + ); } diff --git a/apps/login/src/lib/login.ts b/apps/login/src/lib/login.ts new file mode 100644 index 00000000000..39f3396c9f8 --- /dev/null +++ b/apps/login/src/lib/login.ts @@ -0,0 +1,32 @@ +import { redirect } from "next/navigation"; + +type FinishFlowCommand = + | { + sessionId: string; + authRequestId: string; + } + | { loginName: string }; + +/** + * redirects user back to OIDC application or to a success page + * @param command + * @returns + */ +export function finishFlow( + command: FinishFlowCommand & { organization?: string }, +) { + return "sessionId" in command && "authRequestId" in command + ? redirect( + `/login?` + + new URLSearchParams({ + sessionId: command.sessionId, + authRequest: command.authRequestId, + }), + ) + : redirect( + `/signedin?` + + new URLSearchParams({ + loginName: command.loginName, + }), + ); +} diff --git a/apps/login/src/lib/server/password.ts b/apps/login/src/lib/server/password.ts index 2cb512bb971..1b121b96e67 100644 --- a/apps/login/src/lib/server/password.ts +++ b/apps/login/src/lib/server/password.ts @@ -21,6 +21,7 @@ import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_se import { headers } from "next/headers"; import { redirect } from "next/navigation"; import { getSessionCookieByLoginName } from "../cookies"; +import { finishFlow } from "../login"; type ResetPasswordCommand = { loginName: string; @@ -239,36 +240,19 @@ export async function sendPassword(command: UpdateSessionCommand) { // return router.push(`/passkey/set?` + params); // } - else if (command.authRequestId && submitted.sessionId) { - const params = new URLSearchParams({ - sessionId: submitted.sessionId, - authRequest: command.authRequestId, - }); - if (command.organization) { - params.append("organization", command.organization); - } - - return redirect(`/login?` + params); - } - - // without OIDC flow - const params = new URLSearchParams( - command.authRequestId + return finishFlow( + command.authRequestId && submitted.sessionId ? { - loginName: submitted.factors.user.loginName, + sessionId: submitted.sessionId, authRequestId: command.authRequestId, + organization: submitted.factors.user.organizationId, } : { loginName: submitted.factors.user.loginName, + organization: submitted.factors.user.organizationId, }, ); - - if (command.organization) { - params.append("organization", command.organization); - } - - return redirect(`/signedin?` + params); } export async function changePassword(command: { diff --git a/apps/login/src/lib/server/session.ts b/apps/login/src/lib/server/session.ts index 2cd618ffb36..54a13fa1490 100644 --- a/apps/login/src/lib/server/session.ts +++ b/apps/login/src/lib/server/session.ts @@ -6,6 +6,7 @@ import { } from "@/lib/server/cookie"; import { deleteSession, listAuthenticationMethodTypes } from "@/lib/zitadel"; 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 { @@ -14,6 +15,7 @@ import { getSessionCookieByLoginName, removeSessionFromCookie, } from "../cookies"; +import { finishFlow } from "../login"; type CreateNewSessionCommand = { userId: string; @@ -32,7 +34,46 @@ export async function createNewSessionForIdp(options: CreateNewSessionCommand) { if (!userId || !idpIntent) { throw new Error("No userId or loginName provided"); } - return createSessionForIdpAndUpdateCookie(userId, idpIntent, authRequestId); + const session = await createSessionForIdpAndUpdateCookie( + userId, + idpIntent, + authRequestId, + ); + + if (!session || !session.factors?.user) { + return { error: "Could not create session" }; + } + + return finishFlow( + authRequestId && session.id + ? { + sessionId: session.id, + authRequestId: authRequestId, + organization: session.factors.user.organizationId, + } + : { + loginName: session.factors.user.loginName, + organization: session.factors.user.organizationId, + }, + ); +} + +export async function continueWithSession({ + authRequestId, + ...session +}: Session & { authRequestId?: string }) { + return authRequestId && session.id && session.factors?.user + ? finishFlow({ + sessionId: session.id, + authRequestId: authRequestId, + organization: session.factors.user.organizationId, + }) + : session.factors?.user + ? finishFlow({ + loginName: session.factors.user.loginName, + organization: session.factors.user.organizationId, + }) + : null; } export type UpdateSessionCommand = { From c12410034ce8c805bc5007475f3727748cb289be Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Wed, 30 Oct 2024 15:44:30 +0100 Subject: [PATCH 02/40] redirects --- apps/login/src/components/sessions-list.tsx | 10 ++++++++ apps/login/src/lib/server/loginname.ts | 1 + apps/login/src/lib/server/register.ts | 26 ++++++++++----------- 3 files changed, 24 insertions(+), 13 deletions(-) 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 ( Date: Mon, 18 Nov 2024 10:27:39 +0100 Subject: [PATCH 03/40] cleanup --- apps/login/src/components/login-otp.tsx | 47 +++++----------- apps/login/src/components/login-passkey.tsx | 33 +++++------ apps/login/src/components/register-u2f.tsx | 62 ++++++++++----------- apps/login/src/components/totp-register.tsx | 38 +++++-------- apps/login/src/lib/login.ts | 2 +- 5 files changed, 71 insertions(+), 111 deletions(-) diff --git a/apps/login/src/components/login-otp.tsx b/apps/login/src/components/login-otp.tsx index 7dfed9bfd16..13e71ecd5e0 100644 --- a/apps/login/src/components/login-otp.tsx +++ b/apps/login/src/components/login-otp.tsx @@ -1,5 +1,6 @@ "use client"; +import { finishFlow } from "@/lib/login"; import { updateSession } from "@/lib/server/session"; import { create } from "@zitadel/client"; import { RequestChallengesSchema } from "@zitadel/proto/zitadel/session/v2/challenge_pb"; @@ -154,40 +155,18 @@ export function LoginOTP({ function setCodeAndContinue(values: Inputs, organization?: string) { return submitCode(values, organization).then((response) => { if (response) { - if (authRequestId && response && response.sessionId) { - const params = new URLSearchParams({ - sessionId: response.sessionId, - authRequest: authRequestId, - }); - - 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); - } + return authRequestId && response.sessionId + ? finishFlow({ + sessionId: response.sessionId, + authRequestId: authRequestId, + organization: response.factors?.user?.organizationId, + }) + : response.factors?.user + ? finishFlow({ + loginName: response.factors.user.loginName, + organization: response.factors?.user?.organizationId, + }) + : null; } }); } diff --git a/apps/login/src/components/login-passkey.tsx b/apps/login/src/components/login-passkey.tsx index db4246eda02..ab801028fec 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 { finishFlow } from "@/lib/login"; import { updateSession } from "@/lib/server/session"; import { create } from "@zitadel/client"; import { @@ -176,26 +177,18 @@ 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({}); - - if (authRequestId) { - params.set("authRequestId", authRequestId); - } - if (resp?.factors?.user?.loginName) { - params.set("loginName", resp.factors.user.loginName); - } - - return router.push(`/signedin?` + params); - } + return authRequestId && resp?.sessionId + ? finishFlow({ + sessionId: resp.sessionId, + authRequestId: authRequestId, + organization: organization, + }) + : resp?.factors?.user?.loginName + ? finishFlow({ + loginName: resp.factors.user.loginName, + organization: organization, + }) + : null; }); }); } diff --git a/apps/login/src/components/register-u2f.tsx b/apps/login/src/components/register-u2f.tsx index ea0cdc1f583..edb3c54944f 100644 --- a/apps/login/src/components/register-u2f.tsx +++ b/apps/login/src/components/register-u2f.tsx @@ -1,6 +1,7 @@ "use client"; import { coerceToArrayBuffer, coerceToBase64Url } from "@/helpers/base64"; +import { finishFlow } from "@/lib/login"; import { addU2F, verifyU2F } from "@/lib/server/u2f"; import { RegisterU2FResponse } from "@zitadel/proto/zitadel/user/v2/user_service_pb"; import { useTranslations } from "next-intl"; @@ -62,7 +63,7 @@ export function RegisterU2f({ return response; } - async function submitRegisterAndContinue(): Promise { + async function submitRegisterAndContinue(): Promise { setError(""); setLoading(true); const response = await addU2F({ @@ -146,38 +147,37 @@ export function RegisterU2f({ return; } - const paramsToContinue = new URLSearchParams({}); - let urlToContinue = "/accounts"; - - if (sessionId) { - paramsToContinue.append("sessionId", sessionId); - } - - if (loginName) { - paramsToContinue.append("loginName", loginName); - } - if (organization) { - paramsToContinue.append("organization", organization); - } - if (checkAfter) { - if (authRequestId) { - paramsToContinue.append("authRequestId", authRequestId); - } - urlToContinue = `/u2f?` + paramsToContinue; - } else if (authRequestId && sessionId) { - if (authRequestId) { - paramsToContinue.append("authRequest", authRequestId); - } - urlToContinue = `/login?` + paramsToContinue; - } else if (loginName) { - if (authRequestId) { - paramsToContinue.append("authRequestId", authRequestId); - } - urlToContinue = `/signedin?` + paramsToContinue; - } + const paramsToContinue = new URLSearchParams({}); - router.push(urlToContinue); + if (sessionId) { + paramsToContinue.append("sessionId", sessionId); + } + if (loginName) { + paramsToContinue.append("loginName", loginName); + } + if (organization) { + paramsToContinue.append("organization", organization); + } + if (authRequestId) { + paramsToContinue.append("authRequestId", authRequestId); + } + + return router.push(`/u2f?` + paramsToContinue); + } else { + return authRequestId && sessionId + ? finishFlow({ + sessionId: sessionId, + authRequestId: authRequestId, + organization: organization, + }) + : loginName + ? finishFlow({ + loginName: loginName, + organization: organization, + }) + : null; + } } } diff --git a/apps/login/src/components/totp-register.tsx b/apps/login/src/components/totp-register.tsx index c3f9b03e2ad..37a744fe971 100644 --- a/apps/login/src/components/totp-register.tsx +++ b/apps/login/src/components/totp-register.tsx @@ -1,4 +1,5 @@ "use client"; +import { finishFlow } from "@/lib/login"; import { verifyTOTP } from "@/lib/server-actions"; import { useTranslations } from "next-intl"; import Link from "next/link"; @@ -67,31 +68,18 @@ export function TotpRegister({ return router.push(`/otp/time-based?` + params); } else { - if (authRequestId && sessionId) { - const params = new URLSearchParams({ - sessionId: sessionId, - authRequest: authRequestId, - }); - - 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); - } + return authRequestId && sessionId + ? finishFlow({ + sessionId: sessionId, + authRequestId: authRequestId, + organization: organization, + }) + : loginName + ? finishFlow({ + loginName: loginName, + organization: organization, + }) + : null; } }) .catch((e) => { diff --git a/apps/login/src/lib/login.ts b/apps/login/src/lib/login.ts index 39f3396c9f8..765255a945a 100644 --- a/apps/login/src/lib/login.ts +++ b/apps/login/src/lib/login.ts @@ -8,7 +8,7 @@ type FinishFlowCommand = | { loginName: string }; /** - * redirects user back to OIDC application or to a success page + * on client: redirects user back to OIDC application or to a success page * @param command * @returns */ From 5db61c8623148599cc3f7b31b4f4e1f0baaf1b1d Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Mon, 18 Nov 2024 10:41:13 +0100 Subject: [PATCH 04/40] idp cleanup --- .../login/src/components/sign-in-with-idp.tsx | 46 ++++++++++--------- apps/login/src/lib/server/idp.ts | 9 ++++ 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/apps/login/src/components/sign-in-with-idp.tsx b/apps/login/src/components/sign-in-with-idp.tsx index 90520d449bc..e19564b81a6 100644 --- a/apps/login/src/components/sign-in-with-idp.tsx +++ b/apps/login/src/components/sign-in-with-idp.tsx @@ -64,17 +64,6 @@ export function SignInWithIdp({ 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); - } - } - return (
{identityProviders && @@ -86,7 +75,7 @@ export function SignInWithIdp({ key={`idp-${i}`} name={idp.name} onClick={() => - navigateToAuthUrl(idp.id, IdentityProviderType.APPLE) + startFlow(idp.id, idpTypeToSlug(IdentityProviderType.APPLE)) } > ); @@ -96,7 +85,7 @@ export function SignInWithIdp({ key={`idp-${i}`} name={idp.name} onClick={() => - navigateToAuthUrl(idp.id, IdentityProviderType.OAUTH) + startFlow(idp.id, idpTypeToSlug(IdentityProviderType.OAUTH)) } > ); @@ -106,7 +95,7 @@ export function SignInWithIdp({ key={`idp-${i}`} name={idp.name} onClick={() => - navigateToAuthUrl(idp.id, IdentityProviderType.OIDC) + startFlow(idp.id, idpTypeToSlug(IdentityProviderType.OIDC)) } > ); @@ -116,7 +105,10 @@ export function SignInWithIdp({ key={`idp-${i}`} name={idp.name} onClick={() => - navigateToAuthUrl(idp.id, IdentityProviderType.GITHUB) + startFlow( + idp.id, + idpTypeToSlug(IdentityProviderType.GITHUB), + ) } > ); @@ -126,7 +118,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 +131,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 +145,10 @@ export function SignInWithIdp({ e2e="google" name={idp.name} onClick={() => - navigateToAuthUrl(idp.id, IdentityProviderType.GOOGLE) + startFlow( + idp.id, + idpTypeToSlug(IdentityProviderType.GOOGLE), + ) } > ); @@ -157,7 +158,10 @@ export function SignInWithIdp({ key={`idp-${i}`} name={idp.name} onClick={() => - navigateToAuthUrl(idp.id, IdentityProviderType.GITLAB) + startFlow( + idp.id, + idpTypeToSlug(IdentityProviderType.GITLAB), + ) } > ); @@ -167,9 +171,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/lib/server/idp.ts b/apps/login/src/lib/server/idp.ts index be00840626b..019b05ecbce 100644 --- a/apps/login/src/lib/server/idp.ts +++ b/apps/login/src/lib/server/idp.ts @@ -1,6 +1,7 @@ "use server"; import { startIdentityProviderFlow } from "@/lib/zitadel"; +import { redirect } from "next/navigation"; export type StartIDPFlowCommand = { idpId: string; @@ -15,5 +16,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); + } }); } From fd90fcb752af66437ff97b9e924294036b48f291 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Mon, 18 Nov 2024 10:42:21 +0100 Subject: [PATCH 05/40] format --- apps/login/src/components/idp-signin.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/login/src/components/idp-signin.tsx b/apps/login/src/components/idp-signin.tsx index 657d72e39a6..aee4bc77883 100644 --- a/apps/login/src/components/idp-signin.tsx +++ b/apps/login/src/components/idp-signin.tsx @@ -34,7 +34,8 @@ export function IdpSignin({ idpIntentToken, }, authRequestId, - }).catch((error) => { + }) + .catch((error) => { setError(error.message); return; }) From 56f2b90c76efb89dffabbbce7fcc55289232e876 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Mon, 18 Nov 2024 17:30:46 +0100 Subject: [PATCH 06/40] finish flow --- apps/login/locales/de.json | 3 +- apps/login/locales/en.json | 3 +- apps/login/locales/es.json | 3 +- apps/login/locales/it.json | 3 +- apps/login/readme.md | 8 ++++ apps/login/src/app/(login)/signedin/page.tsx | 30 ++++++++++++++- apps/login/src/components/login-passkey.tsx | 6 +-- apps/login/src/lib/login.ts | 40 ++++++++++++-------- 8 files changed, 72 insertions(+), 24 deletions(-) diff --git a/apps/login/locales/de.json b/apps/login/locales/de.json index ef71731d1fe..c6576de0001 100644 --- a/apps/login/locales/de.json +++ b/apps/login/locales/de.json @@ -151,7 +151,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..4bb7bfe5524 100644 --- a/apps/login/locales/en.json +++ b/apps/login/locales/en.json @@ -151,7 +151,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..e7f093dc5da 100644 --- a/apps/login/locales/es.json +++ b/apps/login/locales/es.json @@ -151,7 +151,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..0b488e00a27 100644 --- a/apps/login/locales/it.json +++ b/apps/login/locales/it.json @@ -151,7 +151,8 @@ }, "signedin": { "title": "Benvenuto {user}!", - "description": "Sei connesso." + "description": "Sei connesso.", + "continue": "Continua" }, "verify": { "userIdMissing": "Nessun userId fornito!", diff --git a/apps/login/readme.md b/apps/login/readme.md index 190fcf60026..38eee55b90d 100644 --- a/apps/login/readme.md +++ b/apps/login/readme.md @@ -386,3 +386,11 @@ 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 +- loginSettings lifetimes - all besides Multifactor Init Check can be implemented. for the Init Check, an external storage or a timestamp has to be implemented which keeps track of the last verification diff --git a/apps/login/src/app/(login)/signedin/page.tsx b/apps/login/src/app/(login)/signedin/page.tsx index b2274478ea5..3833d1b7536 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) { @@ -48,6 +55,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 +78,22 @@ export default async function Page({ searchParams }: { searchParams: any }) { {sessionFactors?.id && ( )} + + {loginSettings?.defaultRedirectUri && ( +
+ + + + + +
+ )}
); diff --git a/apps/login/src/components/login-passkey.tsx b/apps/login/src/components/login-passkey.tsx index ab801028fec..87691ea47c2 100644 --- a/apps/login/src/components/login-passkey.tsx +++ b/apps/login/src/components/login-passkey.tsx @@ -176,15 +176,15 @@ export function LoginPasskey({ }, }; - return submitLogin(data).then((resp) => { + return submitLogin(data).then(async (resp) => { return authRequestId && resp?.sessionId - ? finishFlow({ + ? await finishFlow({ sessionId: resp.sessionId, authRequestId: authRequestId, organization: organization, }) : resp?.factors?.user?.loginName - ? finishFlow({ + ? await finishFlow({ loginName: resp.factors.user.loginName, organization: organization, }) diff --git a/apps/login/src/lib/login.ts b/apps/login/src/lib/login.ts index 765255a945a..ec023b8a9cf 100644 --- a/apps/login/src/lib/login.ts +++ b/apps/login/src/lib/login.ts @@ -1,4 +1,5 @@ import { redirect } from "next/navigation"; +import { getLoginSettings } from "./zitadel"; type FinishFlowCommand = | { @@ -8,25 +9,32 @@ type FinishFlowCommand = | { loginName: string }; /** - * on client: redirects user back to OIDC application or to a success page + * 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 function finishFlow( +export async function finishFlow( command: FinishFlowCommand & { organization?: string }, ) { - return "sessionId" in command && "authRequestId" in command - ? redirect( - `/login?` + - new URLSearchParams({ - sessionId: command.sessionId, - authRequest: command.authRequestId, - }), - ) - : redirect( - `/signedin?` + - new URLSearchParams({ - loginName: command.loginName, - }), - ); + if ("sessionId" in command && "authRequestId" in command) { + return redirect( + `/login?` + + new URLSearchParams({ + sessionId: command.sessionId, + authRequest: command.authRequestId, + }), + ); + } + + const loginSettings = await getLoginSettings(command.organization); + if (loginSettings?.defaultRedirectUri) { + return redirect(loginSettings.defaultRedirectUri); + } + + return redirect( + `/signedin?` + + new URLSearchParams({ + loginName: command.loginName, + }), + ); } From dcee01d09fb708f9b2b760478407240e510d7f22 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Tue, 19 Nov 2024 15:57:40 +0100 Subject: [PATCH 07/40] cleanup register, check for allowed methods --- apps/login/locales/de.json | 8 +++ apps/login/locales/en.json | 8 +++ apps/login/locales/es.json | 8 +++ apps/login/locales/it.json | 8 +++ apps/login/src/app/(login)/register/page.tsx | 32 ++++----- .../app/(login)/register/password/page.tsx | 70 +++++++++++++++++++ .../register-form-without-password.tsx | 31 +++++--- 7 files changed, 135 insertions(+), 30 deletions(-) create mode 100644 apps/login/src/app/(login)/register/password/page.tsx diff --git a/apps/login/locales/de.json b/apps/login/locales/de.json index c6576de0001..62691051a95 100644 --- a/apps/login/locales/de.json +++ b/apps/login/locales/de.json @@ -122,6 +122,14 @@ } }, "register": { + "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", diff --git a/apps/login/locales/en.json b/apps/login/locales/en.json index 4bb7bfe5524..68fa95e8102 100644 --- a/apps/login/locales/en.json +++ b/apps/login/locales/en.json @@ -122,6 +122,14 @@ } }, "register": { + "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", diff --git a/apps/login/locales/es.json b/apps/login/locales/es.json index e7f093dc5da..4b658bbdd06 100644 --- a/apps/login/locales/es.json +++ b/apps/login/locales/es.json @@ -122,6 +122,14 @@ } }, "register": { + "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", diff --git a/apps/login/locales/it.json b/apps/login/locales/it.json index 0b488e00a27..2e6a7686b25 100644 --- a/apps/login/locales/it.json +++ b/apps/login/locales/it.json @@ -122,6 +122,14 @@ } }, "register": { + "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", diff --git a/apps/login/src/app/(login)/register/page.tsx b/apps/login/src/app/(login)/register/page.tsx index f23582ae3f7..06cb928d9ad 100644 --- a/apps/login/src/app/(login)/register/page.tsx +++ b/apps/login/src/app/(login)/register/page.tsx @@ -1,10 +1,10 @@ import { DynamicTheme } from "@/components/dynamic-theme"; import { RegisterFormWithoutPassword } from "@/components/register-form-without-password"; -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"; @@ -36,25 +36,18 @@ export default async function Page({ 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")}

@@ -68,6 +61,7 @@ export default async function Page({ lastname={lastname} email={email} authRequestId={authRequestId} + 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..66843d45ac4 --- /dev/null +++ b/apps/login/src/app/(login)/register/password/page.tsx @@ -0,0 +1,70 @@ +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({ + searchParams, +}: { + searchParams: Record; +}) { + 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/components/register-form-without-password.tsx b/apps/login/src/components/register-form-without-password.tsx index 52b6c3b9a4e..8392c9e903a 100644 --- a/apps/login/src/components/register-form-without-password.tsx +++ b/apps/login/src/components/register-form-without-password.tsx @@ -2,6 +2,10 @@ 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"; @@ -32,6 +36,7 @@ type Props = { email?: string; organization?: string; authRequestId?: string; + loginSettings?: LoginSettings; }; export function RegisterFormWithoutPassword({ @@ -41,6 +46,7 @@ export function RegisterFormWithoutPassword({ lastname, organization, authRequestId, + loginSettings, }: Props) { const t = useTranslations("register"); @@ -99,7 +105,9 @@ export function RegisterFormWithoutPassword({ } if (withPassword) { - return router.push(`/register?` + new URLSearchParams(registerParams)); + return router.push( + `/register/password?` + new URLSearchParams(registerParams), + ); } else { return submitAndRegister(value); } @@ -143,29 +151,30 @@ 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/app/(login)/passkey/page.tsx b/apps/login/src/app/(login)/passkey/page.tsx index fc0f701e805..09605ad3827 100644 --- a/apps/login/src/app/(login)/passkey/page.tsx +++ b/apps/login/src/app/(login)/passkey/page.tsx @@ -4,7 +4,11 @@ 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({ @@ -37,6 +41,8 @@ export default async function Page({ const branding = await getBrandingSettings(organization); + const loginSettings = await getLoginSettings(organization); + return (
@@ -61,6 +67,7 @@ export default async function Page({ authRequestId={authRequestId} altPassword={altPassword === "true"} organization={organization} + loginSettings={loginSettings} /> )}
diff --git a/apps/login/src/components/login-otp.tsx b/apps/login/src/components/login-otp.tsx index cc1e272be96..74c0c0b2624 100644 --- a/apps/login/src/components/login-otp.tsx +++ b/apps/login/src/components/login-otp.tsx @@ -1,10 +1,11 @@ "use client"; -import { finishFlow } from "@/lib/login"; +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"; @@ -23,6 +24,7 @@ type Props = { organization?: string; method: string; code?: string; + loginSettings?: LoginSettings; }; type Inputs = { @@ -36,6 +38,7 @@ export function LoginOTP({ organization, method, code, + loginSettings, }: Props) { const t = useTranslations("otp"); @@ -153,20 +156,31 @@ export function LoginOTP({ } function setCodeAndContinue(values: Inputs, organization?: string) { - return submitCode(values, organization).then((response) => { + return submitCode(values, organization).then(async (response) => { if (response) { - return authRequestId && response.sessionId - ? finishFlow({ - sessionId: response.sessionId, - authRequestId: authRequestId, - organization: response.factors?.user?.organizationId, - }) - : response.factors?.user - ? finishFlow({ - loginName: response.factors.user.loginName, - organization: response.factors?.user?.organizationId, - }) - : null; + 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 (url) { + router.push(url); + } } }); } diff --git a/apps/login/src/components/login-passkey.tsx b/apps/login/src/components/login-passkey.tsx index c4dfb7dfe17..dda6b1ef567 100644 --- a/apps/login/src/components/login-passkey.tsx +++ b/apps/login/src/components/login-passkey.tsx @@ -1,7 +1,7 @@ "use client"; import { coerceToArrayBuffer, coerceToBase64Url } from "@/helpers/base64"; -import { finishFlow } from "@/lib/login"; +import { getNextUrl } from "@/lib/client"; import { updateSession } from "@/lib/server/session"; import { create } from "@zitadel/client"; import { @@ -9,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"; @@ -25,6 +26,7 @@ type Props = { altPassword: boolean; login?: boolean; organization?: string; + loginSettings?: LoginSettings; }; export function LoginPasskey({ @@ -34,6 +36,7 @@ export function LoginPasskey({ altPassword, organization, login = true, + loginSettings, }: Props) { const t = useTranslations("passkey"); @@ -177,18 +180,29 @@ export function LoginPasskey({ }; return submitLogin(data).then(async (resp) => { - return authRequestId && resp?.sessionId - ? await finishFlow({ - sessionId: resp.sessionId, - authRequestId: authRequestId, - organization: organization, - }) - : resp?.factors?.user?.loginName - ? await finishFlow({ - loginName: resp.factors.user.loginName, - organization: organization, - }) - : null; + 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 (url) { + router.push(url); + } }); }); } diff --git a/apps/login/src/components/register-u2f.tsx b/apps/login/src/components/register-u2f.tsx index b749c72f138..8c8cd503d9b 100644 --- a/apps/login/src/components/register-u2f.tsx +++ b/apps/login/src/components/register-u2f.tsx @@ -1,8 +1,9 @@ "use client"; import { coerceToArrayBuffer, coerceToBase64Url } from "@/helpers/base64"; -import { finishFlow } from "@/lib/login"; +import { getNextUrl } from "@/lib/client"; import { addU2F, verifyU2F } from "@/lib/server/u2f"; +import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb"; import { RegisterU2FResponse } from "@zitadel/proto/zitadel/user/v2/user_service_pb"; import { useTranslations } from "next-intl"; import { useRouter } from "next/navigation"; @@ -18,6 +19,7 @@ type Props = { authRequestId?: string; organization?: string; checkAfter: boolean; + loginSettings?: LoginSettings; }; export function RegisterU2f({ @@ -26,6 +28,7 @@ export function RegisterU2f({ organization, authRequestId, checkAfter, + loginSettings, }: Props) { const t = useTranslations("u2f"); @@ -165,18 +168,28 @@ export function RegisterU2f({ return router.push(`/u2f?` + paramsToContinue); } else { - return authRequestId && sessionId - ? finishFlow({ - sessionId: sessionId, - authRequestId: authRequestId, - organization: organization, - }) - : loginName - ? finishFlow({ - loginName: loginName, - organization: organization, - }) - : null; + 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 (url) { + return router.push(url); + } } } } diff --git a/apps/login/src/components/totp-register.tsx b/apps/login/src/components/totp-register.tsx index ee40f202f13..e8519981715 100644 --- a/apps/login/src/components/totp-register.tsx +++ b/apps/login/src/components/totp-register.tsx @@ -1,6 +1,7 @@ "use client"; -import { finishFlow } from "@/lib/login"; +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"; @@ -25,6 +26,7 @@ type Props = { authRequestId?: string; organization?: string; checkAfter?: boolean; + loginSettings?: LoginSettings; }; export function TotpRegister({ uri, @@ -34,6 +36,7 @@ export function TotpRegister({ authRequestId, organization, checkAfter, + loginSettings, }: Props) { const t = useTranslations("otp"); @@ -51,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({}); @@ -68,18 +71,29 @@ export function TotpRegister({ return router.push(`/otp/time-based?` + params); } else { - return authRequestId && sessionId - ? finishFlow({ - sessionId: sessionId, - authRequestId: authRequestId, - organization: organization, - }) - : loginName - ? finishFlow({ - loginName: loginName, - organization: organization, - }) - : null; + 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 (url) { + return router.push(url); + } } }) .catch((e) => { diff --git a/apps/login/src/lib/login.ts b/apps/login/src/lib/client.ts similarity index 51% rename from apps/login/src/lib/login.ts rename to apps/login/src/lib/client.ts index ec023b8a9cf..7dc2b83cbb0 100644 --- a/apps/login/src/lib/login.ts +++ b/apps/login/src/lib/client.ts @@ -1,6 +1,3 @@ -import { redirect } from "next/navigation"; -import { getLoginSettings } from "./zitadel"; - type FinishFlowCommand = | { sessionId: string; @@ -13,28 +10,29 @@ type FinishFlowCommand = * @param command * @returns */ -export async function finishFlow( +export async function getNextUrl( command: FinishFlowCommand & { organization?: string }, -) { + defaultRedirectUri?: string, +): Promise { if ("sessionId" in command && "authRequestId" in command) { - return redirect( + const url = `/login?` + - new URLSearchParams({ - sessionId: command.sessionId, - authRequest: command.authRequestId, - }), - ); - } - - const loginSettings = await getLoginSettings(command.organization); - if (loginSettings?.defaultRedirectUri) { - return redirect(loginSettings.defaultRedirectUri); - } - - return redirect( - `/signedin?` + new URLSearchParams({ - loginName: command.loginName, - }), - ); + 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/server/register.ts b/apps/login/src/lib/server/register.ts index eebb9ccd69a..fc37466a56f 100644 --- a/apps/login/src/lib/server/register.ts +++ b/apps/login/src/lib/server/register.ts @@ -1,7 +1,7 @@ "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 { @@ -9,7 +9,7 @@ import { ChecksSchema, } from "@zitadel/proto/zitadel/session/v2/session_service_pb"; import { redirect } from "next/navigation"; -import { finishFlow } from "../login"; +import { getNextUrl } from "../client"; type RegisterUserCommand = { email: string; @@ -73,7 +73,11 @@ export async function registerUser(command: RegisterUserCommand) { return redirect("/passkey/set?" + params); } else { - return finishFlow( + const loginSettings = await getLoginSettings( + session.factors.user.organizationId, + ); + + const url = await getNextUrl( command.authRequestId && session.id ? { sessionId: session.id, @@ -84,6 +88,9 @@ export async function registerUser(command: RegisterUserCommand) { loginName: session.factors.user.loginName, organization: session.factors.user.organizationId, }, + loginSettings?.defaultRedirectUri, ); + + return redirect(url); } } diff --git a/apps/login/src/lib/server/session.ts b/apps/login/src/lib/server/session.ts index aad5f97cc74..bb08b05d36a 100644 --- a/apps/login/src/lib/server/session.ts +++ b/apps/login/src/lib/server/session.ts @@ -4,17 +4,22 @@ import { createSessionForIdpAndUpdateCookie, setSessionAndUpdateCookie, } from "@/lib/server/cookie"; -import { deleteSession, listAuthenticationMethodTypes } from "@/lib/zitadel"; +import { + deleteSession, + getLoginSettings, + listAuthenticationMethodTypes, +} from "@/lib/zitadel"; 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 { redirect } from "next/navigation"; +import { getNextUrl } from "../client"; import { getMostRecentSessionCookie, getSessionCookieById, getSessionCookieByLoginName, removeSessionFromCookie, } from "../cookies"; -import { finishFlow } from "../login"; type CreateNewSessionCommand = { userId: string; @@ -43,7 +48,11 @@ export async function createNewSessionForIdp(options: CreateNewSessionCommand) { return { error: "Could not create session" }; } - return finishFlow( + const loginSettings = await getLoginSettings( + session.factors.user.organizationId, + ); + + const url = await getNextUrl( authRequestId && session.id ? { sessionId: session.id, @@ -54,25 +63,44 @@ export async function createNewSessionForIdp(options: CreateNewSessionCommand) { 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 }) { - return authRequestId && session.id && session.factors?.user - ? finishFlow({ - sessionId: session.id, - authRequestId: authRequestId, - organization: session.factors.user.organizationId, - }) - : session.factors?.user - ? finishFlow({ - loginName: session.factors.user.loginName, - organization: session.factors.user.organizationId, - }) - : null; + 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 = { From 21cd5e7c1cde5ba8bf0c4ca2296faa1a23e579f4 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Thu, 21 Nov 2024 10:53:23 +0100 Subject: [PATCH 10/40] initial stub for loginsettings --- .../zitadel.settings.v2.SettingsService.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) 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..816adbfe8cb 100644 --- a/apps/login/mock/initial-stubs/zitadel.settings.v2.SettingsService.json +++ b/apps/login/mock/initial-stubs/zitadel.settings.v2.SettingsService.json @@ -46,5 +46,17 @@ } } } + }, + { + "service": "zitadel.settings.v2.SettingsService", + "method": "GetLoginSettings", + "out": { + "data": { + "settings": { + "passkeysType": 1, + "defaultRedirectUri": "" + } + } + } } ] From 68f7ea5ef04ab3d48db2b127042a99351c3bb12b Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Thu, 21 Nov 2024 14:12:13 +0100 Subject: [PATCH 11/40] cleanup register --- apps/login/src/app/(login)/register/page.tsx | 8 +-- apps/login/src/components/password-form.tsx | 4 -- ...without-password.tsx => register-form.tsx} | 10 ++-- apps/login/src/lib/server/password.ts | 58 +++++++++---------- 4 files changed, 35 insertions(+), 45 deletions(-) rename apps/login/src/components/{register-form-without-password.tsx => register-form.tsx} (93%) diff --git a/apps/login/src/app/(login)/register/page.tsx b/apps/login/src/app/(login)/register/page.tsx index 06cb928d9ad..00adc174b21 100644 --- a/apps/login/src/app/(login)/register/page.tsx +++ b/apps/login/src/app/(login)/register/page.tsx @@ -1,5 +1,5 @@ import { DynamicTheme } from "@/components/dynamic-theme"; -import { RegisterFormWithoutPassword } from "@/components/register-form-without-password"; +import { RegisterForm } from "@/components/register-form"; import { getBrandingSettings, getDefaultOrg, @@ -28,8 +28,6 @@ export default async function Page({ } } - const setPassword = !!(firstname && lastname && email); - const legal = await getLegalAndSupportSettings(organization); const passwordComplexitySettings = await getPasswordComplexitySettings(organization); @@ -54,7 +52,7 @@ export default async function Page({

{t("description")}

{legal && passwordComplexitySettings && ( - + > )}
diff --git a/apps/login/src/components/password-form.tsx b/apps/login/src/components/password-form.tsx index 5885ecc6d44..8c715236491 100644 --- a/apps/login/src/components/password-form.tsx +++ b/apps/login/src/components/password-form.tsx @@ -73,10 +73,6 @@ export function PasswordForm({ setError(response.error); return; } - - if (response && response.nextStep) { - return router.push(response.nextStep); - } } async function resetPasswordAndContinue() { diff --git a/apps/login/src/components/register-form-without-password.tsx b/apps/login/src/components/register-form.tsx similarity index 93% rename from apps/login/src/components/register-form-without-password.tsx rename to apps/login/src/components/register-form.tsx index 19abe482a6a..0655a15f4be 100644 --- a/apps/login/src/components/register-form-without-password.tsx +++ b/apps/login/src/components/register-form.tsx @@ -39,7 +39,7 @@ type Props = { loginSettings?: LoginSettings; }; -export function RegisterFormWithoutPassword({ +export function RegisterForm({ legal, email, firstname, @@ -104,6 +104,7 @@ export function RegisterFormWithoutPassword({ registerParams.authRequestId = authRequestId; } + // redirect user to /register/password if password is chosen if (withPassword) { return router.push( `/register/password?` + new URLSearchParams(registerParams), @@ -116,7 +117,7 @@ export function RegisterFormWithoutPassword({ const { errors } = formState; const [tosAndPolicyAccepted, setTosAndPolicyAccepted] = useState(false); - + console.log(loginSettings); return (
@@ -188,8 +189,9 @@ export function RegisterFormWithoutPassword({ const usePasswordToContinue: boolean = loginSettings?.allowUsernamePassword && loginSettings?.passkeysType === PasskeysType.ALLOWED - ? !!!(selected.name === methods[0].name) - : !!loginSettings?.allowUsernamePassword; + ? !!!(selected.name === methods[0].name) // choose selection if both available + : !!loginSettings?.allowUsernamePassword; // if password is chosen + // set password as default if only password is allowed return submitAndContinue(values, usePasswordToContinue); })} data-testid="submit-button" diff --git a/apps/login/src/lib/server/password.ts b/apps/login/src/lib/server/password.ts index c01b7fb4dea..24ba10faf82 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, @@ -20,6 +21,7 @@ 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 = { @@ -240,42 +242,34 @@ 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, - }); - - if (command.organization || session.factors?.user?.organizationId) { - params.append( - "organization", - command.organization ?? session.factors?.user?.organizationId, - ); - } - - return { nextStep: `/login?${params}` }; - } - - // without OIDC flow - const params = new URLSearchParams( - command.authRequestId - ? { - loginName: session.factors.user.loginName, - authRequestId: command.authRequestId, - organization: session.factors.user.organizationId, - } - : { - loginName: session.factors.user.loginName, - }, - ); - - if (command.organization || session.factors?.user?.organizationId) { - params.append( - "organization", + const loginSettings = await getLoginSettings( command.organization ?? session.factors?.user?.organizationId, ); + const nextUrl = await getNextUrl( + { + sessionId: session.id, + authRequestId: command.authRequestId, + organization: + command.organization ?? session.factors?.user?.organizationId, + }, + loginSettings?.defaultRedirectUri, + ); + + return redirect(nextUrl); } - return { nextStep: `/signedin?${params}` }; + const loginSettings = await getLoginSettings( + command.organization ?? session.factors?.user?.organizationId, + ); + const url = await getNextUrl( + { + loginName: session.factors.user.loginName, + organization: session.factors?.user?.organizationId, + }, + loginSettings?.defaultRedirectUri, + ); + + return redirect(url); } export async function changePassword(command: { From 7e1445dda26006c8f14d3b71a91148824288ba03 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Thu, 21 Nov 2024 14:16:45 +0100 Subject: [PATCH 12/40] stub to allow register --- .../mock/initial-stubs/zitadel.settings.v2.SettingsService.json | 2 ++ 1 file changed, 2 insertions(+) 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 816adbfe8cb..fa1e4018f51 100644 --- a/apps/login/mock/initial-stubs/zitadel.settings.v2.SettingsService.json +++ b/apps/login/mock/initial-stubs/zitadel.settings.v2.SettingsService.json @@ -53,7 +53,9 @@ "out": { "data": { "settings": { + "allowRegister": "true", "passkeysType": 1, + "allowUsernamePassword": true, "defaultRedirectUri": "" } } From b1f6257e1073203c97b8f6db4e5eed10c3c15f67 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Thu, 21 Nov 2024 14:17:56 +0100 Subject: [PATCH 13/40] remove nextstep on pwd pages --- apps/login/src/components/change-password-form.tsx | 5 ----- apps/login/src/components/set-password-form.tsx | 5 ----- 2 files changed, 10 deletions(-) diff --git a/apps/login/src/components/change-password-form.tsx b/apps/login/src/components/change-password-form.tsx index c2e891ffb80..7a08687ac02 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"; @@ -107,10 +106,6 @@ export function ChangePasswordForm({ return; } - if (passwordResponse && passwordResponse.nextStep) { - return redirect(passwordResponse.nextStep); - } - return; } diff --git a/apps/login/src/components/set-password-form.tsx b/apps/login/src/components/set-password-form.tsx index 65405ed8f0d..b194065d2a1 100644 --- a/apps/login/src/components/set-password-form.tsx +++ b/apps/login/src/components/set-password-form.tsx @@ -11,7 +11,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"; @@ -127,10 +126,6 @@ export function SetPasswordForm({ return; } - if (passwordResponse && passwordResponse.nextStep) { - return redirect(passwordResponse.nextStep); - } - return; } From 5931c56fb51d5992dbddb4955121f2655efd6507 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Thu, 21 Nov 2024 14:26:55 +0100 Subject: [PATCH 14/40] boolean --- .../mock/initial-stubs/zitadel.settings.v2.SettingsService.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 fa1e4018f51..264b483c19d 100644 --- a/apps/login/mock/initial-stubs/zitadel.settings.v2.SettingsService.json +++ b/apps/login/mock/initial-stubs/zitadel.settings.v2.SettingsService.json @@ -53,7 +53,7 @@ "out": { "data": { "settings": { - "allowRegister": "true", + "allowRegister": true, "passkeysType": 1, "allowUsernamePassword": true, "defaultRedirectUri": "" From de787899de1126b97fff1375ea957d5c6861c12a Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Thu, 21 Nov 2024 16:31:51 +0100 Subject: [PATCH 15/40] auth method change --- apps/login/locales/de.json | 4 + apps/login/locales/en.json | 4 + apps/login/locales/es.json | 4 + apps/login/locales/it.json | 4 + .../authentication-method-radio.tsx | 109 ++++++++---------- apps/login/src/components/register-form.tsx | 5 +- 6 files changed, 68 insertions(+), 62 deletions(-) diff --git a/apps/login/locales/de.json b/apps/login/locales/de.json index 62691051a95..4d5f0c1530d 100644 --- a/apps/login/locales/de.json +++ b/apps/login/locales/de.json @@ -122,6 +122,10 @@ } }, "register": { + "methods": { + "passkey": "Passkey", + "password": "Password" + }, "disabled": { "title": "Registrierung deaktiviert", "description": "Die Registrierung ist deaktiviert. Bitte wenden Sie sich an den Administrator." diff --git a/apps/login/locales/en.json b/apps/login/locales/en.json index 68fa95e8102..c7fd5e30b9a 100644 --- a/apps/login/locales/en.json +++ b/apps/login/locales/en.json @@ -122,6 +122,10 @@ } }, "register": { + "methods": { + "passkey": "Passkey", + "password": "Password" + }, "disabled": { "title": "Registration disabled", "description": "The registration is disabled. Please contact your administrator." diff --git a/apps/login/locales/es.json b/apps/login/locales/es.json index 4b658bbdd06..e722db5812c 100644 --- a/apps/login/locales/es.json +++ b/apps/login/locales/es.json @@ -122,6 +122,10 @@ } }, "register": { + "methods": { + "passkey": "Clave de acceso", + "password": "Contraseña" + }, "disabled": { "title": "Registro deshabilitado", "description": "Registrarse está deshabilitado en este momento." diff --git a/apps/login/locales/it.json b/apps/login/locales/it.json index 2e6a7686b25..9467f0ba840 100644 --- a/apps/login/locales/it.json +++ b/apps/login/locales/it.json @@ -122,6 +122,10 @@ } }, "register": { + "methods": { + "passkey": "Passkey", + "password": "Password" + }, "disabled": { "title": "Registration disabled", "description": "Registrazione disabilitata. Contatta l'amministratore di sistema per assistenza." 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/register-form.tsx b/apps/login/src/components/register-form.tsx index 0655a15f4be..cf3f1631da1 100644 --- a/apps/login/src/components/register-form.tsx +++ b/apps/login/src/components/register-form.tsx @@ -12,6 +12,7 @@ import { useState } from "react"; import { FieldValues, useForm } from "react-hook-form"; import { Alert } from "./alert"; import { + AuthenticationMethod, AuthenticationMethodRadio, methods, } from "./authentication-method-radio"; @@ -60,7 +61,7 @@ export function RegisterForm({ }); const [loading, setLoading] = useState(false); - const [selected, setSelected] = useState(methods[0]); + const [selected, setSelected] = useState(methods[0]); const [error, setError] = useState(""); const router = useRouter(); @@ -189,7 +190,7 @@ export function RegisterForm({ const usePasswordToContinue: boolean = loginSettings?.allowUsernamePassword && loginSettings?.passkeysType === PasskeysType.ALLOWED - ? !!!(selected.name === methods[0].name) // choose selection if both available + ? !!!(selected === methods[0]) // choose selection if both available : !!loginSettings?.allowUsernamePassword; // if password is chosen // set password as default if only password is allowed return submitAndContinue(values, usePasswordToContinue); From 61bb6ac7566407c818383319025fc0b5896b157b Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Fri, 22 Nov 2024 08:46:16 +0100 Subject: [PATCH 16/40] change test ids --- acceptance/tests/register-screen.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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) { From ff73d8e3ccd2d52ad1aa4aca32f0e2ceb3ddb1fa Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Fri, 22 Nov 2024 09:41:44 +0100 Subject: [PATCH 17/40] use before stub --- apps/login/cypress/integration/register.cy.ts | 10 ++++++++++ apps/login/src/components/register-form.tsx | 1 - 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/login/cypress/integration/register.cy.ts b/apps/login/cypress/integration/register.cy.ts index 902c6a8061a..1040b91c14c 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", diff --git a/apps/login/src/components/register-form.tsx b/apps/login/src/components/register-form.tsx index cf3f1631da1..f4f1fec610e 100644 --- a/apps/login/src/components/register-form.tsx +++ b/apps/login/src/components/register-form.tsx @@ -118,7 +118,6 @@ export function RegisterForm({ const { errors } = formState; const [tosAndPolicyAccepted, setTosAndPolicyAccepted] = useState(false); - console.log(loginSettings); return (
From 19c310f83bed6cc403414b665668dcddbed8280b Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Fri, 22 Nov 2024 09:54:08 +0100 Subject: [PATCH 18/40] remove type check --- apps/login/readme.md | 2 +- apps/login/src/app/(login)/password/page.tsx | 2 +- apps/login/src/components/choose-authenticator-to-setup.tsx | 4 ++-- apps/login/src/components/register-form.tsx | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/login/readme.md b/apps/login/readme.md index 38eee55b90d..a1999e60412 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. diff --git a/apps/login/src/app/(login)/password/page.tsx b/apps/login/src/app/(login)/password/page.tsx index 9731e4030e8..2064e161ff5 100644 --- a/apps/login/src/app/(login)/password/page.tsx +++ b/apps/login/src/app/(login)/password/page.tsx @@ -83,7 +83,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/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/register-form.tsx b/apps/login/src/components/register-form.tsx index f4f1fec610e..9788ab0e7d8 100644 --- a/apps/login/src/components/register-form.tsx +++ b/apps/login/src/components/register-form.tsx @@ -165,7 +165,7 @@ export function RegisterForm({ {/* show chooser if both methods are allowed */} {loginSettings && loginSettings.allowUsernamePassword && - loginSettings.passkeysType === PasskeysType.ALLOWED && ( + loginSettings.passkeysType == PasskeysType.ALLOWED && (
{ const usePasswordToContinue: boolean = loginSettings?.allowUsernamePassword && - loginSettings?.passkeysType === PasskeysType.ALLOWED + loginSettings?.passkeysType == PasskeysType.ALLOWED ? !!!(selected === methods[0]) // choose selection if both available : !!loginSettings?.allowUsernamePassword; // if password is chosen // set password as default if only password is allowed From 837cd4f674a3ea9f921ac592e1aef70aa901947b Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Fri, 22 Nov 2024 11:25:03 +0100 Subject: [PATCH 19/40] update nextjs to 15 --- apps/login/cypress/integration/register.cy.ts | 8 +- .../zitadel.settings.v2.SettingsService.json | 24 +- apps/login/next.config.mjs | 3 + apps/login/package.json | 18 +- apps/login/src/app/(login)/accounts/page.tsx | 11 +- .../app/(login)/authenticator/set/page.tsx | 11 +- .../(login)/idp/[provider]/failure/page.tsx | 14 +- .../(login)/idp/[provider]/success/page.tsx | 19 +- apps/login/src/app/(login)/idp/page.tsx | 11 +- apps/login/src/app/(login)/invite/page.tsx | 11 +- .../src/app/(login)/invite/success/page.tsx | 11 +- apps/login/src/app/(login)/loginname/page.tsx | 11 +- apps/login/src/app/(login)/mfa/page.tsx | 11 +- apps/login/src/app/(login)/mfa/set/page.tsx | 11 +- .../src/app/(login)/otp/[method]/page.tsx | 15 +- .../src/app/(login)/otp/[method]/set/page.tsx | 15 +- apps/login/src/app/(login)/passkey/page.tsx | 11 +- .../src/app/(login)/passkey/set/page.tsx | 11 +- .../src/app/(login)/password/change/page.tsx | 11 +- apps/login/src/app/(login)/password/page.tsx | 11 +- .../src/app/(login)/password/set/page.tsx | 11 +- apps/login/src/app/(login)/register/page.tsx | 18 +- .../app/(login)/register/password/page.tsx | 23 +- apps/login/src/app/(login)/signedin/page.tsx | 3 +- apps/login/src/app/(login)/u2f/page.tsx | 11 +- apps/login/src/app/(login)/u2f/set/page.tsx | 11 +- apps/login/src/app/(login)/verify/page.tsx | 11 +- apps/login/src/components/register-form.tsx | 1 + apps/login/src/i18n/request.ts | 2 +- apps/login/src/lib/cookies.ts | 24 +- apps/login/src/lib/server/invite.ts | 2 +- apps/login/src/lib/server/loginname.ts | 4 +- apps/login/src/lib/server/passkeys.ts | 4 +- apps/login/src/lib/server/password.ts | 2 +- apps/login/src/lib/server/u2f.ts | 4 +- apps/login/src/lib/zitadel.ts | 101 +-- pnpm-lock.yaml | 842 ++++++++++++------ 37 files changed, 775 insertions(+), 547 deletions(-) diff --git a/apps/login/cypress/integration/register.cy.ts b/apps/login/cypress/integration/register.cy.ts index 1040b91c14c..262302c4c35 100644 --- a/apps/login/cypress/integration/register.cy.ts +++ b/apps/login/cypress/integration/register.cy.ts @@ -63,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/mock/initial-stubs/zitadel.settings.v2.SettingsService.json b/apps/login/mock/initial-stubs/zitadel.settings.v2.SettingsService.json index 264b483c19d..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", @@ -46,19 +54,5 @@ } } } - }, - { - "service": "zitadel.settings.v2.SettingsService", - "method": "GetLoginSettings", - "out": { - "data": { - "settings": { - "allowRegister": true, - "passkeysType": 1, - "allowUsernamePassword": true, - "defaultRedirectUri": "" - } - } - } } ] diff --git a/apps/login/next.config.mjs b/apps/login/next.config.mjs index e2906b1fa89..e42b4ef7a19 100755 --- a/apps/login/next.config.mjs +++ b/apps/login/next.config.mjs @@ -37,6 +37,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..e621cb567a8 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": "15.0.3", "next-intl": "^3.20.0", "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", @@ -88,5 +88,11 @@ "ts-proto": "^2.2.7", "typescript": "^5.6.3", "zitadel-tailwind-config": "workspace:*" + }, + "pnpm": { + "overrides": { + "@types/react": "npm:types-react@19.0.0-rc.1", + "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1" + } } } diff --git a/apps/login/src/app/(login)/accounts/page.tsx b/apps/login/src/app/(login)/accounts/page.tsx index d8813fada0c..e072d7c2e7e 100644 --- a/apps/login/src/app/(login)/accounts/page.tsx +++ b/apps/login/src/app/(login)/accounts/page.tsx @@ -20,11 +20,12 @@ 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..e2f093adb95 100644 --- a/apps/login/src/app/(login)/authenticator/set/page.tsx +++ b/apps/login/src/app/(login)/authenticator/set/page.tsx @@ -15,11 +15,12 @@ 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..8729c1e9781 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,13 @@ 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..eb62bd35bc0 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,14 @@ 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; @@ -137,12 +138,12 @@ export default async function Page({ if (idpLink) { return ( // TODO: possibily login user now - + (

{t("linkingSuccess.title")}

{t("linkingSuccess.description")}
-
+
) ); } } diff --git a/apps/login/src/app/(login)/idp/page.tsx b/apps/login/src/app/(login)/idp/page.tsx index ee43d5582c6..cbf0a1ae788 100644 --- a/apps/login/src/app/(login)/idp/page.tsx +++ b/apps/login/src/app/(login)/idp/page.tsx @@ -12,11 +12,12 @@ 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..c11131b50a6 100644 --- a/apps/login/src/app/(login)/invite/page.tsx +++ b/apps/login/src/app/(login)/invite/page.tsx @@ -9,11 +9,12 @@ 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..5955a8ecc30 100644 --- a/apps/login/src/app/(login)/invite/success/page.tsx +++ b/apps/login/src/app/(login)/invite/success/page.tsx @@ -7,11 +7,12 @@ 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)/loginname/page.tsx b/apps/login/src/app/(login)/loginname/page.tsx index 68928755d33..89b58f516e9 100644 --- a/apps/login/src/app/(login)/loginname/page.tsx +++ b/apps/login/src/app/(login)/loginname/page.tsx @@ -19,11 +19,12 @@ 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..96c708ba636 100644 --- a/apps/login/src/app/(login)/mfa/page.tsx +++ b/apps/login/src/app/(login)/mfa/page.tsx @@ -12,11 +12,12 @@ 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..4c1a7b7207a 100644 --- a/apps/login/src/app/(login)/mfa/set/page.tsx +++ b/apps/login/src/app/(login)/mfa/set/page.tsx @@ -32,11 +32,12 @@ 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 63bdbf551d6..fbeca2fa37b 100644 --- a/apps/login/src/app/(login)/otp/[method]/page.tsx +++ b/apps/login/src/app/(login)/otp/[method]/page.tsx @@ -6,13 +6,14 @@ import { loadMostRecentSession } from "@/lib/session"; 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" }); 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 9fb279e5f9f..2a8b0ea790a 100644 --- a/apps/login/src/app/(login)/otp/[method]/set/page.tsx +++ b/apps/login/src/app/(login)/otp/[method]/set/page.tsx @@ -17,13 +17,14 @@ 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" }); diff --git a/apps/login/src/app/(login)/passkey/page.tsx b/apps/login/src/app/(login)/passkey/page.tsx index 09605ad3827..d6791676f72 100644 --- a/apps/login/src/app/(login)/passkey/page.tsx +++ b/apps/login/src/app/(login)/passkey/page.tsx @@ -11,11 +11,12 @@ 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: "passkey" }); const tError = await getTranslations({ locale, namespace: "error" }); diff --git a/apps/login/src/app/(login)/passkey/set/page.tsx b/apps/login/src/app/(login)/passkey/set/page.tsx index 45ea1d78035..4e4e4f24f0a 100644 --- a/apps/login/src/app/(login)/passkey/set/page.tsx +++ b/apps/login/src/app/(login)/passkey/set/page.tsx @@ -6,11 +6,12 @@ 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..a697547f8f3 100644 --- a/apps/login/src/app/(login)/password/change/page.tsx +++ b/apps/login/src/app/(login)/password/change/page.tsx @@ -10,11 +10,12 @@ 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 2064e161ff5..da7b91fbd78 100644 --- a/apps/login/src/app/(login)/password/page.tsx +++ b/apps/login/src/app/(login)/password/page.tsx @@ -12,11 +12,12 @@ 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" }); diff --git a/apps/login/src/app/(login)/password/set/page.tsx b/apps/login/src/app/(login)/password/set/page.tsx index b7cd7c0d1bd..c44f236c38e 100644 --- a/apps/login/src/app/(login)/password/set/page.tsx +++ b/apps/login/src/app/(login)/password/set/page.tsx @@ -13,11 +13,12 @@ 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 00adc174b21..497c1ac6e44 100644 --- a/apps/login/src/app/(login)/register/page.tsx +++ b/apps/login/src/app/(login)/register/page.tsx @@ -10,11 +10,12 @@ import { 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" }); @@ -39,8 +40,11 @@ export default async function Page({ if (!loginSettings?.allowRegister) { return ( -
{t("disabled.title")}
-

{t("disabled.description")}

+
+

{t("disabled.title")}

+

{t("disabled.description")}

+ {JSON.stringify(loginSettings)} +
); } diff --git a/apps/login/src/app/(login)/register/password/page.tsx b/apps/login/src/app/(login)/register/password/page.tsx index 66843d45ac4..c1d1a895eeb 100644 --- a/apps/login/src/app/(login)/register/password/page.tsx +++ b/apps/login/src/app/(login)/register/password/page.tsx @@ -10,11 +10,12 @@ import { 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" }); @@ -40,8 +41,10 @@ export default async function Page({ return missingData ? ( -
{t("missingdata.title")}
-

{t("missingdata.description")}

+
+

{t("missingdata.title")}

+

{t("missingdata.description")}

+
) : loginSettings?.allowRegister && loginSettings.allowUsernamePassword ? ( @@ -63,8 +66,10 @@ export default async function Page({ ) : ( -
{t("disabled.title")}
-

{t("disabled.description")}

+
+

{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 3833d1b7536..4fc9ac85464 100644 --- a/apps/login/src/app/(login)/signedin/page.tsx +++ b/apps/login/src/app/(login)/signedin/page.tsx @@ -46,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" }); diff --git a/apps/login/src/app/(login)/u2f/page.tsx b/apps/login/src/app/(login)/u2f/page.tsx index 36fef6d7869..4dce6fdeaaf 100644 --- a/apps/login/src/app/(login)/u2f/page.tsx +++ b/apps/login/src/app/(login)/u2f/page.tsx @@ -7,11 +7,12 @@ 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..862b7024d2e 100644 --- a/apps/login/src/app/(login)/u2f/set/page.tsx +++ b/apps/login/src/app/(login)/u2f/set/page.tsx @@ -6,11 +6,12 @@ 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..c8e586f4091 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" }); @@ -60,7 +61,7 @@ export default async function Page({ searchParams }: { searchParams: any }) { } return ( - + (

{t("verify.title")}

{t("verify.description")}

@@ -92,14 +93,14 @@ export default async function Page({ searchParams }: { searchParams: any }) { /> ) : ( // check if auth methods are set - + />) )}
-
+
) ); } diff --git a/apps/login/src/components/register-form.tsx b/apps/login/src/components/register-form.tsx index 9788ab0e7d8..40dfe3c1ea4 100644 --- a/apps/login/src/components/register-form.tsx +++ b/apps/login/src/components/register-form.tsx @@ -50,6 +50,7 @@ export function RegisterForm({ loginSettings, }: Props) { const t = useTranslations("register"); + console.log(loginSettings); const { register, handleSubmit, formState } = useForm({ mode: "onBlur", 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/cookies.ts b/apps/login/src/lib/cookies.ts index c6afb507971..ebf667b51a3 100644 --- a/apps/login/src/lib/cookies.ts +++ b/apps/login/src/lib/cookies.ts @@ -1,7 +1,7 @@ "use server"; import { timestampDate, timestampFromMs } from "@zitadel/client"; -import { cookies } from "next/headers"; +import { cookies, type UnsafeUnwrappedCookies } from "next/headers"; import { LANGUAGE_COOKIE_NAME } from "./i18n"; // TODO: improve this to handle overflow @@ -21,7 +21,7 @@ export type Cookie = { type SessionCookie = Cookie & T; function setSessionHttpOnlyCookie(sessions: SessionCookie[]) { - const cookiesList = cookies(); + const cookiesList = (cookies() as unknown as UnsafeUnwrappedCookies); 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/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 a23664ec46e..797d93488c6 100644 --- a/apps/login/src/lib/server/loginname.ts +++ b/apps/login/src/lib/server/loginname.ts @@ -44,7 +44,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); @@ -81,7 +81,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); 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 24ba10faf82..63d9f4319ff 100644 --- a/apps/login/src/lib/server/password.ts +++ b/apps/login/src/lib/server/password.ts @@ -30,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, 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..ad0b48bc4a3 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 } 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,7 +37,7 @@ 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 @@ -66,43 +60,19 @@ export const orgService = createOrganizationServiceClient(transport); export const settingsService = createSettingsServiceClient(transport); 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, - ); + "use cache"; + cacheLife("hours"); + + return settingsService + .getBrandingSettings({ ctx: makeReqCtx(organization) }, {}) + .then((resp) => (resp.settings ? resp.settings : undefined)); } 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)); + "use cache"; + return await settingsService + .getLoginSettings({ ctx: makeReqCtx(orgId) }, {}) + .then((resp) => (resp.settings ? resp.settings : undefined)); } export async function listIDPLinks(userId: string) { @@ -132,51 +102,24 @@ export async function registerTOTP(userId: string) { } export async function getGeneralSettings() { + "use cache"; return settingsService .getGeneralSettings({}, {}) .then((resp) => resp.supportedLanguages); } 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, - ); + "use cache"; + return settingsService + .getLegalAndSupportSettings({ ctx: makeReqCtx(organization) }, {}) + .then((resp) => (resp.settings ? resp.settings : undefined)); } 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, - ); + "use cache"; + return settingsService + .getPasswordComplexitySettings({ ctx: makeReqCtx(organization) }) + .then((resp) => (resp.settings ? resp.settings : undefined)); } export async function createSessionFromChecks( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f326d64a999..320e21c122b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -64,16 +64,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.3(@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 +96,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.3 + version: 15.0.3(@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) + version: 3.20.0(next@15.0.3(@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.3(@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 +134,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 +142,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 @@ -412,79 +412,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 +495,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 +503,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 +566,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 +594,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] @@ -970,6 +973,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,62 +1113,56 @@ packages: resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} hasBin: true - '@next/env@14.2.14': - resolution: {integrity: sha512-/0hWQfiaD5//LvGNgc8PjvyqV50vGK0cADYzaoOOGN8fxzBn3iAiaq3S0tCRnFBldq0LVveLcxCTi41ZoYgAgg==} + '@next/env@15.0.3': + resolution: {integrity: sha512-t9Xy32pjNOvVn2AS+Utt6VmyrshbpfUMhIjFO60gI58deSo/KgLOp31XZ4O+kY/Is8WAGYwA5gR7kOb1eORDBA==} '@next/eslint-plugin-next@14.2.7': resolution: {integrity: sha512-+7xh142AdhZGjY9/L0iFo7mqRBMJHe+q+uOL+hto1Lfo9DeWCGcR6no4StlFbVSVcA6fQLKEX6y6qhMsSKbgNQ==} - '@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.3': + resolution: {integrity: sha512-s3Q/NOorCsLYdCKvQlWU+a+GeAd3C8Rb3L1YnetsgwXzhc3UTWrtQpB/3eCjFOdGUj5QmXfRak12uocd1ZiiQw==} 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.3': + resolution: {integrity: sha512-Zxl/TwyXVZPCFSf0u2BNj5sE0F2uR6iSKxWpq4Wlk/Sv9Ob6YCKByQTkV2y6BCic+fkabp9190hyrDdPA/dNrw==} 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.3': + resolution: {integrity: sha512-T5+gg2EwpsY3OoaLxUIofmMb7ohAUlcNZW0fPQ6YAutaWJaxt1Z1h+8zdl4FRIOr5ABAAhXtBcpkZNwUcKI2fw==} 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.3': + resolution: {integrity: sha512-WkAk6R60mwDjH4lG/JBpb2xHl2/0Vj0ZRu1TIzWuOYfQ9tt9NFsIinI1Epma77JVgy81F32X/AeD+B2cBu/YQA==} 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.3': + resolution: {integrity: sha512-gWL/Cta1aPVqIGgDb6nxkqy06DkwJ9gAnKORdHWX1QBbSZZB+biFYPFti8aKIQL7otCE1pjyPaXpFzGeG2OS2w==} 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.3': + resolution: {integrity: sha512-QQEMwFd8r7C0GxQS62Zcdy6GKx999I/rTO2ubdXEe+MlZk9ZiinsrjwoiBL5/57tfyjikgh6GOU2WRQVUej3UA==} 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.3': + resolution: {integrity: sha512-9TEp47AAd/ms9fPNgtgnT7F3M1Hf7koIYYWCMQ9neOwjbVWJsHZxrFbI3iEDJ8rf1TDGpmHbKxXf2IFpAvheIQ==} 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.3': + resolution: {integrity: sha512-VNAz+HN4OGgvZs6MOoVfnn41kBzT+M+tB+OK4cww6DNyWS6wKaDpaAm/qLeOUbnMh0oVx1+mg0uoYARF69dJyA==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -1082,89 +1184,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 +1336,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 +1444,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 +1470,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': @@ -1388,7 +1493,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 +1525,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 +1541,7 @@ 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/parser@7.18.0': resolution: {integrity: sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==} @@ -1580,7 +1682,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 +1895,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 +1998,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 +2217,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==} @@ -2517,12 +2623,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] @@ -2770,6 +2876,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 +3241,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: @@ -3269,21 +3378,24 @@ packages: react: '*' react-dom: '*' - next@14.2.14: - resolution: {integrity: sha512-Q1coZG17MW0Ly5x76shJ4dkC23woLAhhnDnw+DfTc7EpZSGuWrlsZ3bZaO8t6u1Yu8FVfhkqJE+U8GC7E0GLPQ==} - engines: {node: '>=18.17.0'} + next@15.0.3: + resolution: {integrity: sha512-ontCbCRKJUIoivAdGB34yCaOcPgYXr9AAkV/IwqFfWWTXEPUgLYkSkqBhIk9KK7gGmgjc64B+RdoeIDM13Irnw==} + 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-66855b96-20241106 + react-dom: ^18.2.0 || 19.0.0-rc-66855b96-20241106 sass: ^1.3.0 peerDependenciesMeta: '@opentelemetry/api': optional: true '@playwright/test': optional: true + babel-plugin-react-compiler: + optional: true sass: optional: true @@ -3698,7 +3810,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 +3860,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 +3875,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 +4002,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 +4028,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 +4065,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 +4208,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 @@ -4297,32 +4416,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 +4480,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'} @@ -5024,6 +5149,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 @@ -5197,18 +5327,18 @@ 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': {} @@ -5256,18 +5386,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 +5411,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,37 +5545,34 @@ snapshots: - encoding - supports-color - '@next/env@14.2.14': {} + '@next/env@15.0.3': {} '@next/eslint-plugin-next@14.2.7': dependencies: glob: 10.3.10 - '@next/swc-darwin-arm64@14.2.14': + '@next/swc-darwin-arm64@15.0.3': optional: true - '@next/swc-darwin-x64@14.2.14': + '@next/swc-darwin-x64@15.0.3': optional: true - '@next/swc-linux-arm64-gnu@14.2.14': + '@next/swc-linux-arm64-gnu@15.0.3': optional: true - '@next/swc-linux-arm64-musl@14.2.14': + '@next/swc-linux-arm64-musl@15.0.3': optional: true - '@next/swc-linux-x64-gnu@14.2.14': + '@next/swc-linux-x64-gnu@15.0.3': optional: true - '@next/swc-linux-x64-musl@14.2.14': + '@next/swc-linux-x64-musl@15.0.3': optional: true - '@next/swc-win32-arm64-msvc@14.2.14': + '@next/swc-win32-arm64-msvc@15.0.3': optional: true - '@next/swc-win32-ia32-msvc@14.2.14': - optional: true - - '@next/swc-win32-x64-msvc@14.2.14': + '@next/swc-win32-x64-msvc@15.0.3': optional: true '@nodelib/fs.scandir@2.1.5': @@ -5478,45 +5680,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 + 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 +5788,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 +5807,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 +5836,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 +5883,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 @@ -5741,12 +5943,12 @@ snapshots: '@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.3(@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.3(@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 +6287,6 @@ snapshots: caniuse-lite@1.0.30001654: {} - caniuse-lite@1.0.30001666: {} - caniuse-lite@1.0.30001680: {} case-anything@2.1.13: {} @@ -6185,8 +6385,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: @@ -6694,7 +6906,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 +6919,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 +6940,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 @@ -7329,6 +7541,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 @@ -7792,43 +8007,43 @@ snapshots: negotiator@0.6.3: {} - 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.20.0(next@15.0.3(@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) + next: 15.0.3(@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.20.0(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.3(@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.3(@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.3(@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.3 + '@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.3 + '@next/swc-darwin-x64': 15.0.3 + '@next/swc-linux-arm64-gnu': 15.0.3 + '@next/swc-linux-arm64-musl': 15.0.3 + '@next/swc-linux-x64-gnu': 15.0.3 + '@next/swc-linux-x64-musl': 15.0.3 + '@next/swc-win32-arm64-msvc': 15.0.3 + '@next/swc-win32-x64-msvc': 15.0.3 '@playwright/test': 1.48.2 sass: 1.80.7 + sharp: 0.33.5 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros @@ -8183,9 +8398,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 +8408,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 +8423,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 +8577,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 +8603,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 +8657,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 +8836,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 +8867,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: {} @@ -8878,6 +9120,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 +9165,15 @@ snapshots: dependencies: punycode: 2.3.1 - use-intl@3.20.0(react@18.3.1): + use-intl@3.20.0(react@19.0.0-rc-66855b96-20241106): dependencies: '@formatjs/fast-memoize': 2.2.0 intl-messageformat: 10.6.0 - react: 18.3.1 + 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: {} From fe615a220a2843916667a8a132da6e77683ba9fe Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Fri, 22 Nov 2024 11:27:37 +0100 Subject: [PATCH 20/40] lint --- apps/login/src/app/(login)/accounts/page.tsx | 8 +++----- .../src/app/(login)/authenticator/set/page.tsx | 8 +++----- .../app/(login)/idp/[provider]/failure/page.tsx | 10 ++++------ .../app/(login)/idp/[provider]/success/page.tsx | 14 ++++++-------- apps/login/src/app/(login)/idp/page.tsx | 8 +++----- apps/login/src/app/(login)/invite/page.tsx | 8 +++----- apps/login/src/app/(login)/invite/success/page.tsx | 8 +++----- apps/login/src/app/(login)/loginname/page.tsx | 8 +++----- apps/login/src/app/(login)/mfa/page.tsx | 8 +++----- apps/login/src/app/(login)/mfa/set/page.tsx | 8 +++----- apps/login/src/app/(login)/otp/[method]/page.tsx | 10 ++++------ .../src/app/(login)/otp/[method]/set/page.tsx | 10 ++++------ apps/login/src/app/(login)/passkey/page.tsx | 8 +++----- apps/login/src/app/(login)/passkey/set/page.tsx | 8 +++----- .../login/src/app/(login)/password/change/page.tsx | 8 +++----- apps/login/src/app/(login)/password/page.tsx | 8 +++----- apps/login/src/app/(login)/password/set/page.tsx | 8 +++----- apps/login/src/app/(login)/register/page.tsx | 8 +++----- .../src/app/(login)/register/password/page.tsx | 8 +++----- apps/login/src/app/(login)/u2f/page.tsx | 8 +++----- apps/login/src/app/(login)/u2f/set/page.tsx | 8 +++----- apps/login/src/app/(login)/verify/page.tsx | 8 ++++---- apps/login/src/lib/cookies.ts | 2 +- 23 files changed, 74 insertions(+), 116 deletions(-) diff --git a/apps/login/src/app/(login)/accounts/page.tsx b/apps/login/src/app/(login)/accounts/page.tsx index e072d7c2e7e..c3944a37688 100644 --- a/apps/login/src/app/(login)/accounts/page.tsx +++ b/apps/login/src/app/(login)/accounts/page.tsx @@ -20,11 +20,9 @@ async function loadSessions() { } } -export default async function Page( - props: { - searchParams: Promise>; - } -) { +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 e2f093adb95..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,9 @@ import { import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page( - props: { - searchParams: Promise>; - } -) { +export default async function Page(props: { + searchParams: Promise>; +}) { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "authenticator" }); 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 8729c1e9781..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,12 +12,10 @@ const PROVIDER_NAME_MAPPING: { [IdentityProviderType.AZURE_AD]: "Microsoft", }; -export default async function Page( - props: { - searchParams: Promise>; - params: Promise<{ 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 eb62bd35bc0..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,12 +29,10 @@ async function loginFailed(branding?: BrandingSettings) { ); } -export default async function Page( - props: { - searchParams: Promise>; - params: Promise<{ 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(); @@ -138,12 +136,12 @@ export default async function Page( if (idpLink) { return ( // TODO: possibily login user now - ( +

{t("linkingSuccess.title")}

{t("linkingSuccess.description")}
-
) +
); } } diff --git a/apps/login/src/app/(login)/idp/page.tsx b/apps/login/src/app/(login)/idp/page.tsx index cbf0a1ae788..d11bd8c20a0 100644 --- a/apps/login/src/app/(login)/idp/page.tsx +++ b/apps/login/src/app/(login)/idp/page.tsx @@ -12,11 +12,9 @@ function getIdentityProviders(orgId?: string) { }); } -export default async function Page( - props: { - searchParams: Promise>; - } -) { +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 c11131b50a6..18c60eb993a 100644 --- a/apps/login/src/app/(login)/invite/page.tsx +++ b/apps/login/src/app/(login)/invite/page.tsx @@ -9,11 +9,9 @@ import { } from "@/lib/zitadel"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page( - props: { - searchParams: Promise>; - } -) { +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 5955a8ecc30..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,9 @@ 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( - props: { - searchParams: Promise>; - } -) { +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)/loginname/page.tsx b/apps/login/src/app/(login)/loginname/page.tsx index 89b58f516e9..55a6682ce16 100644 --- a/apps/login/src/app/(login)/loginname/page.tsx +++ b/apps/login/src/app/(login)/loginname/page.tsx @@ -19,11 +19,9 @@ function getIdentityProviders(orgId?: string) { }); } -export default async function Page( - props: { - searchParams: Promise>; - } -) { +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 96c708ba636..071806db04a 100644 --- a/apps/login/src/app/(login)/mfa/page.tsx +++ b/apps/login/src/app/(login)/mfa/page.tsx @@ -12,11 +12,9 @@ import { } from "@/lib/zitadel"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page( - props: { - searchParams: Promise>; - } -) { +export default async function Page(props: { + searchParams: Promise>; +}) { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "mfa" }); diff --git a/apps/login/src/app/(login)/mfa/set/page.tsx b/apps/login/src/app/(login)/mfa/set/page.tsx index 4c1a7b7207a..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,9 @@ function isSessionValid(session: Partial): { return { valid, verifiedAt }; } -export default async function Page( - props: { - searchParams: Promise>; - } -) { +export default async function Page(props: { + searchParams: Promise>; +}) { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "mfa" }); diff --git a/apps/login/src/app/(login)/otp/[method]/page.tsx b/apps/login/src/app/(login)/otp/[method]/page.tsx index fbeca2fa37b..9c91b3edd26 100644 --- a/apps/login/src/app/(login)/otp/[method]/page.tsx +++ b/apps/login/src/app/(login)/otp/[method]/page.tsx @@ -6,12 +6,10 @@ import { loadMostRecentSession } from "@/lib/session"; import { getBrandingSettings, getLoginSettings } from "@/lib/zitadel"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page( - props: { - searchParams: Promise>; - params: Promise>; - } -) { +export default async function Page(props: { + searchParams: Promise>; + params: Promise>; +}) { const params = await props.params; const searchParams = await props.searchParams; const locale = getLocale(); 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 2a8b0ea790a..e64b4debe0f 100644 --- a/apps/login/src/app/(login)/otp/[method]/set/page.tsx +++ b/apps/login/src/app/(login)/otp/[method]/set/page.tsx @@ -17,12 +17,10 @@ import { getLocale, getTranslations } from "next-intl/server"; import Link from "next/link"; import { redirect } from "next/navigation"; -export default async function Page( - props: { - searchParams: Promise>; - params: Promise>; - } -) { +export default async function Page(props: { + searchParams: Promise>; + params: Promise>; +}) { const params = await props.params; const searchParams = await props.searchParams; const locale = getLocale(); diff --git a/apps/login/src/app/(login)/passkey/page.tsx b/apps/login/src/app/(login)/passkey/page.tsx index d6791676f72..0804f3ce2ea 100644 --- a/apps/login/src/app/(login)/passkey/page.tsx +++ b/apps/login/src/app/(login)/passkey/page.tsx @@ -11,11 +11,9 @@ import { } from "@/lib/zitadel"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page( - props: { - searchParams: Promise>; - } -) { +export default async function Page(props: { + searchParams: Promise>; +}) { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "passkey" }); diff --git a/apps/login/src/app/(login)/passkey/set/page.tsx b/apps/login/src/app/(login)/passkey/set/page.tsx index 4e4e4f24f0a..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,9 @@ import { loadMostRecentSession } from "@/lib/session"; import { getBrandingSettings } from "@/lib/zitadel"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page( - props: { - searchParams: Promise>; - } -) { +export default async function Page(props: { + searchParams: Promise>; +}) { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "passkey" }); diff --git a/apps/login/src/app/(login)/password/change/page.tsx b/apps/login/src/app/(login)/password/change/page.tsx index a697547f8f3..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,9 @@ import { } from "@/lib/zitadel"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page( - props: { - searchParams: Promise>; - } -) { +export default async function Page(props: { + searchParams: Promise>; +}) { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "password" }); diff --git a/apps/login/src/app/(login)/password/page.tsx b/apps/login/src/app/(login)/password/page.tsx index da7b91fbd78..a2c10c32380 100644 --- a/apps/login/src/app/(login)/password/page.tsx +++ b/apps/login/src/app/(login)/password/page.tsx @@ -12,11 +12,9 @@ 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( - props: { - searchParams: Promise>; - } -) { +export default async function Page(props: { + searchParams: Promise>; +}) { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "password" }); diff --git a/apps/login/src/app/(login)/password/set/page.tsx b/apps/login/src/app/(login)/password/set/page.tsx index c44f236c38e..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,9 @@ 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( - props: { - searchParams: Promise>; - } -) { +export default async function Page(props: { + searchParams: Promise>; +}) { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "password" }); diff --git a/apps/login/src/app/(login)/register/page.tsx b/apps/login/src/app/(login)/register/page.tsx index 497c1ac6e44..113e33be74b 100644 --- a/apps/login/src/app/(login)/register/page.tsx +++ b/apps/login/src/app/(login)/register/page.tsx @@ -10,11 +10,9 @@ import { 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>; - } -) { +export default async function Page(props: { + searchParams: Promise>; +}) { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "register" }); diff --git a/apps/login/src/app/(login)/register/password/page.tsx b/apps/login/src/app/(login)/register/password/page.tsx index c1d1a895eeb..48e454c3128 100644 --- a/apps/login/src/app/(login)/register/password/page.tsx +++ b/apps/login/src/app/(login)/register/password/page.tsx @@ -10,11 +10,9 @@ import { 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>; - } -) { +export default async function Page(props: { + searchParams: Promise>; +}) { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "register" }); diff --git a/apps/login/src/app/(login)/u2f/page.tsx b/apps/login/src/app/(login)/u2f/page.tsx index 4dce6fdeaaf..e4dd2bd8d20 100644 --- a/apps/login/src/app/(login)/u2f/page.tsx +++ b/apps/login/src/app/(login)/u2f/page.tsx @@ -7,11 +7,9 @@ import { loadMostRecentSession } from "@/lib/session"; import { getBrandingSettings, getSession } from "@/lib/zitadel"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page( - props: { - searchParams: Promise>; - } -) { +export default async function Page(props: { + searchParams: Promise>; +}) { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "u2f" }); diff --git a/apps/login/src/app/(login)/u2f/set/page.tsx b/apps/login/src/app/(login)/u2f/set/page.tsx index 862b7024d2e..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,9 @@ import { loadMostRecentSession } from "@/lib/session"; import { getBrandingSettings } from "@/lib/zitadel"; import { getLocale, getTranslations } from "next-intl/server"; -export default async function Page( - props: { - searchParams: Promise>; - } -) { +export default async function Page(props: { + searchParams: Promise>; +}) { const searchParams = await props.searchParams; const locale = getLocale(); const t = await getTranslations({ locale, namespace: "u2f" }); diff --git a/apps/login/src/app/(login)/verify/page.tsx b/apps/login/src/app/(login)/verify/page.tsx index c8e586f4091..fc11f459219 100644 --- a/apps/login/src/app/(login)/verify/page.tsx +++ b/apps/login/src/app/(login)/verify/page.tsx @@ -61,7 +61,7 @@ export default async function Page(props: { searchParams: Promise }) { } return ( - ( +

{t("verify.title")}

{t("verify.description")}

@@ -93,14 +93,14 @@ export default async function Page(props: { searchParams: Promise }) { /> ) : ( // check if auth methods are set - () + /> )}
-
) +
); } diff --git a/apps/login/src/lib/cookies.ts b/apps/login/src/lib/cookies.ts index ebf667b51a3..cd7457e8b17 100644 --- a/apps/login/src/lib/cookies.ts +++ b/apps/login/src/lib/cookies.ts @@ -21,7 +21,7 @@ export type Cookie = { type SessionCookie = Cookie & T; function setSessionHttpOnlyCookie(sessions: SessionCookie[]) { - const cookiesList = (cookies() as unknown as UnsafeUnwrappedCookies); + const cookiesList = cookies() as unknown as UnsafeUnwrappedCookies; return cookiesList.set({ name: "sessions", From ee993afbc9bde010b1f1d9f54e9d5a59244aafcd Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Fri, 22 Nov 2024 11:32:14 +0100 Subject: [PATCH 21/40] babel --- apps/login/.eslintrc.cjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/login/.eslintrc.cjs b/apps/login/.eslintrc.cjs index f5383dd47af..09e34c80669 100755 --- a/apps/login/.eslintrc.cjs +++ b/apps/login/.eslintrc.cjs @@ -1,5 +1,5 @@ module.exports = { - extends: ["next/core-web-vitals"], + extends: ["next/babel", "next/core-web-vitals"], ignorePatterns: ["external/**/*.ts"], rules: { "@next/next/no-html-link-for-pages": "off", From 2cb726776e3d5c48acb727501fb96e4e2879fe34 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Fri, 22 Nov 2024 11:35:02 +0100 Subject: [PATCH 22/40] canary version --- apps/login/next-env.d.ts | 2 +- apps/login/package.json | 2 +- pnpm-lock.yaml | 106 +++++++++++++++++++-------------------- 3 files changed, 55 insertions(+), 55 deletions(-) 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/package.json b/apps/login/package.json index e621cb567a8..e04e4306096 100644 --- a/apps/login/package.json +++ b/apps/login/package.json @@ -45,7 +45,7 @@ "copy-to-clipboard": "^3.3.3", "deepmerge": "^4.3.1", "moment": "^2.29.4", - "next": "15.0.3", + "next": "15.0.4-canary.23", "next-intl": "^3.20.0", "next-themes": "^0.2.1", "nice-grpc": "2.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 320e21c122b..e586abc576d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -73,7 +73,7 @@ importers: version: 0.5.7(tailwindcss@3.4.14) '@vercel/analytics': specifier: ^1.2.2 - version: 1.3.1(next@15.0.3(@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) + 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,14 +96,14 @@ importers: specifier: ^2.29.4 version: 2.30.1 next: - specifier: 15.0.3 - version: 15.0.3(@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) + 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@15.0.3(@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) + version: 3.20.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) next-themes: specifier: ^0.2.1 - version: 0.2.1(next@15.0.3(@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) + 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 @@ -1113,56 +1113,56 @@ packages: resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} hasBin: true - '@next/env@15.0.3': - resolution: {integrity: sha512-t9Xy32pjNOvVn2AS+Utt6VmyrshbpfUMhIjFO60gI58deSo/KgLOp31XZ4O+kY/Is8WAGYwA5gR7kOb1eORDBA==} + '@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/swc-darwin-arm64@15.0.3': - resolution: {integrity: sha512-s3Q/NOorCsLYdCKvQlWU+a+GeAd3C8Rb3L1YnetsgwXzhc3UTWrtQpB/3eCjFOdGUj5QmXfRak12uocd1ZiiQw==} + '@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@15.0.3': - resolution: {integrity: sha512-Zxl/TwyXVZPCFSf0u2BNj5sE0F2uR6iSKxWpq4Wlk/Sv9Ob6YCKByQTkV2y6BCic+fkabp9190hyrDdPA/dNrw==} + '@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@15.0.3': - resolution: {integrity: sha512-T5+gg2EwpsY3OoaLxUIofmMb7ohAUlcNZW0fPQ6YAutaWJaxt1Z1h+8zdl4FRIOr5ABAAhXtBcpkZNwUcKI2fw==} + '@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@15.0.3': - resolution: {integrity: sha512-WkAk6R60mwDjH4lG/JBpb2xHl2/0Vj0ZRu1TIzWuOYfQ9tt9NFsIinI1Epma77JVgy81F32X/AeD+B2cBu/YQA==} + '@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@15.0.3': - resolution: {integrity: sha512-gWL/Cta1aPVqIGgDb6nxkqy06DkwJ9gAnKORdHWX1QBbSZZB+biFYPFti8aKIQL7otCE1pjyPaXpFzGeG2OS2w==} + '@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@15.0.3': - resolution: {integrity: sha512-QQEMwFd8r7C0GxQS62Zcdy6GKx999I/rTO2ubdXEe+MlZk9ZiinsrjwoiBL5/57tfyjikgh6GOU2WRQVUej3UA==} + '@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@15.0.3': - resolution: {integrity: sha512-9TEp47AAd/ms9fPNgtgnT7F3M1Hf7koIYYWCMQ9neOwjbVWJsHZxrFbI3iEDJ8rf1TDGpmHbKxXf2IFpAvheIQ==} + '@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-x64-msvc@15.0.3': - resolution: {integrity: sha512-VNAz+HN4OGgvZs6MOoVfnn41kBzT+M+tB+OK4cww6DNyWS6wKaDpaAm/qLeOUbnMh0oVx1+mg0uoYARF69dJyA==} + '@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] @@ -3378,16 +3378,16 @@ packages: react: '*' react-dom: '*' - next@15.0.3: - resolution: {integrity: sha512-ontCbCRKJUIoivAdGB34yCaOcPgYXr9AAkV/IwqFfWWTXEPUgLYkSkqBhIk9KK7gGmgjc64B+RdoeIDM13Irnw==} + 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 babel-plugin-react-compiler: '*' - react: ^18.2.0 || 19.0.0-rc-66855b96-20241106 - react-dom: ^18.2.0 || 19.0.0-rc-66855b96-20241106 + 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': @@ -5545,34 +5545,34 @@ snapshots: - encoding - supports-color - '@next/env@15.0.3': {} + '@next/env@15.0.4-canary.23': {} '@next/eslint-plugin-next@14.2.7': dependencies: glob: 10.3.10 - '@next/swc-darwin-arm64@15.0.3': + '@next/swc-darwin-arm64@15.0.4-canary.23': optional: true - '@next/swc-darwin-x64@15.0.3': + '@next/swc-darwin-x64@15.0.4-canary.23': optional: true - '@next/swc-linux-arm64-gnu@15.0.3': + '@next/swc-linux-arm64-gnu@15.0.4-canary.23': optional: true - '@next/swc-linux-arm64-musl@15.0.3': + '@next/swc-linux-arm64-musl@15.0.4-canary.23': optional: true - '@next/swc-linux-x64-gnu@15.0.3': + '@next/swc-linux-x64-gnu@15.0.4-canary.23': optional: true - '@next/swc-linux-x64-musl@15.0.3': + '@next/swc-linux-x64-musl@15.0.4-canary.23': optional: true - '@next/swc-win32-arm64-msvc@15.0.3': + '@next/swc-win32-arm64-msvc@15.0.4-canary.23': optional: true - '@next/swc-win32-x64-msvc@15.0.3': + '@next/swc-win32-x64-msvc@15.0.4-canary.23': optional: true '@nodelib/fs.scandir@2.1.5': @@ -5713,7 +5713,7 @@ snapshots: '@react-stately/utils@3.10.4(react@19.0.0-rc-66855b96-20241106)': dependencies: - '@swc/helpers': 0.5.5 + '@swc/helpers': 0.5.13 react: 19.0.0-rc-66855b96-20241106 '@react-types/shared@3.25.0(react@19.0.0-rc-66855b96-20241106)': @@ -5943,11 +5943,11 @@ snapshots: '@ungap/structured-clone@1.2.0': {} - '@vercel/analytics@1.3.1(next@15.0.3(@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/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: 15.0.3(@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: 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': {} @@ -8007,23 +8007,23 @@ snapshots: negotiator@0.6.3: {} - next-intl@3.20.0(next@15.0.3(@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-intl@3.20.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): dependencies: '@formatjs/intl-localematcher': 0.5.4 negotiator: 0.6.3 - next: 15.0.3(@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: 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.20.0(react@19.0.0-rc-66855b96-20241106) - next-themes@0.2.1(next@15.0.3(@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): + 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: 15.0.3(@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: 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@15.0.3(@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@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': 15.0.3 + '@next/env': 15.0.4-canary.23 '@swc/counter': 0.1.3 '@swc/helpers': 0.5.13 busboy: 1.6.0 @@ -8033,14 +8033,14 @@ snapshots: 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': 15.0.3 - '@next/swc-darwin-x64': 15.0.3 - '@next/swc-linux-arm64-gnu': 15.0.3 - '@next/swc-linux-arm64-musl': 15.0.3 - '@next/swc-linux-x64-gnu': 15.0.3 - '@next/swc-linux-x64-musl': 15.0.3 - '@next/swc-win32-arm64-msvc': 15.0.3 - '@next/swc-win32-x64-msvc': 15.0.3 + '@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 From 58dbcdc3aa3835102bc35f85d3b7f30a68e785fb Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Fri, 22 Nov 2024 11:40:21 +0100 Subject: [PATCH 23/40] rm cache life in layout --- apps/login/src/app/(login)/layout.tsx | 2 -- apps/login/src/lib/zitadel.ts | 4 ---- apps/login/tailwind.config.mjs | 2 +- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/apps/login/src/app/(login)/layout.tsx b/apps/login/src/app/(login)/layout.tsx index 75820d79905..9105c45eb9a 100644 --- a/apps/login/src/app/(login)/layout.tsx +++ b/apps/login/src/app/(login)/layout.tsx @@ -14,8 +14,6 @@ const lato = Lato({ subsets: ["latin"], }); -export const revalidate = 60; // revalidate every minute - export default async function RootLayout({ children, }: { diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts index ad0b48bc4a3..7c5d63c4e5a 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -41,10 +41,6 @@ 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!, diff --git a/apps/login/tailwind.config.mjs b/apps/login/tailwind.config.mjs index 705398ceb64..0241b0c4490 100644 --- a/apps/login/tailwind.config.mjs +++ b/apps/login/tailwind.config.mjs @@ -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}"], From 7796f590fd03387e9b0e456326ecc3131a1c8c3f Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Fri, 22 Nov 2024 15:34:31 +0100 Subject: [PATCH 24/40] add suspense --- apps/login/package.json | 2 +- apps/login/src/app/(login)/layout.tsx | 40 +++---- .../src/components/language-provider.tsx | 18 +++ apps/login/src/lib/zitadel.ts | 8 ++ pnpm-lock.yaml | 104 ++++++++++-------- 5 files changed, 102 insertions(+), 70 deletions(-) create mode 100644 apps/login/src/components/language-provider.tsx diff --git a/apps/login/package.json b/apps/login/package.json index e04e4306096..3dc0946609a 100644 --- a/apps/login/package.json +++ b/apps/login/package.json @@ -46,7 +46,7 @@ "deepmerge": "^4.3.1", "moment": "^2.29.4", "next": "15.0.4-canary.23", - "next-intl": "^3.20.0", + "next-intl": "^3.25.1", "next-themes": "^0.2.1", "nice-grpc": "2.0.1", "qrcode.react": "^3.1.0", diff --git a/apps/login/src/app/(login)/layout.tsx b/apps/login/src/app/(login)/layout.tsx index 9105c45eb9a..1975b7c5e5a 100644 --- a/apps/login/src/app/(login)/layout.tsx +++ b/apps/login/src/app/(login)/layout.tsx @@ -1,13 +1,12 @@ import "@/styles/globals.scss"; +import { LanguageProvider } from "@/components/language-provider"; import { LanguageSwitcher } from "@/components/language-switcher"; 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"], @@ -19,33 +18,28 @@ export default async function RootLayout({ }: { children: ReactNode; }) { - const locale = await getLocale(); - const messages = await getMessages(); - return ( - + - -
-
- {children} -
- - + Loading...
}> + +
+
+ {children} +
+ + +
-
- - + + + diff --git a/apps/login/src/components/language-provider.tsx b/apps/login/src/components/language-provider.tsx new file mode 100644 index 00000000000..438eee9293a --- /dev/null +++ b/apps/login/src/components/language-provider.tsx @@ -0,0 +1,18 @@ +"use cache"; + +import { NextIntlClientProvider } from "next-intl"; +import { getLocale, getMessages } from "next-intl/server"; +import { unstable_cacheLife as cacheLife } from "next/cache"; +import { ReactNode } from "react"; + +export async function LanguageProvider({ children }: { children: ReactNode }) { + cacheLife("hours"); + + const locale = await getLocale(); + const messages = await getMessages(); + return ( + + {children} + + ); +} diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts index 7c5d63c4e5a..0092f4ad44d 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -66,6 +66,8 @@ export async function getBrandingSettings(organization?: string) { export async function getLoginSettings(orgId?: string) { "use cache"; + cacheLife("hours"); + return await settingsService .getLoginSettings({ ctx: makeReqCtx(orgId) }, {}) .then((resp) => (resp.settings ? resp.settings : undefined)); @@ -99,6 +101,8 @@ export async function registerTOTP(userId: string) { export async function getGeneralSettings() { "use cache"; + cacheLife("hours"); + return settingsService .getGeneralSettings({}, {}) .then((resp) => resp.supportedLanguages); @@ -106,6 +110,8 @@ export async function getGeneralSettings() { export async function getLegalAndSupportSettings(organization?: string) { "use cache"; + cacheLife("hours"); + return settingsService .getLegalAndSupportSettings({ ctx: makeReqCtx(organization) }, {}) .then((resp) => (resp.settings ? resp.settings : undefined)); @@ -113,6 +119,8 @@ export async function getLegalAndSupportSettings(organization?: string) { export async function getPasswordComplexitySettings(organization?: string) { "use cache"; + cacheLife("hours"); + return settingsService .getPasswordComplexitySettings({ ctx: makeReqCtx(organization) }) .then((resp) => (resp.settings ? resp.settings : undefined)); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e586abc576d..9a9d40dbf9f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -99,8 +99,8 @@ importers: 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@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) + 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@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) @@ -918,21 +918,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'} @@ -2865,8 +2868,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==} @@ -3361,15 +3364,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==} @@ -4393,6 +4396,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'} @@ -4531,10 +4537,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==} @@ -5343,31 +5349,35 @@ snapshots: '@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 @@ -7524,12 +7534,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: @@ -8005,15 +8015,15 @@ snapshots: natural-compare@1.4.0: {} - negotiator@0.6.3: {} + negotiator@1.0.0: {} - next-intl@3.20.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): + 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 + 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.20.0(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@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: @@ -9020,6 +9030,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) @@ -9165,10 +9177,10 @@ snapshots: dependencies: punycode: 2.3.1 - use-intl@3.20.0(react@19.0.0-rc-66855b96-20241106): + use-intl@3.25.1(react@19.0.0-rc-66855b96-20241106): dependencies: - '@formatjs/fast-memoize': 2.2.0 - intl-messageformat: 10.6.0 + '@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@19.0.0-rc-66855b96-20241106): From e964c7c0620ce51b310f7b8449e06a20d6cc633b Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Mon, 25 Nov 2024 09:19:58 +0100 Subject: [PATCH 25/40] rm caching of i18n --- apps/login/src/components/language-provider.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apps/login/src/components/language-provider.tsx b/apps/login/src/components/language-provider.tsx index 438eee9293a..524704b6006 100644 --- a/apps/login/src/components/language-provider.tsx +++ b/apps/login/src/components/language-provider.tsx @@ -1,13 +1,8 @@ -"use cache"; - import { NextIntlClientProvider } from "next-intl"; import { getLocale, getMessages } from "next-intl/server"; -import { unstable_cacheLife as cacheLife } from "next/cache"; import { ReactNode } from "react"; export async function LanguageProvider({ children }: { children: ReactNode }) { - cacheLife("hours"); - const locale = await getLocale(); const messages = await getMessages(); return ( From b48c25f7cdd986b0c05557dc6503e94007d918fd Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Mon, 25 Nov 2024 09:35:36 +0100 Subject: [PATCH 26/40] lint --- apps/login/.eslintrc.cjs | 2 +- packages/eslint-config-zitadel/index.js | 7 + packages/eslint-config-zitadel/package.json | 5 +- pnpm-lock.yaml | 219 +++++++++++++++++++- 4 files changed, 221 insertions(+), 12 deletions(-) diff --git a/apps/login/.eslintrc.cjs b/apps/login/.eslintrc.cjs index 09e34c80669..f5383dd47af 100755 --- a/apps/login/.eslintrc.cjs +++ b/apps/login/.eslintrc.cjs @@ -1,5 +1,5 @@ module.exports = { - extends: ["next/babel", "next/core-web-vitals"], + extends: ["next/core-web-vitals"], ignorePatterns: ["external/**/*.ts"], rules: { "@next/next/no-html-link-for-pages": "off", 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/pnpm-lock.yaml b/pnpm-lock.yaml index 9a9d40dbf9f..c1f59c0c030 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -222,12 +222,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 +339,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'} @@ -885,10 +895,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} @@ -1119,8 +1139,8 @@ packages: '@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@15.0.4-canary.23': resolution: {integrity: sha512-sX3MaDUiFiMT14KSx5mJz6B+IH9k7+buNniNrDP7iz4YG28jssm9e8uHbiWXsbn9jnkQUJu8PHoUOLhgjZgtsQ==} @@ -1170,6 +1190,9 @@ packages: 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'} @@ -1546,6 +1569,17 @@ packages: '@types/yauzl@2.10.3': 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==} engines: {node: ^18.18.0 || >=20.0.0} @@ -1560,10 +1594,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} @@ -1573,10 +1625,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==} @@ -2340,8 +2415,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' @@ -2430,14 +2505,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} @@ -2461,6 +2548,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'} @@ -4364,6 +4455,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==} @@ -4810,6 +4907,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 @@ -5306,8 +5411,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 @@ -5557,7 +5669,7 @@ snapshots: '@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 @@ -5585,6 +5697,10 @@ snapshots: '@next/swc-win32-x64-msvc@15.0.4-canary.23': 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: '@nodelib/fs.stat': 2.0.5 @@ -5911,6 +6027,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 @@ -5929,8 +6063,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 @@ -5946,11 +6099,43 @@ 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@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)': @@ -6874,10 +7059,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 @@ -7018,13 +7204,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) @@ -7084,6 +7279,8 @@ snapshots: dependencies: estraverse: 5.3.0 + estraverse@4.3.0: {} + estraverse@5.3.0: {} estree-walker@3.0.3: @@ -8998,6 +9195,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: {} From 76e9fea4e45d51769ce416c70e7259edbf96d910 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Mon, 25 Nov 2024 10:59:28 +0100 Subject: [PATCH 27/40] scss, module, nextjs, hydration fixes --- apps/login/next.config.mjs | 1 - apps/login/package.json | 6 ------ apps/login/src/components/input.tsx | 2 ++ apps/login/src/styles/globals.scss | 2 +- apps/login/tailwind.config.mjs | 2 +- package.json | 4 +++- .../zitadel-tailwind-config/tailwind.config.mjs | 14 +++++--------- pnpm-lock.yaml | 6 ++++-- 8 files changed, 16 insertions(+), 21 deletions(-) diff --git a/apps/login/next.config.mjs b/apps/login/next.config.mjs index e42b4ef7a19..a6e1d1a6d8d 100755 --- a/apps/login/next.config.mjs +++ b/apps/login/next.config.mjs @@ -36,7 +36,6 @@ const secureHeaders = [ const nextConfig = { reactStrictMode: true, // Recommended for the `pages` directory, default in `app`. - swcMinify: true, experimental: { dynamicIO: true, }, diff --git a/apps/login/package.json b/apps/login/package.json index 3dc0946609a..f8f3b89a3fb 100644 --- a/apps/login/package.json +++ b/apps/login/package.json @@ -88,11 +88,5 @@ "ts-proto": "^2.2.7", "typescript": "^5.6.3", "zitadel-tailwind-config": "workspace:*" - }, - "pnpm": { - "overrides": { - "@types/react": "npm:types-react@19.0.0-rc.1", - "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1" - } } } 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 && "*"} ({ "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 c1f59c0c030..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: @@ -1508,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: From 74eae3aed3eb532491d16c6c07003e814ce22e27 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Mon, 25 Nov 2024 13:59:30 +0100 Subject: [PATCH 28/40] only cache in prod --- apps/login/src/lib/zitadel.ts | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts index 0092f4ad44d..9b8d37979ca 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -56,8 +56,10 @@ export const orgService = createOrganizationServiceClient(transport); export const settingsService = createSettingsServiceClient(transport); export async function getBrandingSettings(organization?: string) { - "use cache"; - cacheLife("hours"); + if (process.env.DEBUG !== "true") { + ("use cache"); + cacheLife("hours"); + } return settingsService .getBrandingSettings({ ctx: makeReqCtx(organization) }, {}) @@ -65,8 +67,10 @@ export async function getBrandingSettings(organization?: string) { } export async function getLoginSettings(orgId?: string) { - "use cache"; - cacheLife("hours"); + if (process.env.DEBUG !== "true") { + ("use cache"); + cacheLife("hours"); + } return await settingsService .getLoginSettings({ ctx: makeReqCtx(orgId) }, {}) @@ -100,8 +104,10 @@ export async function registerTOTP(userId: string) { } export async function getGeneralSettings() { - "use cache"; - cacheLife("hours"); + if (process.env.DEBUG !== "true") { + ("use cache"); + cacheLife("hours"); + } return settingsService .getGeneralSettings({}, {}) @@ -109,8 +115,10 @@ export async function getGeneralSettings() { } export async function getLegalAndSupportSettings(organization?: string) { - "use cache"; - cacheLife("hours"); + if (process.env.DEBUG !== "true") { + ("use cache"); + cacheLife("hours"); + } return settingsService .getLegalAndSupportSettings({ ctx: makeReqCtx(organization) }, {}) @@ -118,8 +126,10 @@ export async function getLegalAndSupportSettings(organization?: string) { } export async function getPasswordComplexitySettings(organization?: string) { - "use cache"; - cacheLife("hours"); + if (process.env.DEBUG !== "true") { + ("use cache"); + cacheLife("hours"); + } return settingsService .getPasswordComplexitySettings({ ctx: makeReqCtx(organization) }) From 8d5882fdb0e62c11e2e51f383e3c254e56ef012d Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Tue, 26 Nov 2024 10:13:30 +0100 Subject: [PATCH 29/40] use cache under condition --- apps/login/src/lib/zitadel.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts index 9b8d37979ca..1a1907144aa 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -57,7 +57,8 @@ export const settingsService = createSettingsServiceClient(transport); export async function getBrandingSettings(organization?: string) { if (process.env.DEBUG !== "true") { - ("use cache"); + // @ts-ignore + `${"use cache"}`; cacheLife("hours"); } @@ -68,7 +69,8 @@ export async function getBrandingSettings(organization?: string) { export async function getLoginSettings(orgId?: string) { if (process.env.DEBUG !== "true") { - ("use cache"); + // @ts-ignore + `${"use cache"}`; cacheLife("hours"); } @@ -105,7 +107,8 @@ export async function registerTOTP(userId: string) { export async function getGeneralSettings() { if (process.env.DEBUG !== "true") { - ("use cache"); + // @ts-ignore + `${"use cache"}`; cacheLife("hours"); } @@ -116,7 +119,8 @@ export async function getGeneralSettings() { export async function getLegalAndSupportSettings(organization?: string) { if (process.env.DEBUG !== "true") { - ("use cache"); + // @ts-ignore + `${"use cache"}`; cacheLife("hours"); } @@ -127,7 +131,8 @@ export async function getLegalAndSupportSettings(organization?: string) { export async function getPasswordComplexitySettings(organization?: string) { if (process.env.DEBUG !== "true") { - ("use cache"); + // @ts-ignore + `${"use cache"}`; cacheLife("hours"); } From 0ab2a100a8c9e76e0ea2db7497f5f498c5eeab80 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Tue, 26 Nov 2024 10:22:59 +0100 Subject: [PATCH 30/40] wrap use cache --- apps/login/src/lib/zitadel.ts | 60 ++++++++++++++++------------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts index 1a1907144aa..a76f772f6bf 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -52,31 +52,33 @@ 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); -export async function getBrandingSettings(organization?: string) { - if (process.env.DEBUG !== "true") { - // @ts-ignore - `${"use cache"}`; - cacheLife("hours"); - } +async function cacheWrapper(callback: Promise) { + "use cache"; + cacheLife("hours"); - return settingsService + return callback; +} + +export async function getBrandingSettings(organization?: string) { + const useCache = process.env.DEBUG !== "true"; + + 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) { - if (process.env.DEBUG !== "true") { - // @ts-ignore - `${"use cache"}`; - cacheLife("hours"); - } + const useCache = process.env.DEBUG !== "true"; - return await settingsService + 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) { @@ -106,39 +108,33 @@ export async function registerTOTP(userId: string) { } export async function getGeneralSettings() { - if (process.env.DEBUG !== "true") { - // @ts-ignore - `${"use cache"}`; - cacheLife("hours"); - } + const useCache = process.env.DEBUG !== "true"; - return settingsService + const callback = settingsService .getGeneralSettings({}, {}) .then((resp) => resp.supportedLanguages); + + return useCache ? cacheWrapper(callback) : callback; } export async function getLegalAndSupportSettings(organization?: string) { - if (process.env.DEBUG !== "true") { - // @ts-ignore - `${"use cache"}`; - cacheLife("hours"); - } + const useCache = process.env.DEBUG !== "true"; - return settingsService + 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) { - if (process.env.DEBUG !== "true") { - // @ts-ignore - `${"use cache"}`; - cacheLife("hours"); - } + const useCache = process.env.DEBUG !== "true"; - return settingsService + const callback = settingsService .getPasswordComplexitySettings({ ctx: makeReqCtx(organization) }) .then((resp) => (resp.settings ? resp.settings : undefined)); + + return useCache ? cacheWrapper(callback) : callback; } export async function createSessionFromChecks( From e9f5d97352bd212504bf5c6a890c57f325e22eed Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Tue, 26 Nov 2024 10:29:32 +0100 Subject: [PATCH 31/40] cleanup wrapper, suspense --- apps/login/src/app/(login)/layout.tsx | 9 ++++++++- apps/login/src/lib/zitadel.ts | 14 +++----------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/apps/login/src/app/(login)/layout.tsx b/apps/login/src/app/(login)/layout.tsx index 1975b7c5e5a..c7c681f05fa 100644 --- a/apps/login/src/app/(login)/layout.tsx +++ b/apps/login/src/app/(login)/layout.tsx @@ -1,5 +1,6 @@ import "@/styles/globals.scss"; +import { Alert, AlertType } from "@/components/alert"; import { LanguageProvider } from "@/components/language-provider"; import { LanguageSwitcher } from "@/components/language-switcher"; import { Theme } from "@/components/theme"; @@ -23,7 +24,13 @@ export default async function RootLayout({ - Loading...
}> + + Loading... +
+ } + >
) { +const useCache = process.env.DEBUG !== "true"; + +async function cacheWrapper(callback: Promise) { "use cache"; cacheLife("hours"); @@ -62,8 +64,6 @@ async function cacheWrapper(callback: Promise) { } export async function getBrandingSettings(organization?: string) { - const useCache = process.env.DEBUG !== "true"; - const callback = settingsService .getBrandingSettings({ ctx: makeReqCtx(organization) }, {}) .then((resp) => (resp.settings ? resp.settings : undefined)); @@ -72,8 +72,6 @@ export async function getBrandingSettings(organization?: string) { } export async function getLoginSettings(orgId?: string) { - const useCache = process.env.DEBUG !== "true"; - const callback = settingsService .getLoginSettings({ ctx: makeReqCtx(orgId) }, {}) .then((resp) => (resp.settings ? resp.settings : undefined)); @@ -108,8 +106,6 @@ export async function registerTOTP(userId: string) { } export async function getGeneralSettings() { - const useCache = process.env.DEBUG !== "true"; - const callback = settingsService .getGeneralSettings({}, {}) .then((resp) => resp.supportedLanguages); @@ -118,8 +114,6 @@ export async function getGeneralSettings() { } export async function getLegalAndSupportSettings(organization?: string) { - const useCache = process.env.DEBUG !== "true"; - const callback = settingsService .getLegalAndSupportSettings({ ctx: makeReqCtx(organization) }, {}) .then((resp) => (resp.settings ? resp.settings : undefined)); @@ -128,8 +122,6 @@ export async function getLegalAndSupportSettings(organization?: string) { } export async function getPasswordComplexitySettings(organization?: string) { - const useCache = process.env.DEBUG !== "true"; - const callback = settingsService .getPasswordComplexitySettings({ ctx: makeReqCtx(organization) }) .then((resp) => (resp.settings ? resp.settings : undefined)); From fc371da2571d09f3cdeeb501a1e91971a9389fae Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Tue, 26 Nov 2024 11:06:22 +0100 Subject: [PATCH 32/40] redirect outside try catch, await cookie --- apps/login/src/components/session-item.tsx | 22 ++++++++++++--- apps/login/src/components/username-form.tsx | 6 ++++- apps/login/src/lib/cookies.ts | 6 ++--- apps/login/src/lib/server/loginname.ts | 30 +++++++++++---------- 4 files changed, 43 insertions(+), 21 deletions(-) diff --git a/apps/login/src/components/session-item.tsx b/apps/login/src/components/session-item.tsx index 5f9b7348273..1f864d49294 100644 --- a/apps/login/src/components/session-item.tsx +++ b/apps/login/src/components/session-item.tsx @@ -6,6 +6,7 @@ import { XCircleIcon } from "@heroicons/react/24/outline"; import { Timestamp, timestampDate } from "@zitadel/client"; import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb"; import moment from "moment"; +import { redirect } from "next/navigation"; import { useState } from "react"; import { Avatar } from "./avatar"; @@ -57,18 +58,33 @@ export function SessionItem({ return (
- - + ); diff --git a/apps/login/src/components/language-provider.tsx b/apps/login/src/components/language-provider.tsx index 524704b6006..21a53093bb1 100644 --- a/apps/login/src/components/language-provider.tsx +++ b/apps/login/src/components/language-provider.tsx @@ -1,10 +1,10 @@ import { NextIntlClientProvider } from "next-intl"; -import { getLocale, getMessages } from "next-intl/server"; +import { getMessages } from "next-intl/server"; import { ReactNode } from "react"; export async function LanguageProvider({ children }: { children: ReactNode }) { - const locale = await getLocale(); const messages = await getMessages(); + return ( {children} 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/styles/globals.scss b/apps/login/src/styles/globals.scss index 2a2e80f2c66..cfce853bc7a 100755 --- a/apps/login/src/styles/globals.scss +++ b/apps/login/src/styles/globals.scss @@ -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; + } +} From 7d29e541b4a2615213511d3b7bc496ed97302f45 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Tue, 26 Nov 2024 14:48:12 +0100 Subject: [PATCH 37/40] cleanup --- apps/login/src/app/(login)/register/page.tsx | 1 - apps/login/src/components/register-form.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/apps/login/src/app/(login)/register/page.tsx b/apps/login/src/app/(login)/register/page.tsx index 113e33be74b..2cd1c353466 100644 --- a/apps/login/src/app/(login)/register/page.tsx +++ b/apps/login/src/app/(login)/register/page.tsx @@ -41,7 +41,6 @@ export default async function Page(props: {

{t("disabled.title")}

{t("disabled.description")}

- {JSON.stringify(loginSettings)}
); diff --git a/apps/login/src/components/register-form.tsx b/apps/login/src/components/register-form.tsx index 6905aa12ba8..c336b836c4d 100644 --- a/apps/login/src/components/register-form.tsx +++ b/apps/login/src/components/register-form.tsx @@ -50,7 +50,6 @@ export function RegisterForm({ loginSettings, }: Props) { const t = useTranslations("register"); - console.log(loginSettings); const { register, handleSubmit, formState } = useForm({ mode: "onBlur", From 9573cdba04a710e72ae7d77b37ef8e2b32e64115 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Wed, 27 Nov 2024 11:02:34 +0100 Subject: [PATCH 38/40] feat: implement session lifetimes --- apps/login/src/lib/server/cookie.ts | 7 ++- apps/login/src/lib/server/otp.ts | 70 ++++++++++++++------------- apps/login/src/lib/server/password.ts | 19 +++++--- apps/login/src/lib/server/register.ts | 7 ++- apps/login/src/lib/server/session.ts | 36 ++++++++++---- apps/login/src/lib/zitadel.ts | 16 +++--- packages/zitadel-client/src/index.ts | 2 +- 7 files changed, 93 insertions(+), 64 deletions(-) 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/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/password.ts b/apps/login/src/lib/server/password.ts index 526c8c044aa..59afca50a5e 100644 --- a/apps/login/src/lib/server/password.ts +++ b/apps/login/src/lib/server/password.ts @@ -17,6 +17,7 @@ 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"; @@ -66,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, @@ -80,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, ); } @@ -95,6 +101,7 @@ export async function sendPassword(command: UpdateSessionCommand) { command.checks, undefined, command.authRequestId, + loginSettings?.passwordCheckLifetime, ); if (!session?.factors?.user?.id) { @@ -110,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" }; } @@ -241,9 +254,6 @@ export async function sendPassword(command: UpdateSessionCommand) { // return router.push(`/passkey/set?` + params); // } else if (command.authRequestId && session.id) { - const loginSettings = await getLoginSettings( - command.organization ?? session.factors?.user?.organizationId, - ); const nextUrl = await getNextUrl( { sessionId: session.id, @@ -257,9 +267,6 @@ export async function sendPassword(command: UpdateSessionCommand) { return { redirect: nextUrl }; } - const loginSettings = await getLoginSettings( - command.organization ?? session.factors?.user?.organizationId, - ); const url = await getNextUrl( { loginName: session.factors.user.loginName, diff --git a/apps/login/src/lib/server/register.ts b/apps/login/src/lib/server/register.ts index d045f4c8bff..01ddb0d8c8a 100644 --- a/apps/login/src/lib/server/register.ts +++ b/apps/login/src/lib/server/register.ts @@ -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) { @@ -72,10 +75,6 @@ export async function registerUser(command: RegisterUserCommand) { return { redirect: "/passkey/set?" + params }; } else { - const loginSettings = await getLoginSettings( - session.factors.user.organizationId, - ); - const url = await getNextUrl( command.authRequestId && session.id ? { diff --git a/apps/login/src/lib/server/session.ts b/apps/login/src/lib/server/session.ts index d204e4beef7..060be989a1f 100644 --- a/apps/login/src/lib/server/session.ts +++ b/apps/login/src/lib/server/session.ts @@ -7,8 +7,10 @@ import { 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"; @@ -38,20 +40,26 @@ export async function createNewSessionForIdp(options: CreateNewSessionCommand) { if (!userId || !idpIntent) { throw new Error("No userId or loginName provided"); } + + 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 loginSettings = await getLoginSettings( - session.factors.user.organizationId, - ); - const url = await getNextUrl( authRequestId && session.id ? { @@ -110,6 +118,7 @@ export type UpdateSessionCommand = { checks?: Checks; authRequestId?: string; challenges?: RequestChallenges; + lifetime?: Duration; }; export async function updateSession(options: UpdateSessionCommand) { @@ -121,17 +130,17 @@ 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); }); @@ -148,13 +157,20 @@ export async function updateSession(options: UpdateSessionCommand) { 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/zitadel.ts b/apps/login/src/lib/zitadel.ts index aeda88c3865..7a63fc55a7d 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -18,7 +18,7 @@ import { VerifyU2FRegistrationRequest, } from "@zitadel/proto/zitadel/user/v2/user_service_pb"; -import { create } 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"; @@ -132,15 +132,13 @@ export async function getPasswordComplexitySettings(organization?: string) { 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, }, {}, ); @@ -152,6 +150,7 @@ export async function createSessionForUserIdAndIdpIntent( idpIntentId?: string | undefined; idpIntentToken?: string | undefined; }, + lifetime?: Duration, ) { return sessionService.createSession({ checks: { @@ -163,10 +162,7 @@ export async function createSessionForUserIdAndIdpIntent( }, idpIntent, }, - // lifetime: { - // seconds: 300, - // nanos: 0, - // }, + lifetime, }); } @@ -175,6 +171,7 @@ export async function setSession( sessionToken: string, challenges: RequestChallenges | undefined, checks?: Checks, + lifetime?: Duration, ) { return sessionService.setSession( { @@ -183,6 +180,7 @@ export async function setSession( challenges, checks: checks ? checks : {}, metadata: {}, + lifetime, }, {}, ); 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"; From 520c1dc7c072dea1b66f8f4484641200e0e56ee2 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Wed, 27 Nov 2024 11:47:49 +0100 Subject: [PATCH 39/40] fix: host passkey login --- apps/login/readme.md | 1 - apps/login/src/lib/server/session.ts | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/login/readme.md b/apps/login/readme.md index a1999e60412..2aa09da2e49 100644 --- a/apps/login/readme.md +++ b/apps/login/readme.md @@ -393,4 +393,3 @@ In future, self service options to jump to are shown below, like: - loginSettings.disableLoginWithPhone - loginSettings.allowExternalIdp - this will be deprecated with the new login as it can be determined by the available IDPs - loginSettings.forceMfaLocalOnly -- loginSettings lifetimes - all besides Multifactor Init Check can be implemented. for the Init Check, an external storage or a timestamp has to be implemented which keeps track of the last verification diff --git a/apps/login/src/lib/server/session.ts b/apps/login/src/lib/server/session.ts index 060be989a1f..9726ce84e42 100644 --- a/apps/login/src/lib/server/session.ts +++ b/apps/login/src/lib/server/session.ts @@ -14,6 +14,7 @@ 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 { @@ -144,8 +145,7 @@ export async function updateSession(options: UpdateSessionCommand) { 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 && @@ -154,6 +154,7 @@ export async function updateSession(options: UpdateSessionCommand) { !challenges.webAuthN.domain ) { const [hostname, port] = host.split(":"); + challenges.webAuthN.domain = hostname; } From b87b6e254abb918737e9afbe40019824bea84651 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Wed, 27 Nov 2024 11:54:42 +0100 Subject: [PATCH 40/40] rm SESSION_LIFETIME_S --- apps/login/src/lib/zitadel.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/login/src/lib/zitadel.ts b/apps/login/src/lib/zitadel.ts index 7a63fc55a7d..be410551fb7 100644 --- a/apps/login/src/lib/zitadel.ts +++ b/apps/login/src/lib/zitadel.ts @@ -40,8 +40,6 @@ import { import { unstable_cacheLife as cacheLife } from "next/cache"; import { PROVIDER_MAPPING } from "./idp"; -const SESSION_LIFETIME_S = 3600; // TODO load from oidc settings - const transport = createServerTransport( process.env.ZITADEL_SERVICE_USER_TOKEN!, { baseUrl: process.env.ZITADEL_API_URL! },