From 271377d0c255eb8d4c9a1031aa219c11b8d473b2 Mon Sep 17 00:00:00 2001 From: ysoktsk Date: Sat, 18 Jul 2026 16:27:41 +0900 Subject: [PATCH 1/3] fix(next-auth): prevent stale session fetch from resurrecting session after signOut --- packages/next-auth/package.json | 9 +- packages/next-auth/src/lib/client.ts | 20 + packages/next-auth/src/react.tsx | 31 +- packages/next-auth/src/webauthn.ts | 6 +- packages/next-auth/test/react.test.tsx | 200 ++++++ packages/next-auth/vitest.config.ts | 11 + pnpm-lock.yaml | 848 ++++++++++++++++--------- 7 files changed, 831 insertions(+), 294 deletions(-) create mode 100644 packages/next-auth/test/react.test.tsx create mode 100644 packages/next-auth/vitest.config.ts diff --git a/packages/next-auth/package.json b/packages/next-auth/package.json index ae79ad3b4f..f41f859cf1 100644 --- a/packages/next-auth/package.json +++ b/packages/next-auth/package.json @@ -72,8 +72,8 @@ "build": "pnpm clean && pnpm providers && tsc", "clean": "rm -rf *.js *.d.ts* lib providers", "dev": "pnpm providers && tsc -w", - "test": "vitest run -c ../utils/vitest.config.ts", - "test:watch": "vitest -c ../utils/vitest.config.ts", + "test": "vitest run -c ./vitest.config.ts", + "test:watch": "vitest -c ./vitest.config.ts", "test:e2e": "playwright test", "providers": "node ../utils/scripts/providers" }, @@ -107,10 +107,13 @@ } }, "devDependencies": { + "@testing-library/react": "^14.3.1", "@types/react": "18.0.37", "dotenv": "^10.0.0", + "jsdom": "^24.1.3", "next": "15.5.18", "nodemailer": "^8.0.5", - "react": "^18.2.0" + "react": "^18.2.0", + "react-dom": "^18.2.0" } } diff --git a/packages/next-auth/src/lib/client.ts b/packages/next-auth/src/lib/client.ts index 22b0f0cbb2..36d5f3fddd 100644 --- a/packages/next-auth/src/lib/client.ts +++ b/packages/next-auth/src/lib/client.ts @@ -25,6 +25,13 @@ export interface AuthClientConfig { * trigger session updates from places like `signIn` or `signOut` */ _getSession: (...args: any[]) => any + /** + * Aborts in-flight session fetches when the auth state changes + * (e.g. `signIn`, `signOut`), so a stale response cannot overwrite + * the new session state or re-issue a rolling session cookie. + * @internal + */ + _abort?: AbortController | null } export interface UseSessionOptions { @@ -149,6 +156,7 @@ export async function fetchData( "Content-Type": "application/json", ...(req?.headers?.cookie ? { cookie: req.headers.cookie } : {}), }, + ...(req?.signal ? { signal: req.signal } : {}), } if (req?.body) { @@ -161,11 +169,23 @@ export async function fetchData( if (!res.ok) throw data return data } catch (error) { + if ((error as Error)?.name === "AbortError") throw error logger.error(new ClientFetchError((error as Error).message, error as any)) return null } } +/** + * Aborts any in-flight session fetch so its (now stale) result — and the + * rolling session cookie the server attaches to `GET /session` responses — + * is discarded instead of overwriting a newer auth state. + * @internal + */ +export function abortFetches(__NEXTAUTH: AuthClientConfig) { + __NEXTAUTH._abort?.abort() + __NEXTAUTH._abort = null +} + /** @internal */ export function apiBaseUrl(__NEXTAUTH: AuthClientConfig) { if (typeof window === "undefined") { diff --git a/packages/next-auth/src/react.tsx b/packages/next-auth/src/react.tsx index 4110e2bf81..08f6f30060 100644 --- a/packages/next-auth/src/react.tsx +++ b/packages/next-auth/src/react.tsx @@ -14,6 +14,7 @@ import * as React from "react" import { + abortFetches, apiBaseUrl, ClientSessionError, fetchData, @@ -176,6 +177,8 @@ export interface GetSessionParams { event?: "storage" | "timer" | "hidden" | string triggerEvent?: boolean broadcast?: boolean + /** Aborts the session fetch, discarding its result. */ + signal?: AbortSignal } export async function getSession(params?: GetSessionParams) { @@ -281,6 +284,9 @@ export async function signIn( }/${provider}` const csrfToken = await getCsrfToken() + // Abort in-flight session fetches before and after the sign-in request, so + // a stale response cannot overwrite the new session state afterwards. + abortFetches(__NEXTAUTH) const res = await fetch( `${signInUrl}?${new URLSearchParams(authorizationParams)}`, { @@ -298,6 +304,7 @@ export async function signIn( ) const data = await res.json() + abortFetches(__NEXTAUTH) if (redirect) { const url = data.url ?? redirectTo @@ -343,6 +350,10 @@ export async function signOut( } = options ?? {} const baseUrl = apiBaseUrl(__NEXTAUTH) + // Abort in-flight session fetches before and after the sign-out request, so + // a stale response cannot resurrect the session state — or, with the JWT + // strategy, re-issue a rolling session cookie that outlives the sign-out. + abortFetches(__NEXTAUTH) const csrfToken = await getCsrfToken() const res = await fetch(`${baseUrl}/signout`, { method: "post", @@ -353,6 +364,7 @@ export async function signOut( body: new URLSearchParams({ csrfToken, callbackUrl: redirectTo }), }) const data = await res.json() + abortFetches(__NEXTAUTH) broadcast().postMessage({ event: "session", data: { trigger: "signout" } }) @@ -413,10 +425,16 @@ export function SessionProvider(props: SessionProviderProps) { // or if there are events from other tabs/windows if (storageEvent || __NEXTAUTH._session === undefined) { __NEXTAUTH._lastSync = now() - __NEXTAUTH._session = await getSession({ + const controller = (__NEXTAUTH._abort ??= new AbortController()) + const session = await getSession({ broadcast: !storageEvent, + signal: controller.signal, }) - setSession(__NEXTAUTH._session) + // The auth state changed (e.g. `signOut`) while this fetch was in + // flight; its result is stale and must not overwrite the new state. + if (controller.signal.aborted) return + __NEXTAUTH._session = session + setSession(session) return } @@ -438,9 +456,13 @@ export function SessionProvider(props: SessionProviderProps) { // An event or session staleness occurred, update the client session. __NEXTAUTH._lastSync = now() - __NEXTAUTH._session = await getSession() - setSession(__NEXTAUTH._session) + const controller = (__NEXTAUTH._abort ??= new AbortController()) + const session = await getSession({ signal: controller.signal }) + if (controller.signal.aborted) return + __NEXTAUTH._session = session + setSession(session) } catch (error) { + if ((error as Error).name === "AbortError") return logger.error( new ClientSessionError((error as Error).message, error as any) ) @@ -452,6 +474,7 @@ export function SessionProvider(props: SessionProviderProps) { __NEXTAUTH._getSession() return () => { + abortFetches(__NEXTAUTH) __NEXTAUTH._lastSync = 0 __NEXTAUTH._session = undefined __NEXTAUTH._getSession = () => {} diff --git a/packages/next-auth/src/webauthn.ts b/packages/next-auth/src/webauthn.ts index e1ed98a96b..b5dee13bf8 100644 --- a/packages/next-auth/src/webauthn.ts +++ b/packages/next-auth/src/webauthn.ts @@ -1,4 +1,4 @@ -import { apiBaseUrl } from "./lib/client.js" +import { abortFetches, apiBaseUrl } from "./lib/client.js" import { startAuthentication, startRegistration } from "@simplewebauthn/browser" import { getCsrfToken, getProviders, __NEXTAUTH } from "./react.js" @@ -111,6 +111,9 @@ export async function signIn( webAuthnBody.action = webAuthnResponse.action const signInUrl = `${baseUrl}/callback/${provider}?${new URLSearchParams(authorizationParams)}` + // Abort in-flight session fetches before and after the sign-in request, so + // a stale response cannot overwrite the new session state afterwards. + abortFetches(__NEXTAUTH) const res = await fetch(signInUrl, { method: "post", headers: { @@ -126,6 +129,7 @@ export async function signIn( }) const data = await res.json() + abortFetches(__NEXTAUTH) if (redirect) { const url = data.url ?? callbackUrl diff --git a/packages/next-auth/test/react.test.tsx b/packages/next-auth/test/react.test.tsx new file mode 100644 index 0000000000..0df94b450e --- /dev/null +++ b/packages/next-auth/test/react.test.tsx @@ -0,0 +1,200 @@ +// @vitest-environment jsdom +import { describe, it, expect, vi, beforeEach, afterEach } from "vitest" +import * as React from "react" +import { act, cleanup, render, screen, waitFor } from "@testing-library/react" +import { + SessionProvider, + signIn, + signOut, + useSession, + __NEXTAUTH, +} from "../src/react" +import type { Session } from "@auth/core/types" + +const expires = new Date(Date.now() + 60 * 60 * 1000).toISOString() +const sessionA: Session = { user: { name: "a" }, expires } +const sessionB: Session = { user: { name: "b" }, expires } + +interface Deferred { + promise: Promise + resolve: (value: Session | null) => void +} + +function deferred(): Deferred { + let resolve!: Deferred["resolve"] + const promise = new Promise((r) => (resolve = r)) + return { promise, resolve } +} + +interface RecordedCall { + url: string + method: string + signal?: AbortSignal +} + +let calls: RecordedCall[] +/** One deferred per `GET /api/auth/session`, in request order. */ +let sessionRequests: Deferred[] +/** `signal.aborted` of each session request at the moment `POST /signout` was received. */ +let sessionSignalsAbortedAtSignOut: (boolean | undefined)[] | undefined + +function sessionCalls() { + return calls.filter((c) => c.url.includes("/session")) +} + +function jsonResponse(body: any) { + return { ok: true, status: 200, json: async () => body } +} + +function Probe() { + const { data, status } = useSession() + return React.createElement( + "span", + { "data-testid": "state" }, + `${status}:${data?.user?.name ?? "none"}` + ) +} + +function renderProvider() { + return render( + React.createElement(SessionProvider, null, React.createElement(Probe)) + ) +} + +function state() { + return screen.getByTestId("state").textContent +} + +/** Waits until the nth (1-indexed) session request has been issued. */ +async function nthSessionRequest(n: number) { + await waitFor(() => expect(sessionRequests.length).toBeGreaterThanOrEqual(n)) + return sessionRequests[n - 1] +} + +async function flush() { + await act(async () => { + await new Promise((r) => setTimeout(r, 10)) + }) +} + +beforeEach(() => { + calls = [] + sessionRequests = [] + sessionSignalsAbortedAtSignOut = undefined + + // `BroadcastChannel` would deliver `getSession` messages back to the + // provider and trigger extra, nondeterministic session fetches. + vi.stubGlobal("BroadcastChannel", undefined) + + vi.stubGlobal( + "fetch", + vi.fn(async (input: any, init: RequestInit = {}) => { + const url = typeof input === "string" ? input : input.url + const method = (init.method ?? "get").toString().toLowerCase() + calls.push({ url, method, signal: init.signal ?? undefined }) + + if (url.includes("/session")) { + const request = deferred() + sessionRequests.push(request) + return request.promise.then(jsonResponse) + } + if (url.includes("/csrf")) return jsonResponse({ csrfToken: "csrf" }) + if (url.includes("/signout")) { + sessionSignalsAbortedAtSignOut = sessionCalls().map( + (c) => c.signal?.aborted + ) + return jsonResponse({ url: "http://localhost:3000/" }) + } + if (url.includes("/callback/credentials")) { + return jsonResponse({ url: "http://localhost:3000/" }) + } + if (url.includes("/providers")) { + return jsonResponse({ + credentials: { + id: "credentials", + name: "Credentials", + type: "credentials", + signinUrl: "http://localhost:3000/api/auth/signin/credentials", + callbackUrl: "http://localhost:3000/", + redirectTo: "http://localhost:3000/", + }, + }) + } + throw new Error(`Unexpected fetch: ${method} ${url}`) + }) + ) +}) + +afterEach(() => { + cleanup() + vi.unstubAllGlobals() +}) + +describe("in-flight session fetch vs. auth state changes", () => { + it("signOut discards a stale in-flight session response", async () => { + renderProvider() + + // Mount fetch resolves with a session. + const first = await nthSessionRequest(1) + await act(async () => first.resolve(sessionA)) + await waitFor(() => expect(state()).toBe("authenticated:a")) + + // A refetch (window regains focus) starts and stays in flight. + await act(async () => { + document.dispatchEvent(new Event("visibilitychange")) + }) + const stale = await nthSessionRequest(2) + + // Sign out while the refetch is still pending. + let signOutDone: Promise + await act(async () => { + signOutDone = signOut({ redirect: false }) + // signOut refetches the (now empty) session before resolving. + const final = await nthSessionRequest(3) + final.resolve(null) + await signOutDone + }) + expect(state()).toBe("unauthenticated:none") + + // The stale response must be aborted before the signout request is even + // sent, so its rolling session cookie cannot outlive the sign-out. + expect(sessionCalls()[1].signal?.aborted).toBe(true) + expect(sessionSignalsAbortedAtSignOut?.[1]).toBe(true) + + // The stale response arrives last; it must not resurrect the session. + await act(async () => stale.resolve(sessionA)) + await flush() + expect(state()).toBe("unauthenticated:none") + expect(__NEXTAUTH._session).toBeNull() + }) + + it("signIn discards a stale in-flight session response", async () => { + renderProvider() + + const first = await nthSessionRequest(1) + await act(async () => first.resolve(sessionA)) + await waitFor(() => expect(state()).toBe("authenticated:a")) + + await act(async () => { + document.dispatchEvent(new Event("visibilitychange")) + }) + const stale = await nthSessionRequest(2) + + // Switch accounts while the refetch is still pending. + await act(async () => { + const signInDone = signIn("credentials", { redirect: false }) + const final = await nthSessionRequest(3) + final.resolve(sessionB) + await signInDone + }) + await waitFor(() => expect(state()).toBe("authenticated:b")) + + expect(sessionCalls()[1].signal?.aborted).toBe(true) + + // The stale response must not overwrite the new account's session. + await act(async () => stale.resolve(sessionA)) + await flush() + expect(state()).toBe("authenticated:b") + expect(__NEXTAUTH._session).toEqual(sessionB) + }) +}) diff --git a/packages/next-auth/vitest.config.ts b/packages/next-auth/vitest.config.ts new file mode 100644 index 0000000000..d8356e932b --- /dev/null +++ b/packages/next-auth/vitest.config.ts @@ -0,0 +1,11 @@ +/// + +import sharedConfig from "../utils/vitest.config" + +// The shared config enables `@preact/preset-vite`, which aliases +// react/react-dom to preact/compat and breaks `@testing-library/react`. +// The preset returns an array of plugins, so drop it and keep the rest. +export default { + ...sharedConfig, + plugins: (sharedConfig.plugins ?? []).filter((p) => !Array.isArray(p)), +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 769673e560..cd3fd40ca8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -152,7 +152,7 @@ importers: version: 6.19.1(eslint@9.9.1(jiti@1.21.7))(typescript@5.3.3) '@vitest/coverage-v8': specifier: 3.2.6 - version: 3.2.6(vitest@3.2.6(@types/debug@4.1.13)(@types/node@20.12.7)(@vitest/ui@3.2.6)(jiti@1.21.7)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3)) + version: 3.2.6(vitest@3.2.6(@types/debug@4.1.13)(@types/node@20.12.7)(@vitest/ui@3.2.6)(jiti@1.21.7)(jsdom@24.1.3)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3)) '@vitest/ui': specifier: ^3.2.6 version: 3.2.6(vitest@3.2.6) @@ -215,7 +215,7 @@ importers: version: 6.4.2(@types/node@20.12.7)(jiti@1.21.7)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3) vitest: specifier: 3.2.6 - version: 3.2.6(@types/debug@4.1.13)(@types/node@20.12.7)(@vitest/ui@3.2.6(vitest@3.2.6))(jiti@1.21.7)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3) + version: 3.2.6(@types/debug@4.1.13)(@types/node@20.12.7)(@vitest/ui@3.2.6(vitest@3.2.6))(jiti@1.21.7)(jsdom@24.1.3)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3) apps/dev/express: dependencies: @@ -359,7 +359,7 @@ importers: version: 3.8.3(@algolia/client-search@5.20.0)(@types/react@18.2.78)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.2) '@inkeep/widgets': specifier: ^0.2.289 - version: 0.2.289(@internationalized/date@3.5.2)(@types/react@18.2.78)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3) + version: 0.2.289(@internationalized/date@3.5.2)(@types/react@18.2.78)(jsdom@24.1.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3) '@next/third-parties': specifier: ^15.5.18 version: 15.5.19(next@15.5.18(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(react@18.3.1) @@ -380,7 +380,7 @@ importers: version: 4.24.0 better-auth: specifier: 1.6.16 - version: 1.6.16(@cloudflare/workers-types@4.20240117.0)(@prisma/client@6.0.0(prisma@6.0.0))(@sveltejs/kit@2.60.1(svelte@5.55.7(@typescript-eslint/types@8.3.0))(typescript@5.6.3)(vite@6.4.2(@types/node@20.12.7)(jiti@1.21.7)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3)))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20240117.0)(@prisma/client@6.0.0(prisma@6.0.0))(kysely@0.28.17)(mysql2@3.9.8)(pg@8.11.3)(prisma@6.0.0))(mongodb@6.9.0)(mysql2@3.9.8)(next@15.5.18(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(pg@8.11.3)(prisma@6.0.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(solid-js@1.9.4)(svelte@5.55.7(@typescript-eslint/types@8.3.0))(vitest@3.2.6(@types/debug@4.1.13)(@types/node@20.12.7)(@vitest/ui@3.2.6(vitest@3.2.6))(jiti@1.21.7)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3)) + version: 1.6.16(@cloudflare/workers-types@4.20240117.0)(@prisma/client@6.0.0(prisma@6.0.0))(@sveltejs/kit@2.60.1(svelte@5.55.7(@typescript-eslint/types@8.3.0))(typescript@5.6.3)(vite@6.4.2(@types/node@20.12.7)(jiti@1.21.7)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3)))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20240117.0)(@prisma/client@6.0.0(prisma@6.0.0))(kysely@0.28.17)(mysql2@3.9.8)(pg@8.11.3)(prisma@6.0.0))(mongodb@6.9.0)(mysql2@3.9.8)(next@15.5.18(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(pg@8.11.3)(prisma@6.0.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(solid-js@1.9.4)(svelte@5.55.7(@typescript-eslint/types@8.3.0))(vitest@3.2.6(@types/debug@4.1.13)(@types/node@20.12.7)(@vitest/ui@3.2.6(vitest@3.2.6))(jiti@1.21.7)(jsdom@24.1.3)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3)) classnames: specifier: ^2.5.1 version: 2.5.1 @@ -389,7 +389,7 @@ importers: version: 11.11.8(@emotion/is-prop-valid@0.8.8)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next: specifier: 15.5.18 - version: 15.5.18(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0) + version: 15.5.18(@opentelemetry/api@1.7.0)(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0) next-sitemap: specifier: ^4.2.3 version: 4.2.3(next@15.5.18(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0)) @@ -978,21 +978,30 @@ importers: specifier: ^9.0.2 version: 9.0.3(encoding@0.1.13) devDependencies: + '@testing-library/react': + specifier: ^14.3.1 + version: 14.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@types/react': specifier: 18.0.37 version: 18.0.37 dotenv: specifier: ^10.0.0 version: 10.0.0 + jsdom: + specifier: ^24.1.3 + version: 24.1.3 next: specifier: 15.5.18 - version: 15.5.18(@opentelemetry/api@1.7.0)(@playwright/test@1.55.1)(react-dom@19.0.0-rc-935180c7e0-20240524(react@18.3.1))(react@18.3.1)(sass@1.70.0) + version: 15.5.18(@opentelemetry/api@1.7.0)(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0) nodemailer: specifier: 8.0.5 version: 8.0.5 react: specifier: ^18.2.0 version: 18.3.1 + react-dom: + specifier: ^18.2.0 + version: 18.3.1(react@18.3.1) packages/utils: dependencies: @@ -1216,6 +1225,9 @@ packages: react: '>=18.0.0' react-dom: '>=18.0.0' + '@asamuzakjp/css-color@3.2.0': + resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} + '@aws-crypto/crc32@3.0.0': resolution: {integrity: sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==} @@ -1442,10 +1454,6 @@ packages: resolution: {integrity: sha512-ZQI11Uz1j0HJohb9JZLRD8z0moVcPks1AFW4Q/Gcl67+QvH4aKEJti7fjCcipEEZYb/qzLSO8U6IZgPYytsiJQ==} deprecated: A newer major version of this library is available. Please upgrade to the latest available version. - '@babel/code-frame@7.23.5': - resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} - engines: {node: '>=6.9.0'} - '@babel/code-frame@7.29.7': resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} @@ -1623,10 +1631,6 @@ packages: resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.22.20': - resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} - engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.29.7': resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} engines: {node: '>=6.9.0'} @@ -1647,10 +1651,6 @@ packages: resolution: {integrity: sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==} engines: {node: '>=6.9.0'} - '@babel/highlight@7.23.4': - resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} - engines: {node: '>=6.9.0'} - '@babel/parser@7.23.9': resolution: {integrity: sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==} engines: {node: '>=6.0.0'} @@ -2353,6 +2353,34 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} + '@csstools/color-helpers@5.1.0': + resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} + engines: {node: '>=18'} + + '@csstools/css-calc@2.1.4': + resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-color-parser@3.1.0': + resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-parser-algorithms@3.0.5': + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} + engines: {node: '>=18'} + '@csstools/selector-resolve-nested@1.1.0': resolution: {integrity: sha512-uWvSaeRcHyeNenKg8tp17EVDRkpflmdyvbE0DHo6D/GdBb6PDnCYYU6gRpXhtICMGMcahQmj2zGxwFM/WC8hCg==} engines: {node: ^14 || ^16 || >=18} @@ -4898,6 +4926,17 @@ packages: '@tediousjs/connection-string@0.3.0': resolution: {integrity: sha512-d/keJiNKfpHo+GmSB8QcsAwBx8h+V1UbdozA5TD+eSLXprNY53JAYub47J9evsSKWDdNG5uVj0FiMozLKuzowQ==} + '@testing-library/dom@9.3.4': + resolution: {integrity: sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==} + engines: {node: '>=14'} + + '@testing-library/react@14.3.1': + resolution: {integrity: sha512-H99XjUhWQw0lTgyMN05W3xQG1Nh4lq574D8keFf1dDoNTJgp66VbJozRaczoF+wsiaPJNt/TcnfpLGufGxSrZQ==} + engines: {node: '>=14'} + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + '@theguild/remark-mermaid@0.1.3': resolution: {integrity: sha512-2FjVlaaKXK7Zj7UJAgOVTyaahn/3/EAfqYhyXg0BfDBVUl+lXcoIWRaxzqfnDr2rv8ax6GsC5mNh6hAaT86PDw==} peerDependencies: @@ -4965,6 +5004,9 @@ packages: '@types/argparse@1.0.38': resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -6136,6 +6178,10 @@ packages: resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} engines: {node: '>= 14'} + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + agentkeepalive@4.5.0: resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} engines: {node: '>= 8.0.0'} @@ -6214,6 +6260,10 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} @@ -6270,6 +6320,9 @@ packages: argv-formatter@1.0.0: resolution: {integrity: sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==} + aria-query@5.1.3: + resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} + aria-query@5.3.1: resolution: {integrity: sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==} engines: {node: '>= 0.4'} @@ -6393,10 +6446,6 @@ packages: peerDependencies: postcss: 8.5.10 - available-typed-arrays@1.0.5: - resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} - engines: {node: '>= 0.4'} - available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -7184,6 +7233,10 @@ packages: resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + cssstyle@4.6.0: + resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==} + engines: {node: '>=18'} + csstype@3.1.2: resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} @@ -7359,6 +7412,10 @@ packages: resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} engines: {node: '>= 12'} + data-urls@5.0.0: + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} + dataloader@2.2.2: resolution: {integrity: sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==} @@ -7438,6 +7495,9 @@ packages: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + decode-named-character-reference@1.0.2: resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} @@ -7460,6 +7520,10 @@ packages: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} + deep-equal@2.2.3: + resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} + engines: {node: '>= 0.4'} + deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} @@ -7605,6 +7669,9 @@ packages: doctypes@1.1.0: resolution: {integrity: sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==} + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} @@ -7854,10 +7921,6 @@ packages: resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==} engines: {node: '>= 0.4'} - es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} - es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -7866,6 +7929,9 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} + es-get-iterator@1.1.3: + resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} + es-iterator-helpers@1.0.15: resolution: {integrity: sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==} @@ -8369,9 +8435,6 @@ packages: debug: optional: true - for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - for-each@0.3.5: resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} @@ -8646,9 +8709,6 @@ packages: resolution: {integrity: sha512-3bnD8RASQyaxOYTdWLgwpQco/aytTxFavoI/UN5QN5txDLp8QRrBHNtCUJ5+Ago+551GD92jG8jJduwvmaneUw==} engines: {node: '>=14'} - gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -8742,10 +8802,6 @@ packages: resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} engines: {node: '>= 0.4'} - has-tostringtag@1.0.0: - resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} - engines: {node: '>= 0.4'} - has-tostringtag@1.0.2: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} @@ -8843,6 +8899,10 @@ packages: html-dom-parser@3.1.7: resolution: {integrity: sha512-cDgNF4YgF6J3H+d9mcldGL19p0GzVdS3iGuDNzYWQpU47q3+IRM85X3Xo07E+nntF4ek4s78A9V24EwxlPTjig==} + html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + html-entities@2.3.3: resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==} @@ -8896,6 +8956,10 @@ packages: resolution: {integrity: sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==} engines: {node: '>= 14'} + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + http-shutdown@1.2.2: resolution: {integrity: sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} @@ -8908,6 +8972,10 @@ packages: resolution: {integrity: sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==} engines: {node: '>= 14'} + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -9028,6 +9096,10 @@ packages: resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} engines: {node: '>= 0.4'} + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + internmap@1.0.1: resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==} @@ -9070,6 +9142,10 @@ packages: is-alphanumerical@2.0.1: resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + is-arguments@1.2.0: + resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} + engines: {node: '>= 0.4'} + is-array-buffer@3.0.2: resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} @@ -9201,6 +9277,9 @@ packages: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-promise@2.2.2: resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} @@ -9216,10 +9295,6 @@ packages: is-reference@3.0.3: resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} - is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} - is-regex@1.2.1: resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} engines: {node: '>= 0.4'} @@ -9262,10 +9337,6 @@ packages: resolution: {integrity: sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==} engines: {node: '>=0.10.0'} - is-typed-array@1.1.12: - resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} - engines: {node: '>= 0.4'} - is-typed-array@1.1.15: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} @@ -9423,6 +9494,15 @@ packages: resolution: {integrity: sha512-MgtD0ZiCDk9B+eI73BextfRrVQl0oyzRG8B2BjORts6jbunj4ScKPcyXGTbB6eXL4y9TzxCm6hyeLq/2ASzNdw==} engines: {node: '>=12.0.0'} + jsdom@24.1.3: + resolution: {integrity: sha512-MyL55p3Ut3cXbeBEG7Hcv0mVM8pp8PBNWxRqchZnSfAiES1v1mRnMeFfaHWIPULpwsYfvO+ZmMZz5tGCnjzDUQ==} + engines: {node: '>=18'} + peerDependencies: + canvas: ^2.11.2 + peerDependenciesMeta: + canvas: + optional: true + jsesc@0.5.0: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} hasBin: true @@ -9852,6 +9932,9 @@ packages: resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} engines: {node: 14 || >=16.14} + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@4.0.2: resolution: {integrity: sha512-uQw9OqphAGiZhkuPlpFGmdTU2tEuhxTourM/19qGJrxBPHAr/f8BT1a0i/lOclESnGatdJG/UCkP9kZB/Lh1iw==} @@ -9879,6 +9962,10 @@ packages: lunr@2.3.9: resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + magic-string@0.27.0: resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} engines: {node: '>=12'} @@ -10761,6 +10848,9 @@ packages: nullthrows@1.1.1: resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} + nwsapi@2.2.24: + resolution: {integrity: sha512-7YRhZ3jS45LwmSCT4b2sVFHt/WuovaktDU07QrtOBY2PXskss5a9jfmR9jptyumwXST+rFjrmppMY1KT/yn35A==} + oauth4webapi@3.3.0: resolution: {integrity: sha512-ZlozhPlFfobzh3hB72gnBFLjXpugl/dljz1fJSRdqaV2r3D5dmi5lg2QWI0LmUYuazmE+b5exsloEv6toUtw9g==} @@ -10772,13 +10862,14 @@ packages: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} - object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} - object-inspect@1.13.4: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} + object-is@1.1.6: + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} + engines: {node: '>= 0.4'} + object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} @@ -10961,9 +11052,6 @@ packages: parse5@6.0.1: resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} - parse5@7.1.2: - resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} - parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} @@ -11465,6 +11553,10 @@ packages: engines: {node: '>=14'} hasBin: true + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + prism-react-renderer@2.1.0: resolution: {integrity: sha512-I5cvXHjA1PVGbGm1MsWCpvBCRrYyxEri0MC7/JbfIfYfcXAxHyO5PaUjs3A8H5GW6kJcLhTHxxMaOZZpRZD2iQ==} peerDependencies: @@ -11645,11 +11737,6 @@ packages: peerDependencies: react: 19.0.0-rc-4c58fce7-20240904 - react-dom@19.0.0-rc-935180c7e0-20240524: - resolution: {integrity: sha512-17SL+9qxiLUZnaBWr+mO3hpz5ncP5NbJp6jnbA6cFbsWNdV3p4s8iMVALIcfZF1zPIiWQeYrZQK/Z8GY3xjihg==} - peerDependencies: - react: 19.0.0-rc-935180c7e0-20240524 - react-error-boundary@4.0.13: resolution: {integrity: sha512-b6PwbdSv8XeOSYvjt8LpgpKrZ0yGdtZokYwkwV2wlcZbxgopHX/hgPl5VgpnoVOWd868n1hktM8Qm4b+02MiLQ==} peerDependencies: @@ -11675,6 +11762,9 @@ packages: react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + react-is@18.2.0: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} @@ -12030,6 +12120,12 @@ packages: resolution: {integrity: sha512-SFgmvjoIhp5S4iBEDW3XnbT+7PRuZ55oRuNjY+CDB1SGZkyCG9bqQ3/dhaZTctTBYMAvDxd2Uy9dStuaUfgJqQ==} engines: {node: '>= 6'} + rrweb-cssom@0.7.1: + resolution: {integrity: sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==} + + rrweb-cssom@0.8.0: + resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} + run-applescript@5.0.0: resolution: {integrity: sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==} engines: {node: '>=12'} @@ -12081,15 +12177,16 @@ packages: resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} engines: {node: '>=11.0.0'} + saxes@6.0.0: + 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-4c58fce7-20240904: resolution: {integrity: sha512-eU7RBVIRjFNzLI3oWxMGUYy872yVmN7gDcJiNiWo8Jh+lKfh/k003fgFTZNBCE7DgVCIc6k6/afMuMDqDcUwcw==} - scheduler@0.25.0-rc-935180c7e0-20240524: - resolution: {integrity: sha512-YfkorLQDTfVArSlFsSmTFMWW2CoUtNhkveeEzfbyqi5bShsEyQxAPLBGOUoBxaXEcQSJ2bXhkz3ZSTJCO/Th8A==} - scroll-into-view-if-needed@3.1.0: resolution: {integrity: sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==} @@ -12521,6 +12618,10 @@ packages: std-env@3.7.0: resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} + stoppable@1.1.0: resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} engines: {node: '>=4', npm: '>=6'} @@ -12765,6 +12866,9 @@ packages: resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} engines: {node: '>=0.10'} + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + system-architecture@0.1.0: resolution: {integrity: sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA==} engines: {node: '>=18'} @@ -12928,6 +13032,10 @@ packages: resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} engines: {node: '>=6'} + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} + engines: {node: '>=6'} + tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} @@ -12935,6 +13043,10 @@ packages: resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==} engines: {node: '>=14'} + tr46@5.1.1: + resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} + engines: {node: '>=18'} + traverse@0.6.8: resolution: {integrity: sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==} engines: {node: '>= 0.4'} @@ -13770,6 +13882,10 @@ packages: vuvuzela@1.0.3: resolution: {integrity: sha512-Tm7jR1xTzBbPW+6y1tknKiEhz04Wf/1iZkcTJjSFcpNko43+dFW6+OOeQe9taJIug3NdfUAjFKgUSyQrIKaDvQ==} + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + wait-on@6.0.1: resolution: {integrity: sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==} engines: {node: '>=10.0.0'} @@ -13810,10 +13926,23 @@ packages: resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} engines: {node: '>=0.8.0'} + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + whatwg-url@13.0.0: resolution: {integrity: sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==} engines: {node: '>=16'} + whatwg-url@14.2.0: + resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} + engines: {node: '>=18'} + whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} @@ -13834,10 +13963,6 @@ packages: resolution: {integrity: sha512-MOiaDbA5ZZgUjkeMWM5EkJp4loW5ZRoa5bc3/aeMox/PJelMhE6t7S/mLuiY43DBupyxH+S0U1bTui9kWUlmsw==} engines: {node: '>=8.15'} - which-typed-array@1.1.13: - resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} - engines: {node: '>= 0.4'} - which-typed-array@1.1.22: resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==} engines: {node: '>= 0.4'} @@ -13914,6 +14039,10 @@ packages: utf-8-validate: optional: true + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + xml2js@0.5.0: resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} engines: {node: '>=4.0.0'} @@ -13922,6 +14051,9 @@ packages: resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} engines: {node: '>=4.0'} + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + xmldom-sre@0.1.31: resolution: {integrity: sha512-f9s+fUkX04BxQf+7mMWAp5zk61pciie+fFLC9hX9UVvCeJQfNHRHXpeo5MPcR0EUf57PYLdt+ZO4f3Ipk2oZUw==} engines: {node: '>=0.1'} @@ -14406,6 +14538,14 @@ snapshots: transitivePeerDependencies: - '@internationalized/date' + '@asamuzakjp/css-color@3.2.0': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + lru-cache: 10.4.3 + '@aws-crypto/crc32@3.0.0': dependencies: '@aws-crypto/util': 3.0.0 @@ -15066,11 +15206,6 @@ snapshots: - debug - supports-color - '@babel/code-frame@7.23.5': - dependencies: - '@babel/highlight': 7.23.4 - chalk: 2.4.2 - '@babel/code-frame@7.29.7': dependencies: '@babel/helper-validator-identifier': 7.29.7 @@ -15084,7 +15219,7 @@ snapshots: '@babel/core@7.23.9': dependencies: '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.23.5 + '@babel/code-frame': 7.29.7 '@babel/generator': 7.23.6 '@babel/helper-compilation-targets': 7.23.6 '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.9) @@ -15254,7 +15389,7 @@ snapshots: '@babel/helper-module-imports': 7.22.15 '@babel/helper-simple-access': 7.22.5 '@babel/helper-split-export-declaration': 7.22.6 - '@babel/helper-validator-identifier': 7.22.20 + '@babel/helper-validator-identifier': 7.29.7 '@babel/helper-module-transforms@7.29.7(@babel/core@7.23.9)': dependencies: @@ -15332,8 +15467,6 @@ snapshots: '@babel/helper-string-parser@7.29.7': {} - '@babel/helper-validator-identifier@7.22.20': {} - '@babel/helper-validator-identifier@7.29.7': {} '@babel/helper-validator-option@7.23.5': {} @@ -15351,12 +15484,6 @@ snapshots: '@babel/template': 7.29.7 '@babel/types': 7.29.7 - '@babel/highlight@7.23.4': - dependencies: - '@babel/helper-validator-identifier': 7.29.7 - chalk: 2.4.2 - js-tokens: 4.0.0 - '@babel/parser@7.23.9': dependencies: '@babel/types': 7.29.7 @@ -16004,7 +16131,7 @@ snapshots: '@babel/template@7.23.9': dependencies: - '@babel/code-frame': 7.23.5 + '@babel/code-frame': 7.29.7 '@babel/parser': 7.23.9 '@babel/types': 7.23.9 @@ -16016,7 +16143,7 @@ snapshots: '@babel/traverse@7.23.9': dependencies: - '@babel/code-frame': 7.23.5 + '@babel/code-frame': 7.29.7 '@babel/generator': 7.23.6 '@babel/helper-environment-visitor': 7.22.20 '@babel/helper-function-name': 7.23.0 @@ -16044,7 +16171,7 @@ snapshots: '@babel/types@7.23.9': dependencies: '@babel/helper-string-parser': 7.23.4 - '@babel/helper-validator-identifier': 7.22.20 + '@babel/helper-validator-identifier': 7.29.7 to-fast-properties: 2.0.0 '@babel/types@7.29.7': @@ -16238,6 +16365,26 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 + '@csstools/color-helpers@5.1.0': {} + + '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/color-helpers': 5.1.0 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-tokenizer@3.0.4': {} + '@csstools/selector-resolve-nested@1.1.0(postcss-selector-parser@6.1.2)': dependencies: postcss-selector-parser: 6.1.2 @@ -17166,14 +17313,14 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@inkeep/components@0.0.24(@ark-ui/react@0.15.0(@internationalized/date@3.5.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@internationalized/date@3.5.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)': + '@inkeep/components@0.0.24(@ark-ui/react@0.15.0(@internationalized/date@3.5.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@internationalized/date@3.5.2)(jsdom@24.1.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)': dependencies: '@ark-ui/react': 0.15.0(@internationalized/date@3.5.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@inkeep/preset': 0.0.24(@internationalized/date@3.5.2)(typescript@5.6.3) - '@inkeep/preset-chakra': 0.0.24(@internationalized/date@3.5.2)(typescript@5.6.3) + '@inkeep/preset': 0.0.24(@internationalized/date@3.5.2)(jsdom@24.1.3)(typescript@5.6.3) + '@inkeep/preset-chakra': 0.0.24(@internationalized/date@3.5.2)(jsdom@24.1.3)(typescript@5.6.3) '@inkeep/shared': 0.0.25 '@inkeep/styled-system': 0.0.44 - '@pandacss/dev': 0.22.1(typescript@5.6.3) + '@pandacss/dev': 0.22.1(jsdom@24.1.3)(typescript@5.6.3) framer-motion: 10.18.0(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) @@ -17182,22 +17329,22 @@ snapshots: - jsdom - typescript - '@inkeep/preset-chakra@0.0.24(@internationalized/date@3.5.2)(typescript@5.6.3)': + '@inkeep/preset-chakra@0.0.24(@internationalized/date@3.5.2)(jsdom@24.1.3)(typescript@5.6.3)': dependencies: '@ark-ui/anatomy': 0.1.0(@internationalized/date@3.5.2) '@inkeep/shared': 0.0.25 - '@pandacss/dev': 0.22.1(typescript@5.6.3) + '@pandacss/dev': 0.22.1(jsdom@24.1.3)(typescript@5.6.3) transitivePeerDependencies: - '@internationalized/date' - jsdom - typescript - '@inkeep/preset@0.0.24(@internationalized/date@3.5.2)(typescript@5.6.3)': + '@inkeep/preset@0.0.24(@internationalized/date@3.5.2)(jsdom@24.1.3)(typescript@5.6.3)': dependencies: '@ark-ui/anatomy': 0.1.0(@internationalized/date@3.5.2) - '@inkeep/preset-chakra': 0.0.24(@internationalized/date@3.5.2)(typescript@5.6.3) + '@inkeep/preset-chakra': 0.0.24(@internationalized/date@3.5.2)(jsdom@24.1.3)(typescript@5.6.3) '@inkeep/shared': 0.0.25 - '@pandacss/dev': 0.22.1(typescript@5.6.3) + '@pandacss/dev': 0.22.1(jsdom@24.1.3)(typescript@5.6.3) colorjs.io: 0.4.5 transitivePeerDependencies: - '@internationalized/date' @@ -17210,14 +17357,14 @@ snapshots: '@inkeep/styled-system@0.0.46': {} - '@inkeep/widgets@0.2.289(@internationalized/date@3.5.2)(@types/react@18.2.78)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)': + '@inkeep/widgets@0.2.289(@internationalized/date@3.5.2)(@types/react@18.2.78)(jsdom@24.1.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)': dependencies: '@apollo/client': 3.9.5(@types/react@18.2.78)(graphql-ws@5.14.3(graphql@16.8.1))(graphql@16.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@ark-ui/react': 0.15.0(@internationalized/date@3.5.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@inkeep/color-mode': 0.0.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@inkeep/components': 0.0.24(@ark-ui/react@0.15.0(@internationalized/date@3.5.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@internationalized/date@3.5.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3) - '@inkeep/preset': 0.0.24(@internationalized/date@3.5.2)(typescript@5.6.3) - '@inkeep/preset-chakra': 0.0.24(@internationalized/date@3.5.2)(typescript@5.6.3) + '@inkeep/components': 0.0.24(@ark-ui/react@0.15.0(@internationalized/date@3.5.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@internationalized/date@3.5.2)(jsdom@24.1.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3) + '@inkeep/preset': 0.0.24(@internationalized/date@3.5.2)(jsdom@24.1.3)(typescript@5.6.3) + '@inkeep/preset-chakra': 0.0.24(@internationalized/date@3.5.2)(jsdom@24.1.3)(typescript@5.6.3) '@inkeep/shared': 0.0.25 '@inkeep/styled-system': 0.0.46 '@types/lodash.isequal': 4.5.8 @@ -17784,7 +17931,7 @@ snapshots: '@next/third-parties@15.5.19(next@15.5.18(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(react@18.3.1)': dependencies: - next: 15.5.18(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0) + next: 15.5.18(@opentelemetry/api@1.7.0)(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0) react: 18.3.1 third-party-capital: 1.0.20 @@ -17941,14 +18088,14 @@ snapshots: postcss-selector-parser: 6.1.2 ts-pattern: 5.0.5 - '@pandacss/dev@0.22.1(typescript@5.6.3)': + '@pandacss/dev@0.22.1(jsdom@24.1.3)(typescript@5.6.3)': dependencies: '@clack/prompts': 0.6.3 '@pandacss/config': 0.22.1 '@pandacss/error': 0.22.1 '@pandacss/logger': 0.22.1 - '@pandacss/node': 0.22.1(typescript@5.6.3) - '@pandacss/postcss': 0.22.1(typescript@5.6.3) + '@pandacss/node': 0.22.1(jsdom@24.1.3)(typescript@5.6.3) + '@pandacss/postcss': 0.22.1(jsdom@24.1.3)(typescript@5.6.3) '@pandacss/preset-panda': 0.22.1 '@pandacss/shared': 0.22.1 '@pandacss/token-dictionary': 0.22.1 @@ -17962,9 +18109,9 @@ snapshots: '@pandacss/error@0.22.1': {} - '@pandacss/extractor@0.22.1(typescript@5.6.3)': + '@pandacss/extractor@0.22.1(jsdom@24.1.3)(typescript@5.6.3)': dependencies: - ts-evaluator: 1.2.0(typescript@5.6.3) + ts-evaluator: 1.2.0(jsdom@24.1.3)(typescript@5.6.3) ts-morph: 19.0.0 transitivePeerDependencies: - jsdom @@ -17992,16 +18139,16 @@ snapshots: kleur: 4.1.5 lil-fp: 1.4.5 - '@pandacss/node@0.22.1(typescript@5.6.3)': + '@pandacss/node@0.22.1(jsdom@24.1.3)(typescript@5.6.3)': dependencies: '@pandacss/config': 0.22.1 '@pandacss/core': 0.22.1 '@pandacss/error': 0.22.1 - '@pandacss/extractor': 0.22.1(typescript@5.6.3) + '@pandacss/extractor': 0.22.1(jsdom@24.1.3)(typescript@5.6.3) '@pandacss/generator': 0.22.1 '@pandacss/is-valid-prop': 0.22.1 '@pandacss/logger': 0.22.1 - '@pandacss/parser': 0.22.1(typescript@5.6.3) + '@pandacss/parser': 0.22.1(jsdom@24.1.3)(typescript@5.6.3) '@pandacss/shared': 0.22.1 '@pandacss/token-dictionary': 0.22.1 '@pandacss/types': 0.22.1 @@ -18031,10 +18178,10 @@ snapshots: - jsdom - typescript - '@pandacss/parser@0.22.1(typescript@5.6.3)': + '@pandacss/parser@0.22.1(jsdom@24.1.3)(typescript@5.6.3)': dependencies: '@pandacss/config': 0.22.1 - '@pandacss/extractor': 0.22.1(typescript@5.6.3) + '@pandacss/extractor': 0.22.1(jsdom@24.1.3)(typescript@5.6.3) '@pandacss/is-valid-prop': 0.22.1 '@pandacss/logger': 0.22.1 '@pandacss/shared': 0.22.1 @@ -18048,9 +18195,9 @@ snapshots: - jsdom - typescript - '@pandacss/postcss@0.22.1(typescript@5.6.3)': + '@pandacss/postcss@0.22.1(jsdom@24.1.3)(typescript@5.6.3)': dependencies: - '@pandacss/node': 0.22.1(typescript@5.6.3) + '@pandacss/node': 0.22.1(jsdom@24.1.3)(typescript@5.6.3) postcss: 8.5.10 transitivePeerDependencies: - jsdom @@ -19570,6 +19717,25 @@ snapshots: '@tediousjs/connection-string@0.3.0': {} + '@testing-library/dom@9.3.4': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/runtime': 7.23.9 + '@types/aria-query': 5.0.4 + aria-query: 5.1.3 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + + '@testing-library/react@14.3.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@babel/runtime': 7.23.9 + '@testing-library/dom': 9.3.4 + '@types/react-dom': 18.2.18 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + '@theguild/remark-mermaid@0.1.3(react@18.3.1)': dependencies: mermaid: 11.15.0 @@ -19625,6 +19791,8 @@ snapshots: '@types/argparse@1.0.38': {} + '@types/aria-query@5.0.4': {} + '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.29.7 @@ -20414,7 +20582,7 @@ snapshots: dependencies: server-only: 0.0.1 optionalDependencies: - next: 15.5.18(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0) + next: 15.5.18(@opentelemetry/api@1.7.0)(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0) react: 18.3.1 '@vercel/kv@1.0.1': @@ -20439,7 +20607,7 @@ snapshots: - supports-color optional: true - '@vitest/coverage-v8@3.2.6(vitest@3.2.6(@types/debug@4.1.13)(@types/node@20.12.7)(@vitest/ui@3.2.6)(jiti@1.21.7)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3))': + '@vitest/coverage-v8@3.2.6(vitest@3.2.6(@types/debug@4.1.13)(@types/node@20.12.7)(@vitest/ui@3.2.6)(jiti@1.21.7)(jsdom@24.1.3)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 @@ -20454,7 +20622,7 @@ snapshots: std-env: 3.10.0 test-exclude: 7.0.2 tinyrainbow: 2.0.0 - vitest: 3.2.6(@types/debug@4.1.13)(@types/node@20.12.7)(@vitest/ui@3.2.6(vitest@3.2.6))(jiti@1.21.7)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3) + vitest: 3.2.6(@types/debug@4.1.13)(@types/node@20.12.7)(@vitest/ui@3.2.6(vitest@3.2.6))(jiti@1.21.7)(jsdom@24.1.3)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3) transitivePeerDependencies: - supports-color @@ -20503,7 +20671,7 @@ snapshots: sirv: 3.0.2 tinyglobby: 0.2.17 tinyrainbow: 2.0.0 - vitest: 3.2.6(@types/debug@4.1.13)(@types/node@20.12.7)(@vitest/ui@3.2.6(vitest@3.2.6))(jiti@1.21.7)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3) + vitest: 3.2.6(@types/debug@4.1.13)(@types/node@20.12.7)(@vitest/ui@3.2.6(vitest@3.2.6))(jiti@1.21.7)(jsdom@24.1.3)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3) '@vitest/utils@3.2.6': dependencies: @@ -21563,6 +21731,8 @@ snapshots: transitivePeerDependencies: - supports-color + agent-base@7.1.4: {} + agentkeepalive@4.5.0: dependencies: humanize-ms: 1.2.1 @@ -21659,6 +21829,8 @@ snapshots: dependencies: color-convert: 2.0.1 + ansi-styles@5.2.0: {} + ansi-styles@6.2.1: {} ansicolors@0.3.2: {} @@ -21705,11 +21877,15 @@ snapshots: argv-formatter@1.0.0: {} + aria-query@5.1.3: + dependencies: + deep-equal: 2.2.3 + aria-query@5.3.1: {} array-buffer-byte-length@1.0.0: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.9 is-array-buffer: 3.0.2 array-flatten@1.1.1: {} @@ -21730,7 +21906,7 @@ snapshots: array.prototype.flat@1.3.2: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.9 define-properties: 1.2.1 es-abstract: 1.22.3 es-shim-unscopables: 1.0.2 @@ -21753,10 +21929,10 @@ snapshots: arraybuffer.prototype.slice@1.0.2: dependencies: array-buffer-byte-length: 1.0.0 - call-bind: 1.0.7 + call-bind: 1.0.9 define-properties: 1.2.1 es-abstract: 1.22.3 - get-intrinsic: 1.2.4 + get-intrinsic: 1.3.0 is-array-buffer: 3.0.2 is-shared-array-buffer: 1.0.2 @@ -21809,7 +21985,7 @@ snapshots: asynciterator.prototype@1.0.0: dependencies: - has-symbols: 1.0.3 + has-symbols: 1.1.0 asynckit@0.4.0: {} @@ -21847,8 +22023,6 @@ snapshots: postcss: 8.5.10 postcss-value-parser: 4.2.0 - available-typed-arrays@1.0.5: {} - available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.1.0 @@ -21974,7 +22148,7 @@ snapshots: dependencies: safe-buffer: 5.1.2 - better-auth@1.6.16(@cloudflare/workers-types@4.20240117.0)(@prisma/client@6.0.0(prisma@6.0.0))(@sveltejs/kit@2.60.1(svelte@5.55.7(@typescript-eslint/types@8.3.0))(typescript@5.6.3)(vite@6.4.2(@types/node@20.12.7)(jiti@1.21.7)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3)))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20240117.0)(@prisma/client@6.0.0(prisma@6.0.0))(kysely@0.28.17)(mysql2@3.9.8)(pg@8.11.3)(prisma@6.0.0))(mongodb@6.9.0)(mysql2@3.9.8)(next@15.5.18(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(pg@8.11.3)(prisma@6.0.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(solid-js@1.9.4)(svelte@5.55.7(@typescript-eslint/types@8.3.0))(vitest@3.2.6(@types/debug@4.1.13)(@types/node@20.12.7)(@vitest/ui@3.2.6(vitest@3.2.6))(jiti@1.21.7)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3)): + better-auth@1.6.16(@cloudflare/workers-types@4.20240117.0)(@prisma/client@6.0.0(prisma@6.0.0))(@sveltejs/kit@2.60.1(svelte@5.55.7(@typescript-eslint/types@8.3.0))(typescript@5.6.3)(vite@6.4.2(@types/node@20.12.7)(jiti@1.21.7)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3)))(drizzle-kit@0.31.10)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20240117.0)(@prisma/client@6.0.0(prisma@6.0.0))(kysely@0.28.17)(mysql2@3.9.8)(pg@8.11.3)(prisma@6.0.0))(mongodb@6.9.0)(mysql2@3.9.8)(next@15.5.18(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(pg@8.11.3)(prisma@6.0.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(solid-js@1.9.4)(svelte@5.55.7(@typescript-eslint/types@8.3.0))(vitest@3.2.6(@types/debug@4.1.13)(@types/node@20.12.7)(@vitest/ui@3.2.6(vitest@3.2.6))(jiti@1.21.7)(jsdom@24.1.3)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3)): dependencies: '@better-auth/core': 1.6.16(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.2.2)(@cloudflare/workers-types@4.20240117.0)(better-call@1.3.6(zod@3.22.4))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0) '@better-auth/drizzle-adapter': 1.6.16(@better-auth/core@1.6.16(@better-auth/utils@0.4.1)(@better-fetch/fetch@1.2.2)(@cloudflare/workers-types@4.20240117.0)(better-call@1.3.6(zod@3.22.4))(jose@6.2.3)(kysely@0.28.17)(nanostores@1.3.0))(@better-auth/utils@0.4.1)(drizzle-orm@0.45.2(@cloudflare/workers-types@4.20240117.0)(@prisma/client@6.0.0(prisma@6.0.0))(kysely@0.28.17)(mysql2@3.9.8)(pg@8.11.3)(prisma@6.0.0)) @@ -22000,14 +22174,14 @@ snapshots: drizzle-orm: 0.45.2(@cloudflare/workers-types@4.20240117.0)(@prisma/client@6.0.0(prisma@6.0.0))(kysely@0.28.17)(mysql2@3.9.8)(pg@8.11.3)(prisma@6.0.0) mongodb: 6.9.0(@aws-sdk/credential-providers@3.499.0)(gcp-metadata@5.3.0)(socks@2.8.9) mysql2: 3.9.8 - next: 15.5.18(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0) + next: 15.5.18(@opentelemetry/api@1.7.0)(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0) pg: 8.11.3 prisma: 6.0.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) solid-js: 1.9.4 svelte: 5.55.7(@typescript-eslint/types@8.3.0) - vitest: 3.2.6(@types/debug@4.1.13)(@types/node@20.12.7)(@vitest/ui@3.2.6(vitest@3.2.6))(jiti@1.21.7)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3) + vitest: 3.2.6(@types/debug@4.1.13)(@types/node@20.12.7)(@vitest/ui@3.2.6(vitest@3.2.6))(jiti@1.21.7)(jsdom@24.1.3)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3) transitivePeerDependencies: - '@cloudflare/workers-types' - '@opentelemetry/api' @@ -22220,10 +22394,10 @@ snapshots: call-bind@1.0.7: dependencies: - es-define-property: 1.0.0 + es-define-property: 1.0.1 es-errors: 1.3.0 function-bind: 1.1.2 - get-intrinsic: 1.2.4 + get-intrinsic: 1.3.0 set-function-length: 1.2.2 call-bind@1.0.9: @@ -22735,6 +22909,11 @@ snapshots: dependencies: css-tree: 2.2.1 + cssstyle@4.6.0: + dependencies: + '@asamuzakjp/css-color': 3.2.0 + rrweb-cssom: 0.8.0 + csstype@3.1.2: {} csstype@3.1.3: {} @@ -22931,6 +23110,11 @@ snapshots: data-uri-to-buffer@4.0.1: {} + data-urls@5.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + dataloader@2.2.2: {} dataloader@2.2.3: {} @@ -22976,6 +23160,8 @@ snapshots: decamelize@1.2.0: {} + decimal.js@10.6.0: {} + decode-named-character-reference@1.0.2: dependencies: character-entities: 2.0.2 @@ -22990,6 +23176,27 @@ snapshots: deep-eql@5.0.2: {} + deep-equal@2.2.3: + dependencies: + array-buffer-byte-length: 1.0.0 + call-bind: 1.0.9 + es-get-iterator: 1.1.3 + get-intrinsic: 1.3.0 + is-arguments: 1.2.0 + is-array-buffer: 3.0.2 + is-date-object: 1.0.5 + is-regex: 1.2.1 + is-shared-array-buffer: 1.0.2 + isarray: 2.0.5 + object-is: 1.1.6 + object-keys: 1.1.1 + object.assign: 4.1.5 + regexp.prototype.flags: 1.5.1 + side-channel: 1.1.1 + which-boxed-primitive: 1.0.2 + which-collection: 1.0.1 + which-typed-array: 1.1.22 + deep-extend@0.6.0: {} deep-is@0.1.4: {} @@ -23019,9 +23226,9 @@ snapshots: define-data-property@1.1.4: dependencies: - es-define-property: 1.0.0 + es-define-property: 1.0.1 es-errors: 1.3.0 - gopd: 1.0.1 + gopd: 1.2.0 define-lazy-prop@2.0.0: {} @@ -23103,6 +23310,8 @@ snapshots: doctypes@1.1.0: {} + dom-accessibility-api@0.5.16: {} + dom-serializer@2.0.0: dependencies: domelementtype: 2.3.0 @@ -23276,29 +23485,29 @@ snapshots: dependencies: array-buffer-byte-length: 1.0.0 arraybuffer.prototype.slice: 1.0.2 - available-typed-arrays: 1.0.5 - call-bind: 1.0.7 - es-set-tostringtag: 2.0.2 + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + es-set-tostringtag: 2.1.0 es-to-primitive: 1.2.1 function.prototype.name: 1.1.6 - get-intrinsic: 1.2.4 + get-intrinsic: 1.3.0 get-symbol-description: 1.0.0 globalthis: 1.0.3 - gopd: 1.0.1 + gopd: 1.2.0 has-property-descriptors: 1.0.2 has-proto: 1.0.1 - has-symbols: 1.0.3 + has-symbols: 1.1.0 hasown: 2.0.4 internal-slot: 1.0.6 is-array-buffer: 3.0.2 is-callable: 1.2.7 is-negative-zero: 2.0.2 - is-regex: 1.1.4 + is-regex: 1.2.1 is-shared-array-buffer: 1.0.2 is-string: 1.0.7 - is-typed-array: 1.1.12 + is-typed-array: 1.1.15 is-weakref: 1.0.2 - object-inspect: 1.13.1 + object-inspect: 1.13.4 object-keys: 1.1.1 object.assign: 4.1.5 regexp.prototype.flags: 1.5.1 @@ -23312,16 +23521,24 @@ snapshots: typed-array-byte-offset: 1.0.0 typed-array-length: 1.0.4 unbox-primitive: 1.0.2 - which-typed-array: 1.1.13 - - es-define-property@1.0.0: - dependencies: - get-intrinsic: 1.2.4 + which-typed-array: 1.1.22 es-define-property@1.0.1: {} es-errors@1.3.0: {} + es-get-iterator@1.1.3: + dependencies: + call-bind: 1.0.9 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + is-arguments: 1.2.0 + is-map: 2.0.2 + is-set: 2.0.2 + is-string: 1.0.7 + isarray: 2.0.5 + stop-iteration-iterator: 1.1.0 + es-iterator-helpers@1.0.15: dependencies: asynciterator.prototype: 1.0.0 @@ -23349,8 +23566,8 @@ snapshots: es-set-tostringtag@2.0.2: dependencies: - get-intrinsic: 1.2.4 - has-tostringtag: 1.0.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 hasown: 2.0.4 es-set-tostringtag@2.1.0: @@ -24116,10 +24333,6 @@ snapshots: optionalDependencies: debug: 4.3.7 - for-each@0.3.3: - dependencies: - is-callable: 1.2.7 - for-each@0.3.5: dependencies: is-callable: 1.2.7 @@ -24237,7 +24450,7 @@ snapshots: function.prototype.name@1.1.6: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.9 define-properties: 1.2.1 es-abstract: 1.22.3 functions-have-names: 1.2.3 @@ -24325,7 +24538,7 @@ snapshots: es-errors: 1.3.0 function-bind: 1.1.2 has-proto: 1.0.1 - has-symbols: 1.0.3 + has-symbols: 1.1.0 hasown: 2.0.4 get-intrinsic@1.3.0: @@ -24360,8 +24573,8 @@ snapshots: get-symbol-description@1.0.0: dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 + call-bind: 1.0.9 + get-intrinsic: 1.3.0 get-tsconfig@4.8.0: dependencies: @@ -24473,10 +24686,6 @@ snapshots: - supports-color optional: true - gopd@1.0.1: - dependencies: - get-intrinsic: 1.2.4 - gopd@1.2.0: {} graceful-fs@4.2.11: {} @@ -24566,7 +24775,7 @@ snapshots: has-property-descriptors@1.0.2: dependencies: - es-define-property: 1.0.0 + es-define-property: 1.0.1 has-proto@1.0.1: {} @@ -24574,10 +24783,6 @@ snapshots: has-symbols@1.1.0: {} - has-tostringtag@1.0.0: - dependencies: - has-symbols: 1.0.3 - has-tostringtag@1.0.2: dependencies: has-symbols: 1.1.0 @@ -24607,7 +24812,7 @@ snapshots: '@types/hast': 3.0.4 devlop: 1.1.0 hast-util-from-parse5: 8.0.1 - parse5: 7.1.2 + parse5: 7.3.0 vfile: 6.0.3 vfile-message: 4.0.2 @@ -24667,7 +24872,7 @@ snapshots: hast-util-to-parse5: 8.0.0 html-void-elements: 3.0.0 mdast-util-to-hast: 13.2.1 - parse5: 7.1.2 + parse5: 7.3.0 unist-util-position: 5.0.0 unist-util-visit: 5.0.0 vfile: 6.0.3 @@ -24805,6 +25010,10 @@ snapshots: domhandler: 5.0.3 htmlparser2: 8.0.2 + html-encoding-sniffer@4.0.0: + dependencies: + whatwg-encoding: 3.1.1 + html-entities@2.3.3: {} html-entities@2.5.2: @@ -24887,6 +25096,13 @@ snapshots: transitivePeerDependencies: - supports-color + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.0 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + http-shutdown@1.2.2: {} https-proxy-agent@5.0.1: @@ -24903,6 +25119,13 @@ snapshots: transitivePeerDependencies: - supports-color + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + human-signals@2.1.0: {} human-signals@3.0.1: {} @@ -25002,9 +25225,15 @@ snapshots: internal-slot@1.0.6: dependencies: - get-intrinsic: 1.2.4 + get-intrinsic: 1.3.0 hasown: 2.0.4 - side-channel: 1.0.6 + side-channel: 1.1.1 + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.4 + side-channel: 1.1.1 internmap@1.0.1: {} @@ -25052,17 +25281,22 @@ snapshots: is-alphabetical: 2.0.1 is-decimal: 2.0.1 + is-arguments@1.2.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + is-array-buffer@3.0.2: dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - is-typed-array: 1.1.12 + call-bind: 1.0.9 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 is-arrayish@0.2.1: {} is-async-function@2.0.0: dependencies: - has-tostringtag: 1.0.0 + has-tostringtag: 1.0.2 is-bigint@1.0.4: dependencies: @@ -25074,8 +25308,8 @@ snapshots: is-boolean-object@1.1.2: dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.0 + call-bind: 1.0.9 + has-tostringtag: 1.0.2 is-buffer@2.0.5: {} @@ -25091,7 +25325,7 @@ snapshots: is-date-object@1.0.5: dependencies: - has-tostringtag: 1.0.0 + has-tostringtag: 1.0.2 is-decimal@2.0.1: {} @@ -25110,13 +25344,13 @@ snapshots: is-finalizationregistry@1.0.2: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.9 is-fullwidth-code-point@3.0.0: {} is-generator-function@1.0.10: dependencies: - has-tostringtag: 1.0.0 + has-tostringtag: 1.0.2 is-glob@4.0.3: dependencies: @@ -25146,7 +25380,7 @@ snapshots: is-number-object@1.0.7: dependencies: - has-tostringtag: 1.0.0 + has-tostringtag: 1.0.2 is-number@7.0.0: {} @@ -25158,6 +25392,8 @@ snapshots: is-plain-obj@4.1.0: {} + is-potential-custom-element-name@1.0.1: {} + is-promise@2.2.2: {} is-property@1.0.2: {} @@ -25175,11 +25411,6 @@ snapshots: dependencies: '@types/estree': 1.0.8 - is-regex@1.1.4: - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.0 - is-regex@1.2.1: dependencies: call-bound: 1.0.4 @@ -25197,7 +25428,7 @@ snapshots: is-shared-array-buffer@1.0.2: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.9 is-stream@1.1.0: {} @@ -25207,20 +25438,16 @@ snapshots: is-string@1.0.7: dependencies: - has-tostringtag: 1.0.0 + has-tostringtag: 1.0.2 is-symbol@1.0.4: dependencies: - has-symbols: 1.0.3 + has-symbols: 1.1.0 is-text-path@1.0.1: dependencies: text-extensions: 1.9.0 - is-typed-array@1.1.12: - dependencies: - which-typed-array: 1.1.13 - is-typed-array@1.1.15: dependencies: which-typed-array: 1.1.22 @@ -25239,12 +25466,12 @@ snapshots: is-weakref@1.0.2: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.9 is-weakset@2.0.2: dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 + call-bind: 1.0.9 + get-intrinsic: 1.3.0 is-what@4.1.16: {} @@ -25304,8 +25531,8 @@ snapshots: iterator.prototype@1.1.2: dependencies: define-properties: 1.2.1 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 reflect.getprototypeof: 1.0.4 set-function-name: 2.0.1 @@ -25370,6 +25597,34 @@ snapshots: jsdoc-type-pratt-parser@3.1.0: {} + jsdom@24.1.3: + dependencies: + cssstyle: 4.6.0 + data-urls: 5.0.0 + decimal.js: 10.6.0 + form-data: 4.0.4 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.24 + parse5: 7.3.0 + rrweb-cssom: 0.7.1 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 4.1.4 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + ws: 8.20.1 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + jsesc@0.5.0: {} jsesc@2.5.2: {} @@ -25394,7 +25649,7 @@ snapshots: json-stable-stringify@1.1.1: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.9 isarray: 2.0.5 jsonify: 0.0.1 object-keys: 1.1.1 @@ -25827,6 +26082,8 @@ snapshots: lru-cache@10.2.0: {} + lru-cache@10.4.3: {} + lru-cache@4.0.2: dependencies: pseudomap: 1.0.2 @@ -25853,6 +26110,8 @@ snapshots: lunr@2.3.9: {} + lz-string@1.5.0: {} + magic-string@0.27.0: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -26950,47 +27209,21 @@ snapshots: '@next/env': 13.5.6 fast-glob: 3.3.2 minimist: 1.2.8 - next: 15.5.18(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0) + next: 15.5.18(@opentelemetry/api@1.7.0)(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0) next-themes@0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - next@15.5.18(@opentelemetry/api@1.7.0)(@playwright/test@1.55.1)(react-dom@19.0.0-rc-4c58fce7-20240904(react@19.0.0-rc-4c58fce7-20240904))(react@19.0.0-rc-4c58fce7-20240904)(sass@1.70.0): - dependencies: - '@next/env': 15.5.18 - '@swc/helpers': 0.5.15 - caniuse-lite: 1.0.30001668 - postcss: 8.5.10 - react: 19.0.0-rc-4c58fce7-20240904 - react-dom: 19.0.0-rc-4c58fce7-20240904(react@19.0.0-rc-4c58fce7-20240904) - styled-jsx: 5.1.6(react@19.0.0-rc-4c58fce7-20240904) - optionalDependencies: - '@next/swc-darwin-arm64': 15.5.18 - '@next/swc-darwin-x64': 15.5.18 - '@next/swc-linux-arm64-gnu': 15.5.18 - '@next/swc-linux-arm64-musl': 15.5.18 - '@next/swc-linux-x64-gnu': 15.5.18 - '@next/swc-linux-x64-musl': 15.5.18 - '@next/swc-win32-arm64-msvc': 15.5.18 - '@next/swc-win32-x64-msvc': 15.5.18 - '@opentelemetry/api': 1.7.0 - '@playwright/test': 1.55.1 - sass: 1.70.0 - sharp: 0.34.5 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - - next@15.5.18(@opentelemetry/api@1.7.0)(@playwright/test@1.55.1)(react-dom@19.0.0-rc-935180c7e0-20240524(react@18.3.1))(react@18.3.1)(sass@1.70.0): + next@15.5.18(@opentelemetry/api@1.7.0)(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0): dependencies: '@next/env': 15.5.18 '@swc/helpers': 0.5.15 caniuse-lite: 1.0.30001668 postcss: 8.5.10 react: 18.3.1 - react-dom: 19.0.0-rc-935180c7e0-20240524(react@18.3.1) + react-dom: 18.3.1(react@18.3.1) styled-jsx: 5.1.6(react@18.3.1) optionalDependencies: '@next/swc-darwin-arm64': 15.5.18 @@ -27009,15 +27242,15 @@ snapshots: - '@babel/core' - babel-plugin-macros - next@15.5.18(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0): + next@15.5.18(@opentelemetry/api@1.7.0)(@playwright/test@1.55.1)(react-dom@19.0.0-rc-4c58fce7-20240904(react@19.0.0-rc-4c58fce7-20240904))(react@19.0.0-rc-4c58fce7-20240904)(sass@1.70.0): dependencies: '@next/env': 15.5.18 '@swc/helpers': 0.5.15 caniuse-lite: 1.0.30001668 postcss: 8.5.10 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - styled-jsx: 5.1.6(react@18.3.1) + react: 19.0.0-rc-4c58fce7-20240904 + react-dom: 19.0.0-rc-4c58fce7-20240904(react@19.0.0-rc-4c58fce7-20240904) + styled-jsx: 5.1.6(react@19.0.0-rc-4c58fce7-20240904) optionalDependencies: '@next/swc-darwin-arm64': 15.5.18 '@next/swc-darwin-x64': 15.5.18 @@ -27027,6 +27260,7 @@ snapshots: '@next/swc-linux-x64-musl': 15.5.18 '@next/swc-win32-arm64-msvc': 15.5.18 '@next/swc-win32-x64-msvc': 15.5.18 + '@opentelemetry/api': 1.7.0 '@playwright/test': 1.55.1 sass: 1.70.0 sharp: 0.34.5 @@ -27040,7 +27274,7 @@ snapshots: clsx: 2.1.0 escape-string-regexp: 5.0.0 flexsearch: 0.7.43 - next: 15.5.18(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0) + next: 15.5.18(@opentelemetry/api@1.7.0)(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0) next-themes: 0.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) nextra: 3.0.15(@types/react@18.2.78)(next@15.5.18(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3) react: 18.3.1 @@ -27068,7 +27302,7 @@ snapshots: hast-util-to-estree: 3.1.0 katex: 0.16.21 negotiator: 0.6.3 - next: 15.5.18(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0) + next: 15.5.18(@opentelemetry/api@1.7.0)(@playwright/test@1.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.70.0) p-limit: 6.1.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -27260,16 +27494,21 @@ snapshots: nullthrows@1.1.1: {} + nwsapi@2.2.24: {} + oauth4webapi@3.3.0: {} object-assign@4.1.1: {} object-hash@3.0.0: {} - object-inspect@1.13.1: {} - object-inspect@1.13.4: {} + object-is@1.1.6: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + object-keys@1.1.1: {} object-path@0.11.8: {} @@ -27282,9 +27521,9 @@ snapshots: object.assign@4.1.5: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.9 define-properties: 1.2.1 - has-symbols: 1.0.3 + has-symbols: 1.1.0 object-keys: 1.1.1 object.entries@1.1.7: @@ -27472,7 +27711,7 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.23.5 + '@babel/code-frame': 7.29.7 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -27494,10 +27733,6 @@ snapshots: parse5@6.0.1: {} - parse5@7.1.2: - dependencies: - entities: 4.5.0 - parse5@7.3.0: dependencies: entities: 6.0.1 @@ -28007,6 +28242,12 @@ snapshots: prettier@3.3.3: {} + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + prism-react-renderer@2.1.0(react@18.3.1): dependencies: '@types/prismjs': 1.26.3 @@ -28217,11 +28458,6 @@ snapshots: react: 19.0.0-rc-4c58fce7-20240904 scheduler: 0.25.0-rc-4c58fce7-20240904 - react-dom@19.0.0-rc-935180c7e0-20240524(react@18.3.1): - dependencies: - react: 18.3.1 - scheduler: 0.25.0-rc-935180c7e0-20240524 - react-error-boundary@4.0.13(react@18.3.1): dependencies: '@babel/runtime': 7.23.9 @@ -28242,6 +28478,8 @@ snapshots: react-is@16.13.1: {} + react-is@17.0.2: {} + react-is@18.2.0: {} react-markdown@8.0.7(@types/react@18.2.78)(react@18.3.1): @@ -28424,10 +28662,10 @@ snapshots: reflect.getprototypeof@1.0.4: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.9 define-properties: 1.2.1 es-abstract: 1.22.3 - get-intrinsic: 1.2.4 + get-intrinsic: 1.3.0 globalthis: 1.0.3 which-builtin-type: 1.1.3 @@ -28447,7 +28685,7 @@ snapshots: regexp.prototype.flags@1.5.1: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.9 define-properties: 1.2.1 set-function-name: 2.0.1 @@ -28773,6 +29011,10 @@ snapshots: route-sort@1.0.0: {} + rrweb-cssom@0.7.1: {} + + rrweb-cssom@0.8.0: {} + run-applescript@5.0.0: dependencies: execa: 5.1.1 @@ -28797,9 +29039,9 @@ snapshots: safe-array-concat@1.1.0: dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 + call-bind: 1.0.9 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 isarray: 2.0.5 safe-buffer@5.1.2: {} @@ -28808,9 +29050,9 @@ snapshots: safe-regex-test@1.0.2: dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - is-regex: 1.1.4 + call-bind: 1.0.9 + get-intrinsic: 1.3.0 + is-regex: 1.2.1 safer-buffer@2.1.2: {} @@ -28823,14 +29065,16 @@ snapshots: sax@1.6.0: {} + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + scheduler@0.23.2: dependencies: loose-envify: 1.4.0 scheduler@0.25.0-rc-4c58fce7-20240904: {} - scheduler@0.25.0-rc-935180c7e0-20240524: {} - scroll-into-view-if-needed@3.1.0: dependencies: compute-scroll-into-view: 3.1.0 @@ -28945,8 +29189,8 @@ snapshots: define-data-property: 1.1.4 es-errors: 1.3.0 function-bind: 1.1.2 - get-intrinsic: 1.2.4 - gopd: 1.0.1 + get-intrinsic: 1.3.0 + gopd: 1.2.0 has-property-descriptors: 1.0.2 set-function-name@2.0.1: @@ -29048,10 +29292,10 @@ snapshots: side-channel@1.0.6: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.9 es-errors: 1.3.0 - get-intrinsic: 1.2.4 - object-inspect: 1.13.1 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 side-channel@1.1.1: dependencies: @@ -29332,6 +29576,11 @@ snapshots: std-env@3.7.0: {} + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + stoppable@1.1.0: {} stream-chain@2.2.5: {} @@ -29385,19 +29634,19 @@ snapshots: string.prototype.trim@1.2.8: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.9 define-properties: 1.2.1 es-abstract: 1.22.3 string.prototype.trimend@1.0.7: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.9 define-properties: 1.2.1 es-abstract: 1.22.3 string.prototype.trimstart@1.0.7: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.9 define-properties: 1.2.1 es-abstract: 1.22.3 @@ -29650,6 +29899,8 @@ snapshots: symbol-observable@4.0.0: {} + symbol-tree@3.2.4: {} + system-architecture@0.1.0: {} tabbable@6.2.0: {} @@ -29860,12 +30111,23 @@ snapshots: universalify: 0.2.0 url-parse: 1.5.10 + tough-cookie@4.1.4: + dependencies: + psl: 1.9.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + tr46@0.0.3: {} tr46@4.1.1: dependencies: punycode: 2.3.1 + tr46@5.1.1: + dependencies: + punycode: 2.3.1 + traverse@0.6.8: {} treeify@1.1.0: {} @@ -29891,12 +30153,14 @@ snapshots: ts-dedent@2.2.0: {} - ts-evaluator@1.2.0(typescript@5.6.3): + ts-evaluator@1.2.0(jsdom@24.1.3)(typescript@5.6.3): dependencies: ansi-colors: 4.1.3 crosspath: 2.0.0 object-path: 0.11.8 typescript: 5.6.3 + optionalDependencies: + jsdom: 24.1.3 ts-interface-checker@0.1.13: {} @@ -30052,9 +30316,9 @@ snapshots: typed-array-buffer@1.0.0: dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - is-typed-array: 1.1.12 + call-bind: 1.0.9 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 typed-array-buffer@1.0.3: dependencies: @@ -30064,24 +30328,24 @@ snapshots: typed-array-byte-length@1.0.0: dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 + call-bind: 1.0.9 + for-each: 0.3.5 has-proto: 1.0.1 - is-typed-array: 1.1.12 + is-typed-array: 1.1.15 typed-array-byte-offset@1.0.0: dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.7 - for-each: 0.3.3 + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + for-each: 0.3.5 has-proto: 1.0.1 - is-typed-array: 1.1.12 + is-typed-array: 1.1.15 typed-array-length@1.0.4: dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - is-typed-array: 1.1.12 + call-bind: 1.0.9 + for-each: 0.3.5 + is-typed-array: 1.1.15 typedoc-plugin-markdown@4.0.0-next.53(typedoc@0.25.13(typescript@5.9.3)): dependencies: @@ -30182,9 +30446,9 @@ snapshots: unbox-primitive@1.0.2: dependencies: - call-bind: 1.0.7 + call-bind: 1.0.9 has-bigints: 1.0.2 - has-symbols: 1.0.3 + has-symbols: 1.1.0 which-boxed-primitive: 1.0.2 unc-path-regex@0.1.2: {} @@ -30586,7 +30850,7 @@ snapshots: error-stack-parser-es: 0.1.1 fs-extra: 11.2.0 open: 9.1.0 - picocolors: 1.1.0 + picocolors: 1.1.1 sirv: 2.0.4 vite: 6.4.2(@types/node@20.12.7)(jiti@1.21.7)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3) transitivePeerDependencies: @@ -30668,7 +30932,7 @@ snapshots: optionalDependencies: vite: 6.4.2(@types/node@22.18.8)(jiti@1.21.7)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3) - vitest@3.2.6(@types/debug@4.1.13)(@types/node@20.12.7)(@vitest/ui@3.2.6(vitest@3.2.6))(jiti@1.21.7)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3): + vitest@3.2.6(@types/debug@4.1.13)(@types/node@20.12.7)(@vitest/ui@3.2.6(vitest@3.2.6))(jiti@1.21.7)(jsdom@24.1.3)(sass@1.70.0)(terser@5.48.0)(tsx@4.22.4)(yaml@2.8.3): dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.6 @@ -30697,6 +30961,7 @@ snapshots: '@types/debug': 4.1.13 '@types/node': 20.12.7 '@vitest/ui': 3.2.6(vitest@3.2.6) + jsdom: 24.1.3 transitivePeerDependencies: - jiti - less @@ -30721,6 +30986,10 @@ snapshots: vuvuzela@1.0.3: {} + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + wait-on@6.0.1(debug@4.3.7): dependencies: axios: 0.32.0(debug@4.3.7) @@ -30763,11 +31032,22 @@ snapshots: websocket-extensions@0.1.4: {} + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@4.0.0: {} + whatwg-url@13.0.0: dependencies: tr46: 4.1.1 webidl-conversions: 7.0.0 + whatwg-url@14.2.0: + dependencies: + tr46: 5.1.1 + webidl-conversions: 7.0.0 + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 @@ -30784,17 +31064,17 @@ snapshots: which-builtin-type@1.1.3: dependencies: function.prototype.name: 1.1.6 - has-tostringtag: 1.0.0 + has-tostringtag: 1.0.2 is-async-function: 2.0.0 is-date-object: 1.0.5 is-finalizationregistry: 1.0.2 is-generator-function: 1.0.10 - is-regex: 1.1.4 + is-regex: 1.2.1 is-weakref: 1.0.2 isarray: 2.0.5 which-boxed-primitive: 1.0.2 which-collection: 1.0.1 - which-typed-array: 1.1.13 + which-typed-array: 1.1.22 which-collection@1.0.1: dependencies: @@ -30810,14 +31090,6 @@ snapshots: load-yaml-file: 0.2.0 path-exists: 4.0.0 - which-typed-array@1.1.13: - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.0 - which-typed-array@1.1.22: dependencies: available-typed-arrays: 1.0.7 @@ -30898,6 +31170,8 @@ snapshots: ws@8.20.1: {} + xml-name-validator@5.0.0: {} + xml2js@0.5.0: dependencies: sax: 1.6.0 @@ -30905,6 +31179,8 @@ snapshots: xmlbuilder@11.0.1: {} + xmlchars@2.2.0: {} + xmldom-sre@0.1.31: {} xpath.js@1.1.0: {} From 9221998fb93fdc73aba0b002c5ec1ce8b6036573 Mon Sep 17 00:00:00 2001 From: ysoktsk Date: Sat, 18 Jul 2026 16:57:38 +0900 Subject: [PATCH 2/3] fix(next-auth): harden session fetch race guards --- packages/next-auth/src/react.tsx | 118 +++++++++++----- packages/next-auth/src/webauthn.ts | 14 +- packages/next-auth/test/react.test.tsx | 178 +++++++++++++++++-------- packages/next-auth/vitest.config.ts | 32 +++-- 4 files changed, 242 insertions(+), 100 deletions(-) diff --git a/packages/next-auth/src/react.tsx b/packages/next-auth/src/react.tsx index 08f6f30060..a33cc95c53 100644 --- a/packages/next-auth/src/react.tsx +++ b/packages/next-auth/src/react.tsx @@ -177,7 +177,10 @@ export interface GetSessionParams { event?: "storage" | "timer" | "hidden" | string triggerEvent?: boolean broadcast?: boolean - /** Aborts the session fetch, discarding its result. */ + /** + * Cancels the session fetch when aborted, in which case the returned + * promise rejects with an `AbortError` instead of resolving. + */ signal?: AbortSignal } @@ -284,8 +287,11 @@ export async function signIn( }/${provider}` const csrfToken = await getCsrfToken() - // Abort in-flight session fetches before and after the sign-in request, so - // a stale response cannot overwrite the new session state afterwards. + // Abort in-flight session fetches so a stale response cannot overwrite the + // new session state afterwards. This narrows the race window rather than + // closing it: fetches whose response headers already arrived, fetches + // started while this request is running (aborted again below), and other + // tabs' fetches are out of reach. abortFetches(__NEXTAUTH) const res = await fetch( `${signInUrl}?${new URLSearchParams(authorizationParams)}`, @@ -304,6 +310,7 @@ export async function signIn( ) const data = await res.json() + // Also abort fetches that started while the request was running. abortFetches(__NEXTAUTH) if (redirect) { @@ -317,9 +324,9 @@ export async function signIn( const error = new URL(data.url).searchParams.get("error") ?? undefined const code = new URL(data.url).searchParams.get("code") ?? undefined - if (res.ok) { - await __NEXTAUTH._getSession({ event: "storage" }) - } + // Refetch even if the sign-in failed: the aborts above may have discarded + // a legitimate in-flight session update that must be replayed. + await __NEXTAUTH._getSession({ event: "storage" }) return { error, @@ -350,9 +357,12 @@ export async function signOut( } = options ?? {} const baseUrl = apiBaseUrl(__NEXTAUTH) - // Abort in-flight session fetches before and after the sign-out request, so - // a stale response cannot resurrect the session state — or, with the JWT - // strategy, re-issue a rolling session cookie that outlives the sign-out. + // Abort in-flight session fetches so a stale response cannot resurrect the + // session state — or, with the JWT strategy, re-issue a rolling session + // cookie that outlives the sign-out. This narrows the race window rather + // than closing it: fetches whose response headers already arrived, fetches + // started while this request is running (aborted again below), and other + // tabs' fetches are out of reach. abortFetches(__NEXTAUTH) const csrfToken = await getCsrfToken() const res = await fetch(`${baseUrl}/signout`, { @@ -364,6 +374,7 @@ export async function signOut( body: new URLSearchParams({ csrfToken, callbackUrl: redirectTo }), }) const data = await res.json() + // Also abort fetches that started while the request was running. abortFetches(__NEXTAUTH) broadcast().postMessage({ event: "session", data: { trigger: "signout" } }) @@ -418,6 +429,35 @@ export function SessionProvider(props: SessionProviderProps) { const [loading, setLoading] = React.useState(!hasInitialSession) React.useEffect(() => { + /** + * Fetches the session and applies it, unless it was superseded while in + * flight — by a newer session fetch, or by an auth-state change + * (`signIn`, `signOut`) aborting it so a stale response cannot overwrite + * the new state. Returns whether the result was applied. + */ + const fetchAndSetSession = async (params?: GetSessionParams) => { + // A newer session fetch always supersedes the previous one, so at most + // one is in flight; aborting the loser also stops its response from + // re-issuing a rolling session cookie. + abortFetches(__NEXTAUTH) + const controller = new AbortController() + __NEXTAUTH._abort = controller + try { + const session = await getSession({ + ...params, + signal: controller.signal, + }) + if (controller.signal.aborted || __NEXTAUTH._abort !== controller) { + return false + } + __NEXTAUTH._session = session + setSession(session) + return true + } finally { + if (__NEXTAUTH._abort === controller) __NEXTAUTH._abort = null + } + } + __NEXTAUTH._getSession = async ({ event } = {}) => { try { const storageEvent = event === "storage" @@ -425,16 +465,12 @@ export function SessionProvider(props: SessionProviderProps) { // or if there are events from other tabs/windows if (storageEvent || __NEXTAUTH._session === undefined) { __NEXTAUTH._lastSync = now() - const controller = (__NEXTAUTH._abort ??= new AbortController()) - const session = await getSession({ - broadcast: !storageEvent, - signal: controller.signal, - }) - // The auth state changed (e.g. `signOut`) while this fetch was in - // flight; its result is stale and must not overwrite the new state. - if (controller.signal.aborted) return - __NEXTAUTH._session = session - setSession(session) + // Only an applied fetch may settle `loading`: a superseded one is + // settled by its superseder instead, so an aborted initial fetch + // cannot briefly render an authenticated user as unauthenticated. + if (await fetchAndSetSession({ broadcast: !storageEvent })) { + setLoading(false) + } return } @@ -456,17 +492,12 @@ export function SessionProvider(props: SessionProviderProps) { // An event or session staleness occurred, update the client session. __NEXTAUTH._lastSync = now() - const controller = (__NEXTAUTH._abort ??= new AbortController()) - const session = await getSession({ signal: controller.signal }) - if (controller.signal.aborted) return - __NEXTAUTH._session = session - setSession(session) + if (await fetchAndSetSession()) setLoading(false) } catch (error) { if ((error as Error).name === "AbortError") return logger.error( new ClientSessionError((error as Error).message, error as any) ) - } finally { setLoading(false) } } @@ -536,14 +567,35 @@ export function SessionProvider(props: SessionProviderProps) { async update(data: any) { if (loading) return setLoading(true) - const newSession = await fetchData( - "session", - __NEXTAUTH, - logger, - typeof data === "undefined" - ? undefined - : { body: { csrfToken: await getCsrfToken(), data } } - ) + // Tie this fetch to the shared abort so `signIn`/`signOut` can + // discard it: a stale update response must not resurrect the session + // state — or its rolling session cookie — after the auth state + // changed. When discarded, whatever aborted it settles `loading`. + abortFetches(__NEXTAUTH) + const controller = new AbortController() + __NEXTAUTH._abort = controller + let newSession: Session | null + try { + newSession = await fetchData( + "session", + __NEXTAUTH, + logger, + typeof data === "undefined" + ? { signal: controller.signal } + : { + body: { csrfToken: await getCsrfToken(), data }, + signal: controller.signal, + } + ) + if (controller.signal.aborted || __NEXTAUTH._abort !== controller) { + return null + } + } catch (error) { + if ((error as Error).name === "AbortError") return null + throw error + } finally { + if (__NEXTAUTH._abort === controller) __NEXTAUTH._abort = null + } setLoading(false) if (newSession) { setSession(newSession) diff --git a/packages/next-auth/src/webauthn.ts b/packages/next-auth/src/webauthn.ts index b5dee13bf8..0719ae24d5 100644 --- a/packages/next-auth/src/webauthn.ts +++ b/packages/next-auth/src/webauthn.ts @@ -111,8 +111,11 @@ export async function signIn( webAuthnBody.action = webAuthnResponse.action const signInUrl = `${baseUrl}/callback/${provider}?${new URLSearchParams(authorizationParams)}` - // Abort in-flight session fetches before and after the sign-in request, so - // a stale response cannot overwrite the new session state afterwards. + // Abort in-flight session fetches so a stale response cannot overwrite the + // new session state afterwards. This narrows the race window rather than + // closing it: fetches whose response headers already arrived, fetches + // started while this request is running (aborted again below), and other + // tabs' fetches are out of reach. abortFetches(__NEXTAUTH) const res = await fetch(signInUrl, { method: "post", @@ -129,6 +132,7 @@ export async function signIn( }) const data = await res.json() + // Also abort fetches that started while the request was running. abortFetches(__NEXTAUTH) if (redirect) { @@ -142,9 +146,9 @@ export async function signIn( const error = new URL(data.url).searchParams.get("error") const code = new URL(data.url).searchParams.get("code") - if (res.ok) { - await __NEXTAUTH._getSession({ event: "storage" }) - } + // Refetch even if the sign-in failed: the aborts above may have discarded + // a legitimate in-flight session update that must be replayed. + await __NEXTAUTH._getSession({ event: "storage" }) return { error, diff --git a/packages/next-auth/test/react.test.tsx b/packages/next-auth/test/react.test.tsx index 0df94b450e..b87249c46c 100644 --- a/packages/next-auth/test/react.test.tsx +++ b/packages/next-auth/test/react.test.tsx @@ -9,55 +9,43 @@ import { useSession, __NEXTAUTH, } from "../src/react" +import type { UpdateSession } from "../src/react" import type { Session } from "@auth/core/types" const expires = new Date(Date.now() + 60 * 60 * 1000).toISOString() const sessionA: Session = { user: { name: "a" }, expires } const sessionB: Session = { user: { name: "b" }, expires } -interface Deferred { - promise: Promise +interface SessionRequest { resolve: (value: Session | null) => void -} - -function deferred(): Deferred { - let resolve!: Deferred["resolve"] - const promise = new Promise((r) => (resolve = r)) - return { promise, resolve } -} - -interface RecordedCall { - url: string - method: string signal?: AbortSignal } -let calls: RecordedCall[] -/** One deferred per `GET /api/auth/session`, in request order. */ -let sessionRequests: Deferred[] -/** `signal.aborted` of each session request at the moment `POST /signout` was received. */ -let sessionSignalsAbortedAtSignOut: (boolean | undefined)[] | undefined +/** One entry per `GET /api/auth/session`, in request order. */ +let sessionRequests: SessionRequest[] +/** `signal.aborted` of the latest session request when `POST /signout` was received. */ +let staleAbortedAtSignOut: boolean | undefined +/** When set, the credentials callback responds with a failed sign-in. */ +let credentialsSignInFails: boolean -function sessionCalls() { - return calls.filter((c) => c.url.includes("/session")) -} - -function jsonResponse(body: any) { - return { ok: true, status: 200, json: async () => body } -} +let updateSession: UpdateSession function Probe() { - const { data, status } = useSession() - return React.createElement( - "span", - { "data-testid": "state" }, - `${status}:${data?.user?.name ?? "none"}` + const { data, status, update } = useSession() + updateSession = update + return ( + {`${status}:${data?.user?.name ?? "none"}`} ) } -function renderProvider() { +function renderProvider(options?: { strictMode?: boolean }) { + const tree = ( + + + + ) return render( - React.createElement(SessionProvider, null, React.createElement(Probe)) + options?.strictMode ? {tree} : tree ) } @@ -71,16 +59,17 @@ async function nthSessionRequest(n: number) { return sessionRequests[n - 1] } +/** Drains all pending promise chains and re-renders. */ async function flush() { await act(async () => { - await new Promise((r) => setTimeout(r, 10)) + await new Promise((r) => setTimeout(r, 0)) }) } beforeEach(() => { - calls = [] sessionRequests = [] - sessionSignalsAbortedAtSignOut = undefined + staleAbortedAtSignOut = undefined + credentialsSignInFails = false // `BroadcastChannel` would deliver `getSession` messages back to the // provider and trigger extra, nondeterministic session fetches. @@ -90,26 +79,29 @@ beforeEach(() => { "fetch", vi.fn(async (input: any, init: RequestInit = {}) => { const url = typeof input === "string" ? input : input.url - const method = (init.method ?? "get").toString().toLowerCase() - calls.push({ url, method, signal: init.signal ?? undefined }) if (url.includes("/session")) { - const request = deferred() - sessionRequests.push(request) - return request.promise.then(jsonResponse) + const { promise, resolve } = Promise.withResolvers() + sessionRequests.push({ resolve, signal: init.signal ?? undefined }) + return promise.then((body) => Response.json(body)) } - if (url.includes("/csrf")) return jsonResponse({ csrfToken: "csrf" }) + if (url.includes("/csrf")) return Response.json({ csrfToken: "csrf" }) if (url.includes("/signout")) { - sessionSignalsAbortedAtSignOut = sessionCalls().map( - (c) => c.signal?.aborted - ) - return jsonResponse({ url: "http://localhost:3000/" }) + staleAbortedAtSignOut = sessionRequests.at(-1)?.signal?.aborted + return Response.json({ url: "http://localhost:3000/" }) } if (url.includes("/callback/credentials")) { - return jsonResponse({ url: "http://localhost:3000/" }) + return credentialsSignInFails + ? Response.json( + { + url: "http://localhost:3000/api/auth/signin?error=CredentialsSignin", + }, + { status: 401 } + ) + : Response.json({ url: "http://localhost:3000/" }) } if (url.includes("/providers")) { - return jsonResponse({ + return Response.json({ credentials: { id: "credentials", name: "Credentials", @@ -120,7 +112,7 @@ beforeEach(() => { }, }) } - throw new Error(`Unexpected fetch: ${method} ${url}`) + throw new Error(`Unexpected fetch: ${url}`) }) ) }) @@ -146,9 +138,8 @@ describe("in-flight session fetch vs. auth state changes", () => { const stale = await nthSessionRequest(2) // Sign out while the refetch is still pending. - let signOutDone: Promise await act(async () => { - signOutDone = signOut({ redirect: false }) + const signOutDone = signOut({ redirect: false }) // signOut refetches the (now empty) session before resolving. const final = await nthSessionRequest(3) final.resolve(null) @@ -156,10 +147,10 @@ describe("in-flight session fetch vs. auth state changes", () => { }) expect(state()).toBe("unauthenticated:none") - // The stale response must be aborted before the signout request is even + // The stale request must be aborted before the signout request is even // sent, so its rolling session cookie cannot outlive the sign-out. - expect(sessionCalls()[1].signal?.aborted).toBe(true) - expect(sessionSignalsAbortedAtSignOut?.[1]).toBe(true) + expect(stale.signal?.aborted).toBe(true) + expect(staleAbortedAtSignOut).toBe(true) // The stale response arrives last; it must not resurrect the session. await act(async () => stale.resolve(sessionA)) @@ -189,7 +180,7 @@ describe("in-flight session fetch vs. auth state changes", () => { }) await waitFor(() => expect(state()).toBe("authenticated:b")) - expect(sessionCalls()[1].signal?.aborted).toBe(true) + expect(stale.signal?.aborted).toBe(true) // The stale response must not overwrite the new account's session. await act(async () => stale.resolve(sessionA)) @@ -197,4 +188,83 @@ describe("in-flight session fetch vs. auth state changes", () => { expect(state()).toBe("authenticated:b") expect(__NEXTAUTH._session).toEqual(sessionB) }) + + it("signOut discards a stale in-flight update() response", async () => { + renderProvider() + + const first = await nthSessionRequest(1) + await act(async () => first.resolve(sessionA)) + await waitFor(() => expect(state()).toBe("authenticated:a")) + + // An update() starts and stays in flight. + let updateDone!: Promise + await act(async () => { + updateDone = updateSession() + }) + const stale = await nthSessionRequest(2) + + await act(async () => { + const signOutDone = signOut({ redirect: false }) + const final = await nthSessionRequest(3) + final.resolve(null) + await signOutDone + }) + expect(state()).toBe("unauthenticated:none") + expect(stale.signal?.aborted).toBe(true) + expect(staleAbortedAtSignOut).toBe(true) + + // The stale update response must not resurrect the session. + await act(async () => stale.resolve(sessionA)) + await flush() + expect(await updateDone).toBeNull() + expect(state()).toBe("unauthenticated:none") + expect(__NEXTAUTH._session).toBeNull() + }) + + it("a failed signIn replays the session fetch it aborted", async () => { + credentialsSignInFails = true + renderProvider() + + const first = await nthSessionRequest(1) + await act(async () => first.resolve(sessionA)) + await waitFor(() => expect(state()).toBe("authenticated:a")) + + await act(async () => { + document.dispatchEvent(new Event("visibilitychange")) + }) + const stale = await nthSessionRequest(2) + + let result: any + await act(async () => { + const signInDone = signIn("credentials", { redirect: false }) + // The aborted refetch is replayed even though the sign-in failed. + const replay = await nthSessionRequest(3) + replay.resolve(sessionA) + result = await signInDone + }) + + expect(result).toMatchObject({ ok: false, error: "CredentialsSignin" }) + expect(stale.signal?.aborted).toBe(true) + expect(state()).toBe("authenticated:a") + expect(__NEXTAUTH._session).toEqual(sessionA) + }) + + it("an aborted initial fetch does not flash an unauthenticated state", async () => { + // StrictMode aborts the first mount's fetch via the effect cleanup and + // starts a second one; while only the aborted fetch has settled, the + // status must stay "loading" (not "unauthenticated", which would trigger + // useSession({ required: true }) redirects for authenticated users). + renderProvider({ strictMode: true }) + + const aborted = await nthSessionRequest(1) + const current = await nthSessionRequest(2) + expect(aborted.signal?.aborted).toBe(true) + + await act(async () => aborted.resolve(null)) + await flush() + expect(state()).toBe("loading:none") + + await act(async () => current.resolve(sessionA)) + await waitFor(() => expect(state()).toBe("authenticated:a")) + }) }) diff --git a/packages/next-auth/vitest.config.ts b/packages/next-auth/vitest.config.ts index d8356e932b..8512e26900 100644 --- a/packages/next-auth/vitest.config.ts +++ b/packages/next-auth/vitest.config.ts @@ -1,11 +1,27 @@ /// -import sharedConfig from "../utils/vitest.config" +import { defineConfig, mergeConfig } from "vite" +import baseConfig from "../utils/vitest.config" -// The shared config enables `@preact/preset-vite`, which aliases -// react/react-dom to preact/compat and breaks `@testing-library/react`. -// The preset returns an array of plugins, so drop it and keep the rest. -export default { - ...sharedConfig, - plugins: (sharedConfig.plugins ?? []).filter((p) => !Array.isArray(p)), -} +// The base config's `@preact/preset-vite` aliases react/react-dom to +// preact/compat, which breaks `@testing-library/react`, so drop the +// preset's plugins ("preact:config", "vite:preact-jsx", "preact:devtools", +// "prefresh") and keep the rest (swc). +const preactPresetPlugin = /^(preact:|vite:preact-jsx|prefresh)/ + +export default mergeConfig( + { ...baseConfig, plugins: [] }, + defineConfig({ + plugins: (baseConfig.plugins ?? []) + .flat() + .filter( + (p) => + !( + p && + typeof p === "object" && + "name" in p && + preactPresetPlugin.test(p.name) + ) + ), + }) +) From e7a32ba19ce4869437f460b30c69dec750adb63d Mon Sep 17 00:00:00 2001 From: ysoktsk Date: Sat, 18 Jul 2026 17:08:30 +0900 Subject: [PATCH 3/3] chore(next-auth): consolidate session race guard comments --- packages/next-auth/src/lib/client.ts | 14 ++++++-------- packages/next-auth/src/react.tsx | 14 +++----------- packages/next-auth/src/webauthn.ts | 6 +----- 3 files changed, 10 insertions(+), 24 deletions(-) diff --git a/packages/next-auth/src/lib/client.ts b/packages/next-auth/src/lib/client.ts index 36d5f3fddd..824e8c64f9 100644 --- a/packages/next-auth/src/lib/client.ts +++ b/packages/next-auth/src/lib/client.ts @@ -25,12 +25,7 @@ export interface AuthClientConfig { * trigger session updates from places like `signIn` or `signOut` */ _getSession: (...args: any[]) => any - /** - * Aborts in-flight session fetches when the auth state changes - * (e.g. `signIn`, `signOut`), so a stale response cannot overwrite - * the new session state or re-issue a rolling session cookie. - * @internal - */ + /** Lets auth-state changes (`signIn`, `signOut`) abort the in-flight session fetch */ _abort?: AbortController | null } @@ -176,9 +171,12 @@ export async function fetchData( } /** - * Aborts any in-flight session fetch so its (now stale) result — and the + * Aborts the in-flight session fetch so its (now stale) result — and the * rolling session cookie the server attaches to `GET /session` responses — - * is discarded instead of overwriting a newer auth state. + * is discarded instead of overwriting a newer auth state. Auth-mutating + * requests (`signIn`, `signOut`) call this before and after their POST, + * which narrows the race window rather than closing it: responses whose + * headers already arrived and other tabs' fetches are out of reach. * @internal */ export function abortFetches(__NEXTAUTH: AuthClientConfig) { diff --git a/packages/next-auth/src/react.tsx b/packages/next-auth/src/react.tsx index a33cc95c53..5caf22426b 100644 --- a/packages/next-auth/src/react.tsx +++ b/packages/next-auth/src/react.tsx @@ -287,11 +287,7 @@ export async function signIn( }/${provider}` const csrfToken = await getCsrfToken() - // Abort in-flight session fetches so a stale response cannot overwrite the - // new session state afterwards. This narrows the race window rather than - // closing it: fetches whose response headers already arrived, fetches - // started while this request is running (aborted again below), and other - // tabs' fetches are out of reach. + // A stale session response must not overwrite the new session state. abortFetches(__NEXTAUTH) const res = await fetch( `${signInUrl}?${new URLSearchParams(authorizationParams)}`, @@ -357,12 +353,8 @@ export async function signOut( } = options ?? {} const baseUrl = apiBaseUrl(__NEXTAUTH) - // Abort in-flight session fetches so a stale response cannot resurrect the - // session state — or, with the JWT strategy, re-issue a rolling session - // cookie that outlives the sign-out. This narrows the race window rather - // than closing it: fetches whose response headers already arrived, fetches - // started while this request is running (aborted again below), and other - // tabs' fetches are out of reach. + // A stale session response must not resurrect the session state — or, with + // the JWT strategy, its rolling session cookie. abortFetches(__NEXTAUTH) const csrfToken = await getCsrfToken() const res = await fetch(`${baseUrl}/signout`, { diff --git a/packages/next-auth/src/webauthn.ts b/packages/next-auth/src/webauthn.ts index 0719ae24d5..26880831ee 100644 --- a/packages/next-auth/src/webauthn.ts +++ b/packages/next-auth/src/webauthn.ts @@ -111,11 +111,7 @@ export async function signIn( webAuthnBody.action = webAuthnResponse.action const signInUrl = `${baseUrl}/callback/${provider}?${new URLSearchParams(authorizationParams)}` - // Abort in-flight session fetches so a stale response cannot overwrite the - // new session state afterwards. This narrows the race window rather than - // closing it: fetches whose response headers already arrived, fetches - // started while this request is running (aborted again below), and other - // tabs' fetches are out of reach. + // A stale session response must not overwrite the new session state. abortFetches(__NEXTAUTH) const res = await fetch(signInUrl, { method: "post",