diff --git a/frontend/.env b/frontend/.env index fc0b786b2f..d9709783be 100644 --- a/frontend/.env +++ b/frontend/.env @@ -1,7 +1,6 @@ VITE_APP_API_URL=http://localhost:43708/api VITE_APP_CLOUD_API_URL=http://localhost:3000 VITE_APP_ASSETS_URL=https://assets2.rivet.gg -VITE_APP_CLERK_PUBLISHABLE_KEY=pk_test_Zmlyc3QtZG9ua2V5LTQuY2xlcmsuYWNjb3VudHMuZGV2JA VITE_APP_SENTRY_DSN="https://66a566505cfb4341732a3d350f2b87e2@o4504307129188352.ingest.sentry.io/4506435887366144" VITE_APP_SENTRY_PROJECT_ID="4506435887366144" # This is a public-facing token, safe to commit to repo diff --git a/frontend/e2e/auth.setup.ts b/frontend/e2e/auth.setup.ts index b0a530301c..f3ea37806f 100644 --- a/frontend/e2e/auth.setup.ts +++ b/frontend/e2e/auth.setup.ts @@ -1,36 +1,36 @@ -import { setupClerkTestingToken } from "@clerk/testing/playwright"; import { expect, test as setup } from "@playwright/test"; const authFile = ".auth/cloud/user.json"; -setup("authenticate", async ({ page }) => { - // Inject Clerk testing token to bypass bot detection - await setupClerkTestingToken({ page }); - - // Navigate to login page - await page.goto("/login"); - +setup("authenticate", async ({ page, request }) => { // Get credentials from environment - const email = process.env.E2E_CLERK_USER_EMAIL; - const password = process.env.E2E_CLERK_USER_PASSWORD; + const email = process.env.E2E_USER_EMAIL; + const password = process.env.E2E_USER_PASSWORD; if (!email || !password) { throw new Error( - "E2E_CLERK_USER_EMAIL and E2E_CLERK_USER_PASSWORD must be set in .env.local", + "E2E_USER_EMAIL and E2E_USER_PASSWORD must be set in .env.local", ); } - // Fill in email - await page.getByPlaceholder("you@company.com").fill(email); - await page.getByRole("button", { name: "Continue" }).click(); + // Sign in via Better Auth API endpoint + const baseURL = "http://localhost:43710"; + const response = await request.post( + `${baseURL}/api/auth/sign-in/email`, + { + data: { email, password }, + headers: { "Content-Type": "application/json" }, + }, + ); + + expect(response.ok()).toBeTruthy(); - // Wait for password step and fill in password - await page.getByPlaceholder("Your password").fill(password); - await page.getByRole("button", { name: "Continue" }).click(); + // Navigate to trigger cookie storage in browser context + await page.goto("/"); - // Wait for successful redirect (user is logged in) + // Wait for redirect away from login (session cookies are set) await expect(page).not.toHaveURL(/login/); - // Save authentication state + // Save authentication state (cookies + storage) await page.context().storageState({ path: authFile }); }); diff --git a/frontend/e2e/cloud/fixtures/index.ts b/frontend/e2e/cloud/fixtures/index.ts index 7879cd4b5f..fccce2f5d0 100644 --- a/frontend/e2e/cloud/fixtures/index.ts +++ b/frontend/e2e/cloud/fixtures/index.ts @@ -1,4 +1,3 @@ -import { setupClerkTestingToken } from "@clerk/testing/playwright"; import { test as base, type Page } from "@playwright/test"; import { OnboardingIntegrationPage } from "./onboarding-integration-page"; import { OnboardingPage } from "./onboarding-page"; @@ -10,8 +9,8 @@ type Fixtures = { }; export const test = base.extend({ - authenticated: async ({ page, context }, use) => { - await setupClerkTestingToken({ page, context }); + authenticated: async ({ page }, use) => { + // Auth state is loaded from .auth/cloud/user.json via Playwright config await use(page); }, onboardingPage: async ({ authenticated }, use) => { diff --git a/frontend/e2e/global.setup.ts b/frontend/e2e/global.setup.ts index f3893c963b..71e8f062d9 100644 --- a/frontend/e2e/global.setup.ts +++ b/frontend/e2e/global.setup.ts @@ -1,5 +1,4 @@ -import { clerkSetup } from "@clerk/testing/playwright"; - export default async function globalSetup() { - await clerkSetup(); + // No global setup required for Better Auth + // Clerk's clerkSetup() is no longer needed } diff --git a/frontend/package.json b/frontend/package.json index 9f8f0b451a..8af2a1aa93 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -24,11 +24,6 @@ "build:ladle": "ladle build" }, "dependencies": { - "@clerk/clerk-js": "^5.97", - "@clerk/clerk-react": "^5.49.1", - "@clerk/elements": "^0.23.63", - "@clerk/shared": "*", - "@clerk/themes": "^2.4.18", "@codemirror/autocomplete": "^6.18.7", "@codemirror/commands": "^6.8.1", "@codemirror/lang-javascript": "^6.2.4", @@ -121,6 +116,7 @@ "actor-core": "^0.6.3", "autoprefixer": "^10.4.21", "bcryptjs": "^2.4.3", + "better-auth": "^1.5.6", "canvas-confetti": "^1.9.3", "cbor-x": "^1.6.0", "class-variance-authority": "^0.7.1", @@ -167,7 +163,6 @@ "zod": "^3.25.76" }, "devDependencies": { - "@clerk/testing": "^1.13.30", "@playwright/test": "^1.57.0", "dotenv": "^17.2.3", "vitest": "^4.0.18" diff --git a/frontend/src/app.tsx b/frontend/src/app.tsx index de2caab47d..b85def5eb2 100644 --- a/frontend/src/app.tsx +++ b/frontend/src/app.tsx @@ -1,4 +1,3 @@ -import type { Clerk } from "@clerk/clerk-js"; import * as Sentry from "@sentry/react"; import { QueryClientProvider } from "@tanstack/react-query"; import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; @@ -22,7 +21,6 @@ import { } from "./app/data-providers/cache"; import { NotFoundCard } from "./app/not-found-card"; import { RouteLayout } from "./app/route-layout"; -import { clerk } from "./lib/auth"; import { queryClient } from "./queries/global"; import { routeTree } from "./routeTree.gen"; @@ -46,8 +44,6 @@ export const router = createRouter({ basepath: import.meta.env.BASE_URL, routeTree, context: { - clerk: - __APP_TYPE__ === "cloud" ? clerk : (undefined as unknown as Clerk), queryClient: queryClient, getOrCreateCloudContext, getOrCreateEngineContext, diff --git a/frontend/src/app/context-switcher.tsx b/frontend/src/app/context-switcher.tsx index 4de5fd614e..b8fdf25e21 100644 --- a/frontend/src/app/context-switcher.tsx +++ b/frontend/src/app/context-switcher.tsx @@ -1,4 +1,3 @@ -import { useClerk } from "@clerk/clerk-react"; import type { Rivet } from "@rivet-gg/cloud"; import { faChevronDown, @@ -34,6 +33,7 @@ import { } from "@/components/actors"; import { SafeHover } from "@/components/safe-hover"; import { VisibilitySensor } from "@/components/visibility-sensor"; +import { authClient } from "@/lib/auth"; import { LazyBillingPlanBadge } from "./billing/billing-plan-badge"; export function ContextSwitcher({ inline }: { inline?: boolean }) { @@ -315,7 +315,6 @@ function ProjectList({ return params.project; }, }); - const clerk = useClerk(); return (
@@ -371,8 +370,8 @@ function ProjectList({ organization={organization} onSelect={() => { onClose?.(); - clerk.setActive({ - organization, + authClient.organization.setActive({ + organizationId: organization, }); return navigate({ to: "/orgs/$organization/projects/$project", @@ -503,7 +502,6 @@ function NamespaceList({ }), ); const navigate = useNavigate(); - const clerk = useClerk(); const namespace = useParams({ strict: false, select(params) { @@ -561,8 +559,8 @@ function NamespaceList({ className="static w-full" onSelect={() => { onClose?.(); - clerk.setActive({ - organization, + authClient.organization.setActive({ + organizationId: organization, }); return navigate({ to: "/orgs/$organization/projects/$project/ns/$namespace", diff --git a/frontend/src/app/data-providers/cache.ts b/frontend/src/app/data-providers/cache.ts index 1421fdc877..c98ce179cf 100644 --- a/frontend/src/app/data-providers/cache.ts +++ b/frontend/src/app/data-providers/cache.ts @@ -1,4 +1,3 @@ -import type { Clerk } from "@clerk/clerk-js"; import { createNamespaceContext as createCloudNamespaceContext, createGlobalContext as createGlobalCloudContext, @@ -29,9 +28,9 @@ const engineNamespaceContextCache = new Map(); const organizationContextCache = new Map(); const projectContextCache = new Map(); -export function getOrCreateCloudContext(clerk: Clerk): CloudContext { +export function getOrCreateCloudContext(): CloudContext { if (!cloudContextCache) { - cloudContextCache = createGlobalCloudContext({ clerk }); + cloudContextCache = createGlobalCloudContext(); } return cloudContextCache; } diff --git a/frontend/src/app/data-providers/cloud-data-provider.tsx b/frontend/src/app/data-providers/cloud-data-provider.tsx index 3aca5fd4fc..946be4346d 100644 --- a/frontend/src/app/data-providers/cloud-data-provider.tsx +++ b/frontend/src/app/data-providers/cloud-data-provider.tsx @@ -1,4 +1,3 @@ -import type { Clerk } from "@clerk/clerk-js"; import { type Rivet, RivetClient } from "@rivet-gg/cloud"; import { fetcher } from "@rivetkit/engine-api-full/core"; import { @@ -8,7 +7,7 @@ import { queryOptions, type UseQueryOptions, } from "@tanstack/react-query"; -import { clerk } from "@/lib/auth"; +import { authClient } from "@/lib/auth"; import { cloudEnv } from "@/lib/env"; import { queryClient } from "@/queries/global"; import { RECORDS_PER_PAGE } from "./default-data-provider"; @@ -20,13 +19,11 @@ import { } from "./engine-data-provider"; import { no404Retry } from "./utilities"; -function createClient({ clerk }: { clerk: Clerk }) { +function createClient() { return new RivetClient({ baseUrl: () => cloudEnv().VITE_APP_CLOUD_API_URL, environment: "", - token: async () => { - return (await clerk.session?.getToken()) || ""; - }, + token: async () => "", // @ts-expect-error fetcher: async (args) => { Object.keys(args.headers || {}).forEach((key) => { @@ -39,21 +36,26 @@ function createClient({ clerk }: { clerk: Clerk }) { { ...args, maxRetries: 1, + withCredentials: true, }, ); }, }); } -export const createGlobalContext = ({ clerk }: { clerk: Clerk }) => { - const client = createClient({ clerk }); +export const createGlobalContext = () => { + const client = createClient(); return { client, organizationQueryOptions(opts: { org: string }) { return queryOptions({ queryKey: ["organization", opts.org], queryFn: async () => { - return clerk.getOrganization(opts.org); + const result = + await authClient.organization.getFullOrganization({ + query: { organizationId: opts.org }, + }); + return result.data; }, }); }, @@ -317,28 +319,15 @@ export const createOrganizationContext = ({ }; const organizationsQueryOptions = () => - infiniteQueryOptions({ + queryOptions({ queryKey: ["organizations"], - initialPageParam: undefined as number | undefined, - queryFn: async ({ pageParam }) => { - if (!clerk.user) { - throw new Error("No user logged in"); - } - return clerk.user.getOrganizationMemberships({ - initialPage: pageParam, - pageSize: RECORDS_PER_PAGE, - }); - }, - getNextPageParam: (lastPage, allPages) => { - if (lastPage.data.length < RECORDS_PER_PAGE) { - return undefined; + queryFn: async () => { + const result = await authClient.organization.list(); + if (!result.data) { + throw new Error("Failed to list organizations"); } - return allPages.reduce( - (prev, cur) => prev + cur.data.length, - 0, - ); + return result.data; }, - select: (data) => data.pages.flatMap((page) => page.data), }); const createProjectMutationOptions = () => diff --git a/frontend/src/app/dialogs/create-organization-frame.tsx b/frontend/src/app/dialogs/create-organization-frame.tsx index d3707f5a32..8e28b276d0 100644 --- a/frontend/src/app/dialogs/create-organization-frame.tsx +++ b/frontend/src/app/dialogs/create-organization-frame.tsx @@ -2,9 +2,20 @@ import { useMutation } from "@tanstack/react-query"; import * as CreateOrganizationForm from "@/app/forms/create-organization-form"; import { Button, type DialogContentProps, Frame } from "@/components"; import { useCloudDataProvider } from "@/components/actors"; -import { clerk } from "@/lib/auth"; +import { authClient } from "@/lib/auth"; import { queryClient } from "@/queries/global"; +function generateSlug(name: string): string { + const base = name + .toLowerCase() + .replace(/[^a-z0-9\s-]/g, "") + .replace(/\s+/g, "-") + .replace(/-+/g, "-") + .replace(/^-|-$/g, ""); + const suffix = Math.random().toString(36).substring(2, 6); + return `${base}-${suffix}`; +} + interface CreateOrganizationContentProps extends DialogContentProps {} export default function CreateOrganizationContent({ @@ -13,10 +24,11 @@ export default function CreateOrganizationContent({ const dataProvider = useCloudDataProvider(); const { mutateAsync } = useMutation({ mutationFn: async (values: { name: string }) => { - const organization = await clerk.createOrganization({ + const result = await authClient.organization.create({ name: values.name, + slug: generateSlug(values.name), }); - return organization; + return result; }, onSuccess: async () => { await queryClient.invalidateQueries( diff --git a/frontend/src/app/dialogs/create-project-frame.tsx b/frontend/src/app/dialogs/create-project-frame.tsx index 2c9ec28361..dd8865f8e8 100644 --- a/frontend/src/app/dialogs/create-project-frame.tsx +++ b/frontend/src/app/dialogs/create-project-frame.tsx @@ -1,17 +1,17 @@ -import { useOrganization } from "@clerk/clerk-react"; import type { Rivet } from "@rivet-gg/cloud"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { useNavigate } from "@tanstack/react-router"; import * as CreateProjectForm from "@/app/forms/create-project-form"; import { Flex, Frame } from "@/components"; import { useCloudDataProvider } from "@/components/actors"; +import { authClient } from "@/lib/auth"; const useDefaultOrg = () => { if (__APP_TYPE__ === "cloud") { // biome-ignore lint/correctness/useHookAtTopLevel: secured by build condition - const user = useOrganization(); + const org = authClient.useActiveOrganization(); - return user.organization?.id; + return org.data?.id; } return undefined; diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx index 8f71bc6859..5aa19cda7b 100644 --- a/frontend/src/app/layout.tsx +++ b/frontend/src/app/layout.tsx @@ -1,4 +1,3 @@ -import { useUser } from "@clerk/clerk-react"; import { faArrowUpRight, faBook, @@ -48,6 +47,7 @@ import { } from "@/components/actors"; import { useRootLayoutOptional } from "@/components/actors/root-layout-context"; import type { HeaderLinkProps } from "@/components/header/header-link"; +import { authClient } from "@/lib/auth"; import { ensureTrailingSlash } from "@/lib/utils"; import { TEST_IDS } from "@/utils/test-ids"; import { ActorBuildsList } from "./actor-builds-list"; @@ -697,7 +697,7 @@ export const Content = ({ }; export const SidebarlessHeader = () => { - const { user } = useUser(); + const { data: session } = authClient.useSession(); return (
@@ -711,7 +711,7 @@ export const SidebarlessHeader = () => { > Logged in as{" "} - {user?.primaryEmailAddress?.emailAddress} + {session?.user?.email} diff --git a/frontend/src/app/login.tsx b/frontend/src/app/login.tsx index 4fbd32fb70..b211f153b1 100644 --- a/frontend/src/app/login.tsx +++ b/frontend/src/app/login.tsx @@ -1,12 +1,8 @@ "use client"; -import { useClerk, useUser } from "@clerk/clerk-react"; -import * as Clerk from "@clerk/elements/common"; -import * as SignIn from "@clerk/elements/sign-in"; import { faGoogle, faSpinnerThird, Icon } from "@rivet-gg/icons"; import { Link, useNavigate, useSearch } from "@tanstack/react-router"; import { motion } from "framer-motion"; -import { useEffect } from "react"; -import { Badge } from "@/components"; +import { type FormEvent, useState } from "react"; import { Button } from "@/components/ui/button"; import { Card, @@ -18,22 +14,71 @@ import { } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; +import { authClient, redirectToOrganization } from "@/lib/auth"; export function Login() { - const clerk = useClerk(); - const { user } = useUser(); const navigate = useNavigate(); const from = useSearch({ strict: false, select: (s) => s?.from as string }); - // HACK: redirect if user is already logged in, race condition with clerk - // biome-ignore lint/correctness/useExhaustiveDependencies: from is stable - useEffect(() => { - if (user) { - // biome-ignore lint/nursery/noFloatingPromises: ignore - navigate({ to: from ?? "/", search: true }); - return; + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [error, setError] = useState(null); + const [isLoading, setIsLoading] = useState(false); + const [isGoogleLoading, setIsGoogleLoading] = useState(false); + + const handleSubmit = async (e: FormEvent) => { + e.preventDefault(); + setError(null); + setIsLoading(true); + + try { + const result = await authClient.signIn.email({ + email, + password, + }); + + if (result.error) { + setError(result.error.message ?? "Invalid credentials"); + setIsLoading(false); + return; + } + + // Redirect to org page + try { + await redirectToOrganization( + from ? { from } : {}, + ); + } catch (e) { + // redirectToOrganization throws a redirect + throw e; + } + + // Fallback navigation if no redirect thrown + await navigate({ to: from ?? "/", search: true }); + } catch (e) { + // Re-throw redirect errors from TanStack Router + if (e && typeof e === "object" && "to" in e) { + throw e; + } + setError("An unexpected error occurred"); + setIsLoading(false); + } + }; + + const handleGoogleSignIn = async () => { + setError(null); + setIsGoogleLoading(true); + + try { + await authClient.signIn.social({ + provider: "google", + callbackURL: from ?? "/", + }); + } catch { + setError("Failed to initiate Google sign-in"); + setIsGoogleLoading(false); } - }, [user, navigate]); + }; return ( - - - {(isGlobalLoading) => ( - <> - - - - Welcome! - - Enter your email below to login to - your account. - - - -
- {/* - - */} - - - -
-

- or -

- - - - - - - - - -
- -
- - - - - -
-
-
-
- - - - - - Use another method - - - Facing issues? You can use any of - these methods to sign in. - - - - - - - - - - - -
- - - -
-
-
-
- - - - - - - Enter your password - -

- Welcome back{" "} - -

-
- - - - - - - - - - - - -
- - - - - - -
-
-
-
- - - - - - Check your email - - - Enter the verification code sent - to your email - -

- Welcome back{" "} - -

-
- - - - Email verification code - -
-
- { - return ( -
- {value} -
- ); - }} - /> -
- - ( - - )} - > - - -
-
-
- -
- - - - - - -
-
-
-
-
- - )} -
-
+ + + Welcome! + + Enter your email below to login to your account. + + +
+ +
+ +
+

+ or +

+
+ + setEmail(e.target.value)} + disabled={isLoading} + /> +
+
+ + setPassword(e.target.value)} + disabled={isLoading} + /> +
+ {error ? ( +

{error}

+ ) : null} +
+ +
+ + +
+
+
+
); } diff --git a/frontend/src/app/sign-up.tsx b/frontend/src/app/sign-up.tsx index 8801c87c1b..8aa234b376 100644 --- a/frontend/src/app/sign-up.tsx +++ b/frontend/src/app/sign-up.tsx @@ -1,11 +1,8 @@ "use client"; -import { useClerk } from "@clerk/clerk-react"; -import * as Clerk from "@clerk/elements/common"; -import * as ClerkSignUp from "@clerk/elements/sign-up"; -import { faGithub, faGoogle, faSpinnerThird, Icon } from "@rivet-gg/icons"; -import { Link } from "@tanstack/react-router"; +import { faGoogle, faSpinnerThird, Icon } from "@rivet-gg/icons"; +import { Link, useNavigate } from "@tanstack/react-router"; import { motion } from "framer-motion"; -import { Badge, cn, Skeleton } from "@/components"; +import { type FormEvent, useState } from "react"; import { Button } from "@/components/ui/button"; import { Card, @@ -17,9 +14,63 @@ import { } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; +import { authClient } from "@/lib/auth"; export function SignUp() { - const clerk = useClerk(); + const navigate = useNavigate(); + + const [name, setName] = useState(""); + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + const [error, setError] = useState(null); + const [isLoading, setIsLoading] = useState(false); + const [isGoogleLoading, setIsGoogleLoading] = useState(false); + + const handleSubmit = async (e: FormEvent) => { + e.preventDefault(); + setError(null); + setIsLoading(true); + + try { + const result = await authClient.signUp.email({ + email, + password, + name, + }); + + if (result.error) { + setError(result.error.message ?? "Sign up failed"); + setIsLoading(false); + return; + } + + // On success, redirect to onboarding + await navigate({ to: "/onboarding/choose-organization" }); + } catch (e) { + // Re-throw redirect errors from TanStack Router + if (e && typeof e === "object" && "to" in e) { + throw e; + } + setError("An unexpected error occurred"); + setIsLoading(false); + } + }; + + const handleGoogleSignUp = async () => { + setError(null); + setIsGoogleLoading(true); + + try { + await authClient.signIn.social({ + provider: "google", + callbackURL: "/onboarding/choose-organization", + }); + } catch { + setError("Failed to initiate Google sign-up"); + setIsGoogleLoading(false); + } + }; + return ( - - - Welcome! - - Enter your email below to login to your account. - - - -
- - -
-

- or -

-
- - -
-
- - -
-
- -
- - +
+

+ or +

+
+ + setName(e.target.value)} + disabled={isLoading} + /> +
+
+ + setEmail(e.target.value)} + disabled={isLoading} + /> +
+
+ + setPassword(e.target.value)} + disabled={isLoading} + /> +
+ {error ? ( +

{error}

+ ) : null} + + +
+ + -
-
- - } - > - - {(isGlobalLoading) => ( - <> - - - - Welcome! - - Enter your email below to login to - your account. - - - -
- {/* - - */} - - - -
-

- or -

- - - - - - - - - - - - - - - - - - -
- -
- - - - - -
-
-
-
- - - - - - Continue registration - - - - - - - - - - - - - - -
- - - -
-
-
-
- - - - - - - Verify your email - - - Use the verification link sent - to your email address - - - -
- - - Email address - -
- { - return ( -
- {value} - {status === - "cursor" && ( -
-
-
- )} -
- ); - }} - /> -
- - - ( - - )} - > - - -
- - -
- - - -
-
- - - - - )} - - + + +
+
+ +
); } diff --git a/frontend/src/app/user-dropdown.tsx b/frontend/src/app/user-dropdown.tsx index 01db4d60e0..421dff7cc2 100644 --- a/frontend/src/app/user-dropdown.tsx +++ b/frontend/src/app/user-dropdown.tsx @@ -1,4 +1,3 @@ -import { useClerk, useOrganizationList } from "@clerk/clerk-react"; import { faChevronDown, faPlus, Icon } from "@rivet-gg/icons"; import { useQuery } from "@tanstack/react-query"; import { useMatchRoute, useNavigate, useParams } from "@tanstack/react-router"; @@ -20,14 +19,14 @@ import { Skeleton, } from "@/components"; import { useCloudDataProvider } from "@/components/actors"; -import { VisibilitySensor } from "@/components/visibility-sensor"; +import { authClient } from "@/lib/auth"; export function UserDropdown({ children }: { children?: React.ReactNode }) { const params = useParams({ strict: false, }); - const clerk = useClerk(); + const { data: session } = authClient.useSession(); const navigate = useNavigate(); const match = useMatchRoute(); @@ -49,39 +48,11 @@ export function UserDropdown({ children }: { children?: React.ReactNode }) { className="text-muted-foreground justify-between py-1 min-h-8 gap-2 w-full" endIcon={} > - {clerk.user?.primaryEmailAddress?.emailAddress} + {session?.user?.email} ))} - { - clerk.openUserProfile(); - }} - > - Profile - - {clerk.organization ? ( - { - clerk.openOrganizationProfile(); - }} - > - Settings - - ) : null} - {clerk.organization ? ( - { - clerk.openOrganizationProfile({ - __experimental_startPath: - "/organization-members", - }); - }} - > - Members - - ) : null} {isMatchingProjectRoute ? ( { @@ -95,7 +66,7 @@ export function UserDropdown({ children }: { children?: React.ReactNode }) { ) : null} - {clerk.organization ? ( + {params.organization ? ( Switch Organization @@ -111,7 +82,7 @@ export function UserDropdown({ children }: { children?: React.ReactNode }) { ) : null} { - clerk.signOut(); + authClient.signOut(); }} > Logout @@ -135,7 +106,7 @@ function Preview({ org }: { org: string }) { >
- + {isLoading ? ( @@ -157,20 +128,9 @@ function Preview({ org }: { org: string }) { } function OrganizationSwitcher({ value }: { value: string | undefined }) { - const { - userMemberships: { - data: userMemberships = [], - isLoading, - hasNextPage, - fetchNext, - }, - } = useOrganizationList({ - userMemberships: { - infinite: true, - }, - }); + const { data: organizations, isPending: isLoading } = + authClient.useListOrganizations(); - const clerk = useClerk(); const navigate = useNavigate(); return ( @@ -186,55 +146,47 @@ function OrganizationSwitcher({ value }: { value: string | undefined }) { - - - - - - ) : null} - {userMemberships.map((membership) => ( + {organizations?.map((org) => ( { - clerk.setActive({ - organization: membership.organization.id, - navigate: () => { - return navigate({ - to: `/orgs/$organization`, - params: { - organization: - membership.organization.id, - }, - }); + authClient.organization.setActive({ + organizationId: org.id, + }); + navigate({ + to: `/orgs/$organization`, + params: { + organization: org.id, }, }); }} > - + - {membership.organization.name[0].toUpperCase()} + {org.name[0].toUpperCase()} - {membership.organization.name} + {org.name} ))} { - clerk.openCreateOrganization({ - hideSlug: true, - afterCreateOrganizationUrl: (org: { id: string }) => - `/orgs/${org.id}`, + navigate({ + to: ".", + search: (old) => ({ + ...old, + modal: "create-organization", + }), }); }} indicator={} > Create a new organization - {hasNextPage ? : null} ); } diff --git a/frontend/src/components/use-deployment-logs-stream.ts b/frontend/src/components/use-deployment-logs-stream.ts index e28c27b852..84ab61bef1 100644 --- a/frontend/src/components/use-deployment-logs-stream.ts +++ b/frontend/src/components/use-deployment-logs-stream.ts @@ -1,6 +1,5 @@ -import { RivetSse } from "@rivet-gg/cloud"; +import type { RivetSse } from "@rivet-gg/cloud"; import { startTransition, useEffect, useRef, useState } from "react"; -import { clerk } from "@/lib/auth"; import { cloudEnv } from "@/lib/env"; const MAX_RETRIES = 8; @@ -20,6 +19,89 @@ async function sleep(ms: number, signal: AbortSignal) { }); } +function parseSseEvent(raw: string): RivetSse.LogStreamEvent | null { + let eventType = "message"; + let data = ""; + for (const line of raw.split("\n")) { + if (line.startsWith("event:")) eventType = line.slice(6).trim(); + else if (line.startsWith("data:")) data = line.slice(5).trim(); + } + if (!data) return null; + try { + const parsed = JSON.parse(data); + if (eventType === "log") return { event: "log", data: parsed }; + if (eventType === "error") return { event: "error", data: parsed }; + if (eventType === "end") return { event: "end", data: parsed }; + if (eventType === "connected") + return { event: "connected", data: parsed }; + } catch { + // ignore malformed events + } + return null; +} + +async function* streamLogsWithCredentials( + baseUrl: string, + project: string, + namespace: string, + pool: string, + request: { + region?: string; + contains?: string; + abortSignal?: AbortSignal; + }, +): AsyncGenerator { + const params = new URLSearchParams(); + if (request.region) params.set("region", request.region); + if (request.contains) params.set("contains", request.contains); + const qs = params.toString(); + const url = `${baseUrl}/projects/${encodeURIComponent(project)}/namespaces/${encodeURIComponent(namespace)}/managed-pools/${encodeURIComponent(pool)}/logs${qs ? `?${qs}` : ""}`; + + const response = await fetch(url, { + method: "GET", + headers: { + Accept: "text/event-stream", + "Cache-Control": "no-cache", + }, + credentials: "include", + signal: request.abortSignal, + }); + + if (!response.ok) { + const body = await response.text(); + throw new Error( + `streamLogs request failed with status ${response.status}: ${body}`, + ); + } + if (!response.body) throw new Error("streamLogs: response body is null"); + + const reader = response.body.getReader(); + const decoder = new TextDecoder(); + let buffer = ""; + try { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + buffer += decoder.decode(value, { stream: true }); + const parts = buffer.split("\n\n"); + buffer = parts.pop() ?? ""; + for (const part of parts) { + const event = parseSseEvent(part); + if (event != null) { + yield event; + if (event.event === "end") return; + } + } + } + if (buffer.trim()) { + const event = parseSseEvent(buffer); + if (event != null) yield event; + } + } finally { + reader.releaseLock(); + } +} + async function streamWithRetry( project: string, namespace: string, @@ -30,18 +112,12 @@ async function streamWithRetry( onConnected: () => void, onEntry: (entry: RivetSse.LogStreamEvent.Log) => void, ): Promise<"exhausted" | "ended" | "aborted" | { error: string }> { - const options = { - baseUrl: cloudEnv().VITE_APP_CLOUD_API_URL, - environment: "", - token: async () => (await clerk.session?.getToken()) || "", - }; - for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) { if (signal.aborted) return "aborted"; try { - const stream = RivetSse.streamLogs( - options, + const stream = streamLogsWithCredentials( + cloudEnv().VITE_APP_CLOUD_API_URL, project, namespace, pool, diff --git a/frontend/src/lib/auth.ts b/frontend/src/lib/auth.ts index e101a6da26..d612e5b640 100644 --- a/frontend/src/lib/auth.ts +++ b/frontend/src/lib/auth.ts @@ -1,34 +1,36 @@ -import { Clerk } from "@clerk/clerk-js"; +import { createAuthClient } from "better-auth/react"; +import { organizationClient } from "better-auth/client/plugins"; import { redirect } from "@tanstack/react-router"; import { cloudEnv } from "./env"; -export const clerk = +const createClient = () => + createAuthClient({ + baseURL: cloudEnv().VITE_APP_CLOUD_API_URL, + plugins: [organizationClient()], + }); + +type AuthClient = ReturnType; + +export const authClient: AuthClient = __APP_TYPE__ === "cloud" - ? new Clerk(cloudEnv().VITE_APP_CLERK_PUBLISHABLE_KEY) - : (null as unknown as Clerk); + ? createClient() + : (null as unknown as AuthClient); export const redirectToOrganization = async ( - clerk: Clerk, search: Record, ) => { - if (clerk.user) { - if (clerk.organization) { - throw redirect({ - to: "/orgs/$organization", - search: true, - params: { - organization: clerk.organization.id, - }, - }); - } - const { data: orgs } = await clerk.user.getOrganizationMemberships(); + const session = await authClient.getSession(); + if (session.data) { + const orgs = await authClient.organization.list(); - if (orgs.length > 0) { - await clerk.setActive({ organization: orgs[0].organization.id }); + if (orgs.data && orgs.data.length > 0) { + await authClient.organization.setActive({ + organizationId: orgs.data[0].id, + }); throw redirect({ to: "/orgs/$organization", search: true, - params: { organization: orgs[0].organization.id }, + params: { organization: orgs.data[0].id }, }); } throw redirect({ diff --git a/frontend/src/lib/env.ts b/frontend/src/lib/env.ts index 3546919c6a..ec5f10be7c 100644 --- a/frontend/src/lib/env.ts +++ b/frontend/src/lib/env.ts @@ -27,7 +27,6 @@ export const cloudEnvSchema = commonEnvSchema.merge( z.object({ // Cloud API endpoint - direct URL without transformation, used for cloud-specific operations VITE_APP_CLOUD_API_URL: z.string().url(), - VITE_APP_CLERK_PUBLISHABLE_KEY: z.string(), VITE_APP_SENTRY_TUNNEL: z.string().optional(), }), ); diff --git a/frontend/src/lib/waitForClerk.ts b/frontend/src/lib/waitForClerk.ts deleted file mode 100644 index 2f424009b4..0000000000 --- a/frontend/src/lib/waitForClerk.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type { Clerk } from "@clerk/clerk-js"; -import * as Sentry from "@sentry/react"; -import { posthog } from "posthog-js"; - -export function waitForClerk(clerk: Clerk): Promise { - if (clerk.status === "ready") { - identify(clerk); - return Promise.resolve(); - } - - return new Promise((resolve, reject) => { - const timeout = setTimeout(() => { - Sentry.captureMessage("Can't confirm identity", "warning"); - reject(new Error("Clerk timeout")); - }, 10_000); - clerk.on("status", (payload: Clerk["status"]) => { - if (payload === "ready") { - clearTimeout(timeout); - if (clerk.user) { - identify(clerk); - } - resolve(); - } - }); - }); -} - -function identify(clerk: Clerk) { - Sentry.setUser({ - id: clerk.user?.id, - email: clerk.user?.primaryEmailAddress?.emailAddress, - }); - posthog.setPersonProperties({ - id: clerk.user?.id, - email: clerk.user?.primaryEmailAddress?.emailAddress, - }); - - // if (typeof Plain !== "undefined") { - // Plain?.setCustomerDetails({ - // clerkId: clerk.user?.id, - // email: clerk.user?.primaryEmailAddress?.emailAddress, - // }); - // } -} diff --git a/frontend/src/routeTree.gen.ts b/frontend/src/routeTree.gen.ts index 24db44ae53..cbddeed8d4 100644 --- a/frontend/src/routeTree.gen.ts +++ b/frontend/src/routeTree.gen.ts @@ -9,14 +9,12 @@ // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. import { Route as rootRouteImport } from './routes/__root' -import { Route as SsoCallbackRouteImport } from './routes/sso-callback' import { Route as OnboardingRouteImport } from './routes/onboarding' import { Route as LoginRouteImport } from './routes/login' import { Route as JoinRouteImport } from './routes/join' import { Route as ContextRouteImport } from './routes/_context' import { Route as ContextIndexRouteImport } from './routes/_context/index' import { Route as OnboardingChooseOrganizationRouteImport } from './routes/onboarding/choose-organization' -import { Route as OnboardingAcceptInvitationRouteImport } from './routes/onboarding/accept-invitation' import { Route as ContextEngineRouteImport } from './routes/_context/_engine' import { Route as ContextCloudRouteImport } from './routes/_context/_cloud' import { Route as ContextCloudNewIndexRouteImport } from './routes/_context/_cloud/new/index' @@ -42,11 +40,6 @@ import { Route as ContextCloudOrgsOrganizationProjectsProjectNsNamespaceDeployme import { Route as ContextCloudOrgsOrganizationProjectsProjectNsNamespaceConnectRouteImport } from './routes/_context/_cloud/orgs.$organization/projects.$project/ns.$namespace/connect' import { Route as ContextCloudOrgsOrganizationProjectsProjectNsNamespaceBillingRouteImport } from './routes/_context/_cloud/orgs.$organization/projects.$project/ns.$namespace/billing' -const SsoCallbackRoute = SsoCallbackRouteImport.update({ - id: '/sso-callback', - path: '/sso-callback', - getParentRoute: () => rootRouteImport, -} as any) const OnboardingRoute = OnboardingRouteImport.update({ id: '/onboarding', path: '/onboarding', @@ -77,12 +70,6 @@ const OnboardingChooseOrganizationRoute = path: '/choose-organization', getParentRoute: () => OnboardingRoute, } as any) -const OnboardingAcceptInvitationRoute = - OnboardingAcceptInvitationRouteImport.update({ - id: '/accept-invitation', - path: '/accept-invitation', - getParentRoute: () => OnboardingRoute, - } as any) const ContextEngineRoute = ContextEngineRouteImport.update({ id: '/_engine', getParentRoute: () => ContextRoute, @@ -250,8 +237,6 @@ export interface FileRoutesByFullPath { '/join': typeof JoinRoute '/login': typeof LoginRoute '/onboarding': typeof OnboardingRouteWithChildren - '/sso-callback': typeof SsoCallbackRoute - '/onboarding/accept-invitation': typeof OnboardingAcceptInvitationRoute '/onboarding/choose-organization': typeof OnboardingChooseOrganizationRoute '/orgs/$organization': typeof ContextCloudOrgsOrganizationRouteWithChildren '/ns/$namespace': typeof ContextEngineNsNamespaceRouteWithChildren @@ -280,9 +265,7 @@ export interface FileRoutesByTo { '/join': typeof JoinRoute '/login': typeof LoginRoute '/onboarding': typeof OnboardingRouteWithChildren - '/sso-callback': typeof SsoCallbackRoute '/': typeof ContextIndexRoute - '/onboarding/accept-invitation': typeof OnboardingAcceptInvitationRoute '/onboarding/choose-organization': typeof OnboardingChooseOrganizationRoute '/new': typeof ContextCloudNewIndexRoute '/ns/$namespace/settings': typeof ContextEngineNsNamespaceSettingsRoute @@ -309,10 +292,8 @@ export interface FileRoutesById { '/join': typeof JoinRoute '/login': typeof LoginRoute '/onboarding': typeof OnboardingRouteWithChildren - '/sso-callback': typeof SsoCallbackRoute '/_context/_cloud': typeof ContextCloudRouteWithChildren '/_context/_engine': typeof ContextEngineRouteWithChildren - '/onboarding/accept-invitation': typeof OnboardingAcceptInvitationRoute '/onboarding/choose-organization': typeof OnboardingChooseOrganizationRoute '/_context/': typeof ContextIndexRoute '/_context/_cloud/orgs/$organization': typeof ContextCloudOrgsOrganizationRouteWithChildren @@ -345,8 +326,6 @@ export interface FileRouteTypes { | '/join' | '/login' | '/onboarding' - | '/sso-callback' - | '/onboarding/accept-invitation' | '/onboarding/choose-organization' | '/orgs/$organization' | '/ns/$namespace' @@ -375,9 +354,7 @@ export interface FileRouteTypes { | '/join' | '/login' | '/onboarding' - | '/sso-callback' | '/' - | '/onboarding/accept-invitation' | '/onboarding/choose-organization' | '/new' | '/ns/$namespace/settings' @@ -403,10 +380,8 @@ export interface FileRouteTypes { | '/join' | '/login' | '/onboarding' - | '/sso-callback' | '/_context/_cloud' | '/_context/_engine' - | '/onboarding/accept-invitation' | '/onboarding/choose-organization' | '/_context/' | '/_context/_cloud/orgs/$organization' @@ -438,18 +413,10 @@ export interface RootRouteChildren { JoinRoute: typeof JoinRoute LoginRoute: typeof LoginRoute OnboardingRoute: typeof OnboardingRouteWithChildren - SsoCallbackRoute: typeof SsoCallbackRoute } declare module '@tanstack/react-router' { interface FileRoutesByPath { - '/sso-callback': { - id: '/sso-callback' - path: '/sso-callback' - fullPath: '/sso-callback' - preLoaderRoute: typeof SsoCallbackRouteImport - parentRoute: typeof rootRouteImport - } '/onboarding': { id: '/onboarding' path: '/onboarding' @@ -492,13 +459,6 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof OnboardingChooseOrganizationRouteImport parentRoute: typeof OnboardingRoute } - '/onboarding/accept-invitation': { - id: '/onboarding/accept-invitation' - path: '/accept-invitation' - fullPath: '/onboarding/accept-invitation' - preLoaderRoute: typeof OnboardingAcceptInvitationRouteImport - parentRoute: typeof OnboardingRoute - } '/_context/_engine': { id: '/_context/_engine' path: '' @@ -817,12 +777,10 @@ const ContextRouteWithChildren = ContextRoute._addFileChildren(ContextRouteChildren) interface OnboardingRouteChildren { - OnboardingAcceptInvitationRoute: typeof OnboardingAcceptInvitationRoute OnboardingChooseOrganizationRoute: typeof OnboardingChooseOrganizationRoute } const OnboardingRouteChildren: OnboardingRouteChildren = { - OnboardingAcceptInvitationRoute: OnboardingAcceptInvitationRoute, OnboardingChooseOrganizationRoute: OnboardingChooseOrganizationRoute, } @@ -835,7 +793,6 @@ const rootRouteChildren: RootRouteChildren = { JoinRoute: JoinRoute, LoginRoute: LoginRoute, OnboardingRoute: OnboardingRouteWithChildren, - SsoCallbackRoute: SsoCallbackRoute, } export const routeTree = rootRouteImport ._addFileChildren(rootRouteChildren) diff --git a/frontend/src/routes/__root.tsx b/frontend/src/routes/__root.tsx index 0e8fc5baf1..08032cecae 100644 --- a/frontend/src/routes/__root.tsx +++ b/frontend/src/routes/__root.tsx @@ -1,11 +1,7 @@ -import type { Clerk } from "@clerk/clerk-js"; -import { ClerkProvider } from "@clerk/clerk-react"; -import { dark } from "@clerk/themes"; import type { QueryClient } from "@tanstack/react-query"; import { createRootRouteWithContext, Outlet, - useNavigate, } from "@tanstack/react-router"; import { TanStackRouterDevtools } from "@tanstack/react-router-devtools"; import { match } from "ts-pattern"; @@ -18,8 +14,6 @@ import type { ProjectContext, } from "@/app/data-providers/cache"; import { FullscreenLoading } from "@/components"; -import { clerk } from "@/lib/auth"; -import { cloudEnv } from "@/lib/env"; function RootRoute() { return ( @@ -33,51 +27,19 @@ function RootRoute() { } function CloudRoute() { - const navigate = useNavigate(); return ( - navigate({ to })} - routerReplace={(to: string) => navigate({ to, replace: true })} - signInUrl="/login" - signUpUrl="/join" - signInForceRedirectUrl="/sso-callback" - signUpForceRedirectUrl="/sso-callback" - taskUrls={{ - "choose-organization": "/onboarding/choose-organization", - }} - > + <> {import.meta.env.DEV ? ( ) : null} - + ); } interface RootRouteContext { - /** - * Only available in cloud mode - */ - clerk: Clerk; queryClient: QueryClient; - getOrCreateCloudContext: (clerk: Clerk) => CloudContext; + getOrCreateCloudContext: () => CloudContext; getOrCreateEngineContext: ( engineToken: (() => string) | string | (() => Promise), ) => EngineContext; diff --git a/frontend/src/routes/_context.tsx b/frontend/src/routes/_context.tsx index 08d4ce8e06..b4005c32e7 100644 --- a/frontend/src/routes/_context.tsx +++ b/frontend/src/routes/_context.tsx @@ -9,7 +9,7 @@ import { match } from "ts-pattern"; import z from "zod"; import { getConfig, ls, useDialog } from "@/components"; import { ModalRenderer } from "@/components/modal-renderer"; -import { waitForClerk } from "@/lib/waitForClerk"; +import { authClient } from "@/lib/auth"; const searchSchema = z .object({ @@ -29,9 +29,6 @@ const searchSchema = z n: z.array(z.string()).optional(), u: z.string().optional(), t: z.string().optional(), - // clerk related - __clerk_ticket: z.string().optional(), - __clerk_status: z.string().optional(), }) .and(z.record(z.string(), z.any())); @@ -47,7 +44,7 @@ export const Route = createFileRoute("/_context")({ __type: "engine" as const, })) .with("cloud", () => ({ - dataProvider: context.getOrCreateCloudContext(context.clerk), + dataProvider: context.getOrCreateCloudContext(), __type: "cloud" as const, })) .otherwise(() => { @@ -59,19 +56,9 @@ export const Route = createFileRoute("/_context")({ beforeLoad: async (route) => { return await match(route.context) .with({ __type: "cloud" }, () => async () => { - await waitForClerk(route.context.clerk); + const session = await authClient.getSession(); - if ( - route.search.__clerk_ticket && - route.search.__clerk_status - ) { - throw redirect({ - to: "/onboarding/accept-invitation", - search: true, - }); - } - - if (!route.context.clerk.user) { + if (!session.data) { throw redirect({ to: "/login", search: (old) => ({ diff --git a/frontend/src/routes/_context/_cloud.tsx b/frontend/src/routes/_context/_cloud.tsx index bafb576efd..95391e993c 100644 --- a/frontend/src/routes/_context/_cloud.tsx +++ b/frontend/src/routes/_context/_cloud.tsx @@ -7,14 +7,13 @@ import { } from "@tanstack/react-router"; import { match } from "ts-pattern"; import { useDialog } from "@/app/use-dialog"; -import { waitForClerk } from "@/lib/waitForClerk"; export const Route = createFileRoute("/_context/_cloud")({ component: RouteComponent, beforeLoad: ({ context }) => { return match(context) - .with({ __type: "cloud" }, async () => { - await waitForClerk(context.clerk); + .with({ __type: "cloud" }, () => { + // Auth check handled by parent _context beforeLoad }) .otherwise(() => { throw notFound(); diff --git a/frontend/src/routes/_context/_cloud/new/index.tsx b/frontend/src/routes/_context/_cloud/new/index.tsx index 2774110efa..6c1699806d 100644 --- a/frontend/src/routes/_context/_cloud/new/index.tsx +++ b/frontend/src/routes/_context/_cloud/new/index.tsx @@ -1,12 +1,15 @@ import { createFileRoute, redirect } from "@tanstack/react-router"; +import { authClient } from "@/lib/auth"; export const Route = createFileRoute("/_context/_cloud/new/")({ component: RouteComponent, - beforeLoad: async ({ context, params }) => { + beforeLoad: async ({ params }) => { + const session = await authClient.getSession(); + const orgId = session.data?.session?.activeOrganizationId ?? ""; throw redirect({ to: "/orgs/$organization/new", params: { - organization: context.clerk.organization?.id ?? "", + organization: orgId, ...params, }, search: true, diff --git a/frontend/src/routes/_context/_cloud/orgs.$organization.tsx b/frontend/src/routes/_context/_cloud/orgs.$organization.tsx index 5a466e2f50..c56776b3f0 100644 --- a/frontend/src/routes/_context/_cloud/orgs.$organization.tsx +++ b/frontend/src/routes/_context/_cloud/orgs.$organization.tsx @@ -1,16 +1,15 @@ import { createFileRoute, Outlet } from "@tanstack/react-router"; import { match } from "ts-pattern"; +import { authClient } from "@/lib/auth"; export const Route = createFileRoute("/_context/_cloud/orgs/$organization")({ component: RouteComponent, beforeLoad: async ({ context, params }) => { return await match(context) .with({ __type: "cloud" }, async (context) => { - if (context.clerk.organization.id !== params.organization) { - await context.clerk.setActive({ - organization: params.organization, - }); - } + await authClient.organization.setActive({ + organizationId: params.organization, + }); return { dataProvider: context.getOrCreateOrganizationContext( diff --git a/frontend/src/routes/_context/_cloud/orgs.$organization/index.tsx b/frontend/src/routes/_context/_cloud/orgs.$organization/index.tsx index 0f27f89ffa..e1b7900fde 100644 --- a/frontend/src/routes/_context/_cloud/orgs.$organization/index.tsx +++ b/frontend/src/routes/_context/_cloud/orgs.$organization/index.tsx @@ -8,9 +8,6 @@ export const Route = createFileRoute("/_context/_cloud/orgs/$organization/")({ loader: async ({ context, params }) => { return match(context) .with({ __type: "cloud" }, async () => { - if (!context.clerk?.organization) { - return; - } const result = await context.queryClient.fetchInfiniteQuery( context.dataProvider.currentOrgProjectsQueryOptions(), ); diff --git a/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/index.tsx b/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/index.tsx index c43e536a0e..ae4a3fb634 100644 --- a/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/index.tsx +++ b/frontend/src/routes/_context/_cloud/orgs.$organization/projects.$project/index.tsx @@ -10,9 +10,6 @@ export const Route = createFileRoute( beforeLoad: ({ context, params, search }) => { return match(__APP_TYPE__) .with("cloud", async () => { - if (!context.clerk?.organization) { - throw notFound(); - } const result = await context.queryClient.fetchInfiniteQuery( context.dataProvider.currentProjectNamespacesQueryOptions(), ); diff --git a/frontend/src/routes/_context/index.tsx b/frontend/src/routes/_context/index.tsx index 10003b15bc..a95e730049 100644 --- a/frontend/src/routes/_context/index.tsx +++ b/frontend/src/routes/_context/index.tsx @@ -18,7 +18,7 @@ export const Route = createFileRoute("/_context/")({ beforeLoad: async ({ context, search }) => { return await match(context) .with({ __type: "cloud" }, async () => { - if (!(await redirectToOrganization(context.clerk, search))) { + if (!(await redirectToOrganization(search))) { throw redirect({ to: "/login", search: true }); } }) diff --git a/frontend/src/routes/join.tsx b/frontend/src/routes/join.tsx index 448fb3b001..50f3b511aa 100644 --- a/frontend/src/routes/join.tsx +++ b/frontend/src/routes/join.tsx @@ -1,13 +1,13 @@ import { createFileRoute, redirect } from "@tanstack/react-router"; import { Logo } from "@/app/logo"; import { SignUp } from "@/app/sign-up"; -import { waitForClerk } from "@/lib/waitForClerk"; +import { authClient } from "@/lib/auth"; export const Route = createFileRoute("/join")({ component: RouteComponent, - beforeLoad: async ({ context }) => { - await waitForClerk(context.clerk); - if (context.clerk.user) { + beforeLoad: async () => { + const session = await authClient.getSession(); + if (session.data) { throw redirect({ to: "/", search: true }); } }, diff --git a/frontend/src/routes/login.tsx b/frontend/src/routes/login.tsx index bde6cc6f24..fc9ce24d37 100644 --- a/frontend/src/routes/login.tsx +++ b/frontend/src/routes/login.tsx @@ -1,14 +1,15 @@ import { createFileRoute } from "@tanstack/react-router"; import { Login } from "@/app/login"; import { Logo } from "@/app/logo"; -import { redirectToOrganization } from "@/lib/auth"; -import { waitForClerk } from "@/lib/waitForClerk"; +import { authClient, redirectToOrganization } from "@/lib/auth"; export const Route = createFileRoute("/login")({ component: RouteComponent, - beforeLoad: async ({ context, search }) => { - await waitForClerk(context.clerk); - await redirectToOrganization(context.clerk, search); + beforeLoad: async ({ search }) => { + const session = await authClient.getSession(); + if (session.data) { + await redirectToOrganization(search as Record); + } }, }); diff --git a/frontend/src/routes/onboarding.tsx b/frontend/src/routes/onboarding.tsx index f74e7c1224..3797cd9b66 100644 --- a/frontend/src/routes/onboarding.tsx +++ b/frontend/src/routes/onboarding.tsx @@ -1,14 +1,17 @@ -import { createFileRoute, notFound, Outlet } from "@tanstack/react-router"; -import { waitForClerk } from "@/lib/waitForClerk"; +import { createFileRoute, notFound, Outlet, redirect } from "@tanstack/react-router"; +import { authClient } from "@/lib/auth"; export const Route = createFileRoute("/onboarding")({ component: RouteComponent, - beforeLoad: async (route) => { + beforeLoad: async () => { if (__APP_TYPE__ !== "cloud") { throw notFound(); } - await waitForClerk(route.context.clerk); + const session = await authClient.getSession(); + if (!session.data) { + throw redirect({ to: "/login" }); + } }, }); diff --git a/frontend/src/routes/onboarding/accept-invitation.tsx b/frontend/src/routes/onboarding/accept-invitation.tsx deleted file mode 100644 index b9a0071e2e..0000000000 --- a/frontend/src/routes/onboarding/accept-invitation.tsx +++ /dev/null @@ -1,258 +0,0 @@ -import { isClerkAPIResponseError } from "@clerk/clerk-js"; -import { useOrganization, useSignIn, useSignUp } from "@clerk/clerk-react"; -import { createFileRoute, Link, useNavigate } from "@tanstack/react-router"; -import { zodValidator } from "@tanstack/zod-adapter"; -import { useEffect, useState } from "react"; -import { useIsMounted } from "usehooks-ts"; -import z from "zod"; -import * as OrgSignUpForm from "@/app/forms/org-sign-up-form"; -import { Logo } from "@/app/logo"; -import { - Button, - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, - toast, -} from "@/components"; -import { clerk } from "@/lib/auth"; - -export const Route = createFileRoute("/onboarding/accept-invitation")({ - component: RouteComponent, - validateSearch: zodValidator( - z - .object({ - __clerk_ticket: z.string().optional(), - __clerk_status: z.string().optional(), - }) - .optional(), - ), -}); - -function RouteComponent() { - const search = Route.useSearch(); - const { organization } = useOrganization(); - - if ( - search?.__clerk_status === "sign_up" && - search.__clerk_ticket && - !organization - ) { - // display sign up flow - return ( -
-
- - -
-
- ); - } - - if ( - search?.__clerk_status === "sign_in" && - search.__clerk_ticket && - !organization - ) { - // complete sign in flow - return ( -
-
- - -
-
- ); - } - - if ( - search?.__clerk_status === "sign_in" && - search.__clerk_ticket && - organization - ) { - // if we get here, the user is already signed in but maybe not to the right org - return ; - } - - if (search?.__clerk_status === "complete") { - // if we get here, the user is already signed in - return ; - } - - return ( -
-
- - - - Invalid Invitation - - The invitation link is invalid. Please check the - link or contact support. - - - -
-
- ); -} - -function OrgSignUpFlow({ ticket }: { ticket: string }) { - const { signUp, setActive: setActiveSignUp } = useSignUp(); - const navigate = useNavigate(); - - return ( - { - try { - const signUpAttempt = await signUp?.create({ - strategy: "ticket", - ticket, - password, - }); - - if (signUpAttempt?.status === "complete") { - await setActiveSignUp?.({ - session: signUpAttempt.createdSessionId, - }); - await navigate({ to: "/" }); - } else { - console.error( - "Sign up attempt not complete", - signUpAttempt, - ); - toast.error( - "An error occurred during sign up. Please try again.", - ); - } - } catch (e) { - if (isClerkAPIResponseError(e)) { - for (const error of e.errors) { - form.setError( - (error.meta?.paramName || "root") as "root", - { - message: error.longMessage, - }, - ); - } - } else { - toast.error( - "An unknown error occurred. Please try again.", - ); - } - } - }} - > - - - Welcome! - - Please set a password for your new account. - - - -
- -
-
- - - Continue - - -
-
- ); -} - -function OrgSignInFlow({ ticket }: { ticket: string }) { - const { organization } = useOrganization(); - const { signIn, setActive: setActiveSignIn } = useSignIn(); - const isMounted = useIsMounted(); - const navigate = useNavigate(); - - const [error, setError] = useState(null); - - useEffect(() => { - async function signInWithTicket() { - const signInAttempt = await signIn?.create({ - strategy: "ticket", - ticket, - }); - - // If the sign-in was successful, set the session to active - if (signInAttempt?.status === "complete") { - await setActiveSignIn?.({ - session: signInAttempt?.createdSessionId, - }); - await navigate({ to: "/" }); - } else { - // If the sign-in attempt is not complete, check why. - // User may need to complete further steps. - console.error(JSON.stringify(signInAttempt, null, 2)); - } - } - - signInWithTicket().catch((e) => { - if (isClerkAPIResponseError(e)) { - setError(e.message); - } else { - setError("An unknown error occurred. Please try again."); - } - }); - }, [isMounted]); - - return ( - - - Welcome back! - - You are signing in to {organization?.name || "your account"} - . - - - {error && ( - -
{error}
-
- )} -
- ); -} - -function CompleteFlow() { - return ( -
-
- - - - Invitation Accepted - - You have successfully accepted the invitation. You - can now proceed to the dashboard. - - - - - - -
-
- ); -} - -function AcceptInvitation({ ticket }: { ticket: string }) { - useEffect(() => { - clerk.getFapiClient().request({ - path: "/tickets/accept", - search: { ticket }, - }); - }, [ticket]); - return ; -} diff --git a/frontend/src/routes/onboarding/choose-organization.tsx b/frontend/src/routes/onboarding/choose-organization.tsx index 163d4401d3..2bee14fe45 100644 --- a/frontend/src/routes/onboarding/choose-organization.tsx +++ b/frontend/src/routes/onboarding/choose-organization.tsx @@ -1,64 +1,49 @@ import { createFileRoute, redirect } from "@tanstack/react-router"; import { Content } from "@/app/layout"; import { RouteLayout } from "@/app/route-layout"; +import { authClient } from "@/lib/auth"; export const Route = createFileRoute("/onboarding/choose-organization")({ component: RouteComponent, - beforeLoad: async ({ context }) => { - const RELOAD_KEY = "clerk-session-reload-count"; - - // After SSO, there's a race condition where Clerk redirects here before - // the session is fully established. If we detect this (user exists from - // API perspective but no local session), reload to let Clerk sync state. - if (!context.clerk.session) { - const MAX_RELOADS = 3; - const reloadCount = Number( - sessionStorage.getItem(RELOAD_KEY) || "0", - ); - - if (reloadCount < MAX_RELOADS) { - console.log( - `[choose-organization] No session yet, reloading page to sync Clerk state (attempt ${reloadCount + 1}/${MAX_RELOADS})`, - ); - sessionStorage.setItem(RELOAD_KEY, String(reloadCount + 1)); - window.location.reload(); - // Return a never-resolving promise to prevent further execution - return new Promise(() => {}); - } - - // Max reloads reached, clear counter and show error - sessionStorage.removeItem(RELOAD_KEY); - console.error( - "[choose-organization] No session after max reload attempts", - ); - throw new Error( - "Unable to establish session. Please try signing in again.", - ); + beforeLoad: async () => { + const session = await authClient.getSession(); + if (!session.data) { + throw redirect({ to: "/login" }); } - // Clear reload counter on success - sessionStorage.removeItem(RELOAD_KEY); + const orgs = await authClient.organization.list(); - if (context.clerk.organization) { + if (orgs.data && orgs.data.length > 0) { + await authClient.organization.setActive({ + organizationId: orgs.data[0].id, + }); throw redirect({ to: "/orgs/$organization", - params: { organization: context.clerk.organization.id }, + params: { organization: orgs.data[0].id }, search: true, }); } - const org = await context.clerk.createOrganization({ - name: `${context.clerk.user?.firstName || context.clerk.user?.primaryEmailAddress?.emailAddress.split("@")[0] || "Anonymous"}'s Organization`, - }); + // No orgs — auto-create a default org + const user = session.data.user; + const name = `${user.name || user.email.split("@")[0] || "Anonymous"}'s Organization`; + const slug = `${name.toLowerCase().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "")}-${Math.random().toString(36).substring(2, 6)}`; + + const newOrg = await authClient.organization.create({ name, slug }); - await context.clerk.setActive({ organization: org.id }); - await context.clerk.session?.reload(); + if (newOrg.data) { + await authClient.organization.setActive({ + organizationId: newOrg.data.id, + }); + throw redirect({ + to: "/orgs/$organization", + params: { organization: newOrg.data.id }, + search: true, + }); + } - throw redirect({ - to: "/orgs/$organization", - params: { organization: org.id }, - search: true, - }); + // Fallback — should not happen + throw redirect({ to: "/login" }); }, }); diff --git a/frontend/src/routes/sso-callback.tsx b/frontend/src/routes/sso-callback.tsx deleted file mode 100644 index 62f5b7c7d8..0000000000 --- a/frontend/src/routes/sso-callback.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { AuthenticateWithRedirectCallback } from "@clerk/clerk-react"; -import { createFileRoute } from "@tanstack/react-router"; -import { FullscreenLoading } from "@/components"; - -export const Route = createFileRoute("/sso-callback")({ - component: RouteComponent, -}); - -function RouteComponent() { - return ( - <> - - {/** biome-ignore lint/correctness/useUniqueElementIds: required by clerk */} -
- - - - ); -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f1500907db..c467d84755 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -271,7 +271,7 @@ importers: dependencies: '@hono/node-server': specifier: ^1.19.1 - version: 1.19.12(hono@4.11.9) + version: 1.19.9(hono@4.11.9) '@rivetkit/engine-envoy-client': specifier: workspace:* version: link:../envoy-client @@ -493,13 +493,13 @@ importers: dependencies: '@ai-sdk/openai': specifier: ^0.0.66 - version: 0.0.66(zod@4.1.13) + version: 0.0.66(zod@4.3.6) '@rivetkit/react': specifier: workspace:* version: link:../../rivetkit-typescript/packages/react ai: specifier: ^4.0.38 - version: 4.3.19(react@19.1.0)(zod@4.1.13) + version: 4.3.19(react@19.1.0)(zod@4.3.6) react: specifier: 19.1.0 version: 19.1.0 @@ -542,7 +542,7 @@ importers: dependencies: '@ai-sdk/openai': specifier: ^0.0.66 - version: 0.0.66(zod@4.1.13) + version: 0.0.66(zod@4.3.6) '@hono/node-server': specifier: ^1.19.7 version: 1.19.9(hono@4.11.9) @@ -554,7 +554,7 @@ importers: version: link:../../rivetkit-typescript/packages/react ai: specifier: ^4.0.38 - version: 4.3.19(react@19.1.0)(zod@4.1.13) + version: 4.3.19(react@19.1.0)(zod@4.3.6) hono: specifier: ^4.11.3 version: 4.11.9 @@ -2097,7 +2097,7 @@ importers: version: link:../../rivetkit-typescript/packages/next-js next: specifier: 16.1.1 - version: 16.1.1(@opentelemetry/api@1.9.0)(@playwright/test@1.57.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.93.2) + version: 16.1.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.57.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.93.2) react: specifier: 19.1.0 version: 19.1.0 @@ -2630,7 +2630,7 @@ importers: version: 4.3.19(react@19.1.0)(zod@3.25.76) drizzle-orm: specifier: ^0.44.2 - version: 0.44.6(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.8)(pg@8.17.2)(sql.js@1.13.0) + version: 0.44.6(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.15)(pg@8.17.2)(sql.js@1.13.0) fdb-tuple: specifier: ^1.0.0 version: 1.0.0 @@ -2801,7 +2801,7 @@ importers: version: 4.3.19(react@19.1.0)(zod@3.25.76) drizzle-orm: specifier: ^0.44.2 - version: 0.44.6(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.8)(pg@8.17.2)(sql.js@1.13.0) + version: 0.44.6(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.15)(pg@8.17.2)(sql.js@1.13.0) fdb-tuple: specifier: ^1.0.0 version: 1.0.0 @@ -2954,7 +2954,7 @@ importers: version: 0.31.5 drizzle-orm: specifier: ^0.44.2 - version: 0.44.6(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.8)(pg@8.17.2)(sql.js@1.13.0) + version: 0.44.6(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.15)(pg@8.17.2)(sql.js@1.13.0) devDependencies: '@types/node': specifier: ^22.13.9 @@ -3201,21 +3201,6 @@ importers: frontend: dependencies: - '@clerk/clerk-js': - specifier: ^5.97 - version: 5.97.0(@types/react@19.2.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.1.0))(zod@3.25.76) - '@clerk/clerk-react': - specifier: ^5.49.1 - version: 5.49.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@clerk/elements': - specifier: ^0.23.63 - version: 0.23.63(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(next@15.5.9(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.57.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.93.2))(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@clerk/shared': - specifier: 3.27.1 - version: 3.27.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@clerk/themes': - specifier: ^2.4.18 - version: 2.4.21(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@codemirror/autocomplete': specifier: 6.18.7 version: 6.18.7 @@ -3485,13 +3470,16 @@ importers: version: 12.10.0(@types/react@19.2.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) actor-core: specifier: ^0.6.3 - version: 0.6.3(eventsource@3.0.7)(ws@8.18.3) + version: 0.6.3(eventsource@3.0.7)(ws@8.19.0) autoprefixer: specifier: ^10.4.21 version: 10.4.22(postcss@8.5.6) bcryptjs: specifier: ^2.4.3 version: 2.4.3 + better-auth: + specifier: ^1.5.6 + version: 1.5.6(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(drizzle-kit@0.31.5)(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.15)(pg@8.17.2)(sql.js@1.13.0))(next@16.1.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.57.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.93.2))(pg@8.17.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@20.19.13)(jiti@1.21.7)(less@4.4.1)(lightningcss@1.32.0)(msw@2.12.10(@types/node@20.19.13)(typescript@5.9.3))(sass@1.93.2)(stylus@0.62.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) canvas-confetti: specifier: ^1.9.3 version: 1.9.3 @@ -3625,9 +3613,6 @@ importers: specifier: ^3.25.76 version: 3.25.76 devDependencies: - '@clerk/testing': - specifier: ^1.13.30 - version: 1.13.30(@playwright/test@1.57.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@playwright/test': specifier: ^1.57.0 version: 1.57.0 @@ -4289,7 +4274,7 @@ importers: version: 4.0.9 drizzle-orm: specifier: ^0.44.2 - version: 0.44.6(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.8)(pg@8.17.2)(sql.js@1.13.0) + version: 0.44.6(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.15)(pg@8.17.2)(sql.js@1.13.0) eventsource: specifier: ^4.0.0 version: 4.0.0 @@ -4812,7 +4797,7 @@ importers: version: 19.2.13 drizzle-orm: specifier: ^0.38.0 - version: 0.38.4(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/react@19.2.13)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.8)(pg@8.17.2)(react@19.1.0)(sql.js@1.13.0) + version: 0.38.4(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/react@19.2.13)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.15)(pg@8.17.2)(react@19.1.0)(sql.js@1.13.0) typescript: specifier: ^5.7.3 version: 5.9.3 @@ -4830,9 +4815,6 @@ packages: '@adobe/css-tools@4.3.3': resolution: {integrity: sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==} - '@adraffy/ens-normalize@1.11.1': - resolution: {integrity: sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==} - '@agentclientprotocol/sdk@0.16.1': resolution: {integrity: sha512-1ad+Sc/0sCtZGHthxxvgEUo5Wsbw16I+aF+YwdiLnPwkZG8KAGUEAPK6LM6Pf69lCyJPt1Aomk1d+8oE3C4ZEw==} peerDependencies: @@ -5768,8 +5750,80 @@ packages: peerDependencies: '@bare-ts/lib': '>=0.3.0 <=0.4.0' - '@base-org/account@2.0.1': - resolution: {integrity: sha512-tySVNx+vd6XEynZL0uvB10uKiwnAfThr8AbKTwILVG86mPbLAhEOInQIk+uDnvpTvfdUhC1Bi5T/46JvFoLZQQ==} + '@better-auth/core@1.5.6': + resolution: {integrity: sha512-Ez9DZdIMFyxHremmoLz1emFPGNQomDC1jqqBPnZ6Ci+6TiGN3R9w/Y03cJn6I8r1ycKgOzeVMZtJ/erOZ27Gsw==} + peerDependencies: + '@better-auth/utils': 0.3.1 + '@better-fetch/fetch': 1.1.21 + '@cloudflare/workers-types': '>=4' + '@opentelemetry/api': ^1.9.0 + better-call: 1.3.2 + jose: ^6.1.0 + kysely: ^0.28.5 + nanostores: ^1.0.1 + peerDependenciesMeta: + '@cloudflare/workers-types': + optional: true + + '@better-auth/drizzle-adapter@1.5.6': + resolution: {integrity: sha512-VfFFmaoFw3ug12SiSuIwzrMoHyIVmkMGWm9gZ4sXdYYVX4HboCL4m3fjzOhppcmK5OGatRuU+N1UX6wxCITcXw==} + peerDependencies: + '@better-auth/core': 1.5.6 + '@better-auth/utils': ^0.3.0 + drizzle-orm: '>=0.41.0' + peerDependenciesMeta: + drizzle-orm: + optional: true + + '@better-auth/kysely-adapter@1.5.6': + resolution: {integrity: sha512-Fnf+h8WVKtw6lEOmVmiVVzDf3shJtM60AYf9XTnbdCeUd6MxN/KnaJZpkgtYnRs7a+nwtkVB+fg4lGETebGFXQ==} + peerDependencies: + '@better-auth/core': 1.5.6 + '@better-auth/utils': ^0.3.0 + kysely: ^0.27.0 || ^0.28.0 + peerDependenciesMeta: + kysely: + optional: true + + '@better-auth/memory-adapter@1.5.6': + resolution: {integrity: sha512-rS7ZsrIl5uvloUgNN0u9LOZJMMXnsZXVdUZ3MrTBKWM2KpoJjzPr9yN3Szyma5+0V7SltnzSGHPkYj2bEzzmlA==} + peerDependencies: + '@better-auth/core': 1.5.6 + '@better-auth/utils': ^0.3.0 + + '@better-auth/mongo-adapter@1.5.6': + resolution: {integrity: sha512-6+M3MS2mor8fTUV3EI1FBLP0cs6QfbN+Ovx9+XxR/GdfKIBoNFzmPEPRbdGt+ft6PvrITsUm+T70+kkHgVSP6w==} + peerDependencies: + '@better-auth/core': 1.5.6 + '@better-auth/utils': ^0.3.0 + mongodb: ^6.0.0 || ^7.0.0 + peerDependenciesMeta: + mongodb: + optional: true + + '@better-auth/prisma-adapter@1.5.6': + resolution: {integrity: sha512-UxY9vQJs1Tt+O+T2YQnseDMlWmUSQvFZSBb5YiFRg7zcm+TEzujh4iX2/csA0YiZptLheovIuVWTP9nriewEBA==} + peerDependencies: + '@better-auth/core': 1.5.6 + '@better-auth/utils': ^0.3.0 + '@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0 + prisma: ^5.0.0 || ^6.0.0 || ^7.0.0 + peerDependenciesMeta: + '@prisma/client': + optional: true + prisma: + optional: true + + '@better-auth/telemetry@1.5.6': + resolution: {integrity: sha512-yXC7NSxnIFlxDkGdpD7KA+J9nqIQAPCJKe77GoaC5bWoe/DALo1MYorZfTgOafS7wrslNtsPT4feV/LJi1ubqQ==} + peerDependencies: + '@better-auth/core': 1.5.6 + + '@better-auth/utils@0.3.1': + resolution: {integrity: sha512-+CGp4UmZSUrHHnpHhLPYu6cV+wSUSvVbZbNykxhUDocpVNTo9uFFxw/NqJlh1iC4wQ9HKKWGCKuZ5wUgS0v6Kg==} + + '@better-fetch/fetch@1.1.21': + resolution: {integrity: sha512-/ImESw0sskqlVR94jB+5+Pxjf+xBwDZF/N5+y2/q4EqD7IARUTSpPfIo8uf39SYpCxyOCtbyYpUrZ3F/k0zT4A==} '@biomejs/biome@2.3.11': resolution: {integrity: sha512-/zt+6qazBWguPG6+eWmiELqO+9jRsMZ/DBU3lfuU2ngtIQYzymocHhKiZRyrbra4aCOoyTg/BmY+6WH5mv9xmQ==} @@ -5912,73 +5966,6 @@ packages: '@chevrotain/utils@11.0.3': resolution: {integrity: sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==} - '@clerk/backend@2.29.4': - resolution: {integrity: sha512-SAw6bnUAqVjROM4AMXEncN1f0XuC9dyEZx7Vuw2JUyzwTLUP4Yp0Q64qD+cqZRJBoUnmaOaRLtswR/m/a0R8yw==} - engines: {node: '>=18.17.0'} - - '@clerk/clerk-js@5.97.0': - resolution: {integrity: sha512-bFaghDHoXni1m8gW0iHadyF1PR6/hV5FID5Ec8S3L3TvhU90LCpU3blakaRKHuoINfPXhk6UwIqSpEbKrYB/iA==} - engines: {node: '>=18.17.0'} - peerDependencies: - react: 19.1.0 - react-dom: 19.1.0 - - '@clerk/clerk-react@5.49.1': - resolution: {integrity: sha512-0yphUDJztg95eAARovx9NbgC5dWNVWhfBQ3klRKupA1hSB8+5VtkE4AugcUU7GMF9XK1jl0yrqMuOGp0U1BTqw==} - engines: {node: '>=18.17.0'} - deprecated: 'This package is no longer supported. Please use @clerk/react instead. See the upgrade guide for more info: https://clerk.com/docs/guides/development/upgrading/upgrade-guides/core-3' - peerDependencies: - react: 19.1.0 - react-dom: 19.1.0 - - '@clerk/elements@0.23.63': - resolution: {integrity: sha512-dJ2Fcn0QDaK1INlMsIRb2z6JMlI5l5hHP2V8a/uwHOXjuRRisVMg2S13FJxuGD9AEZcm/2HQBDLcmo+DJ1/LMA==} - engines: {node: '>=18.17.0'} - deprecated: 'This package is no longer supported. Please see the Core 3 release for more information: https://clerk.com/changelog/2026-03-03-core-3' - peerDependencies: - next: ^13.5.4 || ^14.0.3 || ^15 - react: 19.1.0 - react-dom: 19.1.0 - peerDependenciesMeta: - next: - optional: true - - '@clerk/localizations@3.25.5': - resolution: {integrity: sha512-CRksWw5kTnxYaCfwpfQw2t0YswPnP3PML/9SpZecZYOZVnvqVkl1VriMONhV7IXrMq1PuAIw5eurKagFdzEhpw==} - engines: {node: '>=18.17.0'} - - '@clerk/shared@3.27.1': - resolution: {integrity: sha512-xvlc1LktFvVGt7T25Obg5vDyhGh9pVK8X976k7oGsqaJ9SWCdKVKj4cFIXh5bo0o7HkvJKdbz/gRl9GWk+IyoQ==} - engines: {node: '>=18.17.0'} - peerDependencies: - react: 19.1.0 - react-dom: 19.1.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - - '@clerk/testing@1.13.30': - resolution: {integrity: sha512-OUnC1EFyDNiiCMr9CxvMsIXGDXVSpJ6KfcN3Q7c8UwdHzdjXuxxSXeiXN5drUZQd/jfyu7IocB9z+HjQhUon1A==} - engines: {node: '>=18.17.0'} - peerDependencies: - '@playwright/test': ^1 - cypress: ^13 || ^14 - peerDependenciesMeta: - '@playwright/test': - optional: true - cypress: - optional: true - - '@clerk/themes@2.4.21': - resolution: {integrity: sha512-nvahR5uOF/bSn34SiK4Zub2n2zn5AJWy+AAzKy0uZYNSl1cjgcZcmQ8CsB078jEeTDmXxKqUa6OMLtYMimH27A==} - engines: {node: '>=18.17.0'} - - '@clerk/types@4.101.12': - resolution: {integrity: sha512-ePXOla3B1qgPtV0AzrLx2PVC3s/lsjOSYnuIFAxaIlRNT2+eb/BjeoqtTOcezwbdQ00jQ2RvXahdfZRSEuvZ7A==} - engines: {node: '>=18.17.0'} - '@cloudflare/kv-asset-handler@0.4.0': resolution: {integrity: sha512-+tv3z+SPp+gqTIcImN9o0hqE9xyfQjI1XD9pL6NuKjua9B1y7mNYv0S9cP+QEbA4ppVgGZEmKOvHX5G5Ei1CVA==} engines: {node: '>=18.0.0'} @@ -6058,9 +6045,6 @@ packages: '@codemirror/view@6.38.2': resolution: {integrity: sha512-bTWAJxL6EOFLPzTx+O5P5xAO3gTqpatQ2b/ARQ8itfU/v2LlpS3pH2fkL0A3E/Fx8Y2St2KES7ZEV0sHTsSW/A==} - '@coinbase/wallet-sdk@4.3.0': - resolution: {integrity: sha512-T3+SNmiCw4HzDm4we9wCHCxlP0pqCiwKe4sOwPH3YAK2KSKjxPRydKu6UQJrdONFVLG7ujXvbd/6ZqmvJb8rkw==} - '@colors/colors@1.5.0': resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} @@ -6142,50 +6126,6 @@ packages: '@emnapi/runtime@1.7.1': resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} - '@emotion/babel-plugin@11.13.5': - resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} - - '@emotion/cache@11.11.0': - resolution: {integrity: sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==} - - '@emotion/hash@0.9.2': - resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} - - '@emotion/memoize@0.8.1': - resolution: {integrity: sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==} - - '@emotion/memoize@0.9.0': - resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} - - '@emotion/react@11.11.1': - resolution: {integrity: sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA==} - peerDependencies: - '@types/react': '*' - react: 19.1.0 - peerDependenciesMeta: - '@types/react': - optional: true - - '@emotion/serialize@1.3.3': - resolution: {integrity: sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==} - - '@emotion/sheet@1.4.0': - resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==} - - '@emotion/unitless@0.10.0': - resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==} - - '@emotion/use-insertion-effect-with-fallbacks@1.2.0': - resolution: {integrity: sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==} - peerDependencies: - react: 19.1.0 - - '@emotion/utils@1.4.2': - resolution: {integrity: sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==} - - '@emotion/weak-memoize@0.3.1': - resolution: {integrity: sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==} - '@esbuild-kit/core-utils@3.3.2': resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==} deprecated: 'Merged into tsx: https://tsx.is' @@ -7267,12 +7207,6 @@ packages: react: 19.1.0 react-dom: 19.1.0 - '@floating-ui/react@0.27.12': - resolution: {integrity: sha512-kKlWNrpIQxF1B/a2MZvE0/uyKby4960yjO91W7nVyNKmmfNi62xU9HCjL1M1eWzx/LFj/VPSwJVbwQk9Pq/68A==} - peerDependencies: - react: 19.1.0 - react-dom: 19.1.0 - '@floating-ui/react@0.27.16': resolution: {integrity: sha512-9O8N4SeG2z++TSM8QA/KTeKFBVCNEz/AGS7gWPJf6KFRzmRWixFRnCnkPHRDwSVZW6QPDO6uT0P2SpWNKCc9/g==} peerDependencies: @@ -7286,9 +7220,6 @@ packages: resolution: {integrity: sha512-1s+dIVi/pTMP4Aj4Mkg+4LoZ/+a0Kp6l9piPRxvpgEKm11b/eRiZgJwVytwAHeI/vtg2fuwcFExjtXOEfny/TA==} engines: {node: '>=24.0.0'} - '@formkit/auto-animate@0.8.4': - resolution: {integrity: sha512-DHHC01EJ1p70Q0z/ZFRBIY8NDnmfKccQoyoM84Tgb6omLMat6jivCdf272Y8k3nf4Lzdin/Y4R9q8uFtU0GbnA==} - '@fortawesome/fontawesome-common-types@6.7.2': resolution: {integrity: sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==} engines: {node: '>=6'} @@ -8094,127 +8025,64 @@ packages: resolution: {integrity: sha512-9T3nD5q51X1d4QYW6vouKW9hBSb2Tb/wB/2XoTr4oP5SCGtp3a7aTHHewQFylred1B21/Bhev6gy4x01FPBcbQ==} engines: {node: '>=18'} - '@next/env@15.5.9': - resolution: {integrity: sha512-4GlTZ+EJM7WaW2HEZcyU317tIQDjkQIyENDLxYJfSWlfqguN+dHkZgyQTV/7ykvobU7yEH5gKvreNrH4B6QgIg==} - '@next/env@16.1.1': resolution: {integrity: sha512-3oxyM97Sr2PqiVyMyrZUtrtM3jqqFxOQJVuKclDsgj/L728iZt/GyslkN4NwarledZATCenbk4Offjk1hQmaAA==} - '@next/swc-darwin-arm64@15.5.7': - resolution: {integrity: sha512-IZwtxCEpI91HVU/rAUOOobWSZv4P2DeTtNaCdHqLcTJU4wdNXgAySvKa/qJCgR5m6KI8UsKDXtO2B31jcaw1Yw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - '@next/swc-darwin-arm64@16.1.1': resolution: {integrity: sha512-JS3m42ifsVSJjSTzh27nW+Igfha3NdBOFScr9C80hHGrWx55pTrVL23RJbqir7k7/15SKlrLHhh/MQzqBBYrQA==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@15.5.7': - resolution: {integrity: sha512-UP6CaDBcqaCBuiq/gfCEJw7sPEoX1aIjZHnBWN9v9qYHQdMKvCKcAVs4OX1vIjeE+tC5EIuwDTVIoXpUes29lg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - '@next/swc-darwin-x64@16.1.1': resolution: {integrity: sha512-hbyKtrDGUkgkyQi1m1IyD3q4I/3m9ngr+V93z4oKHrPcmxwNL5iMWORvLSGAf2YujL+6HxgVvZuCYZfLfb4bGw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@15.5.7': - resolution: {integrity: sha512-NCslw3GrNIw7OgmRBxHtdWFQYhexoUCq+0oS2ccjyYLtcn1SzGzeM54jpTFonIMUjNbHmpKpziXnpxhSWLcmBA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - '@next/swc-linux-arm64-gnu@16.1.1': resolution: {integrity: sha512-/fvHet+EYckFvRLQ0jPHJCUI5/B56+2DpI1xDSvi80r/3Ez+Eaa2Yq4tJcRTaB1kqj/HrYKn8Yplm9bNoMJpwQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@15.5.7': - resolution: {integrity: sha512-nfymt+SE5cvtTrG9u1wdoxBr9bVB7mtKTcj0ltRn6gkP/2Nu1zM5ei8rwP9qKQP0Y//umK+TtkKgNtfboBxRrw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - '@next/swc-linux-arm64-musl@16.1.1': resolution: {integrity: sha512-MFHrgL4TXNQbBPzkKKur4Fb5ICEJa87HM7fczFs2+HWblM7mMLdco3dvyTI+QmLBU9xgns/EeeINSZD6Ar+oLg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@15.5.7': - resolution: {integrity: sha512-hvXcZvCaaEbCZcVzcY7E1uXN9xWZfFvkNHwbe/n4OkRhFWrs1J1QV+4U1BN06tXLdaS4DazEGXwgqnu/VMcmqw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - '@next/swc-linux-x64-gnu@16.1.1': resolution: {integrity: sha512-20bYDfgOQAPUkkKBnyP9PTuHiJGM7HzNBbuqmD0jiFVZ0aOldz+VnJhbxzjcSabYsnNjMPsE0cyzEudpYxsrUQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@15.5.7': - resolution: {integrity: sha512-4IUO539b8FmF0odY6/SqANJdgwn1xs1GkPO5doZugwZ3ETF6JUdckk7RGmsfSf7ws8Qb2YB5It33mvNL/0acqA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - '@next/swc-linux-x64-musl@16.1.1': resolution: {integrity: sha512-9pRbK3M4asAHQRkwaXwu601oPZHghuSC8IXNENgbBSyImHv/zY4K5udBusgdHkvJ/Tcr96jJwQYOll0qU8+fPA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@15.5.7': - resolution: {integrity: sha512-CpJVTkYI3ZajQkC5vajM7/ApKJUOlm6uP4BknM3XKvJ7VXAvCqSjSLmM0LKdYzn6nBJVSjdclx8nYJSa3xlTgQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - '@next/swc-win32-arm64-msvc@16.1.1': resolution: {integrity: sha512-bdfQkggaLgnmYrFkSQfsHfOhk/mCYmjnrbRCGgkMcoOBZ4n+TRRSLmT/CU5SATzlBJ9TpioUyBW/vWFXTqQRiA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@15.5.7': - resolution: {integrity: sha512-gMzgBX164I6DN+9/PGA+9dQiwmTkE4TloBNx8Kv9UiGARsr9Nba7IpcBRA1iTV9vwlYnrE3Uy6I7Aj6qLjQuqw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - '@next/swc-win32-x64-msvc@16.1.1': resolution: {integrity: sha512-Ncwbw2WJ57Al5OX0k4chM68DKhEPlrXBaSXDCi2kPi5f4d8b3ejr3RRJGfKBLrn2YJL5ezNS7w2TZLHSti8CMw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@noble/ciphers@1.3.0': - resolution: {integrity: sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==} - engines: {node: ^14.21.3 || >=16} + '@noble/ciphers@2.1.1': + resolution: {integrity: sha512-bysYuiVfhxNJuldNXlFEitTVdNnYUc+XNJZd7Qm2a5j1vZHgY+fazadNFWFaMK/2vye0JVlxV3gHmC0WDfAOQw==} + engines: {node: '>= 20.19.0'} - '@noble/curves@1.9.1': - resolution: {integrity: sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==} - engines: {node: ^14.21.3 || >=16} - - '@noble/curves@1.9.7': - resolution: {integrity: sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw==} - engines: {node: ^14.21.3 || >=16} - - '@noble/hashes@1.4.0': - resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} - engines: {node: '>= 16'} - - '@noble/hashes@1.8.0': - resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} - engines: {node: ^14.21.3 || >=16} + '@noble/hashes@2.0.1': + resolution: {integrity: sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw==} + engines: {node: '>= 20.19.0'} '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -8931,19 +8799,6 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-form@0.1.8': - resolution: {integrity: sha512-QM70k4Zwjttifr5a4sZFts9fn8FzHYvQ5PiB19O2HsYibaHSVt9fH9rzB0XZo/YcM+b7t/p7lYCT/F5eOeF5yQ==} - peerDependencies: - '@types/react': ^19 - '@types/react-dom': ^19 - react: 19.1.0 - react-dom: 19.1.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-icons@1.3.2': resolution: {integrity: sha512-fyQIhGDhzfc9pK2kH6Pl9c4BDJGfMkPqkyIgYDthyNYoNg3wVhoJMMh19WS4Up/1KMPFVpNsT2q3WmXn2N1m6g==} peerDependencies: @@ -9780,15 +9635,6 @@ packages: resolution: {integrity: sha512-trO//ypJBSt5xkewuol9LOykvDgHwUXq8R+yQVS+0CmpN3lYUtewHkb+At9RVGRhDMmJZY2oasaXDnhfurQ33w==} hasBin: true - '@scure/base@1.2.6': - resolution: {integrity: sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==} - - '@scure/bip32@1.7.0': - resolution: {integrity: sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==} - - '@scure/bip39@1.6.0': - resolution: {integrity: sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==} - '@sec-ant/readable-stream@0.4.1': resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} @@ -10470,9 +10316,6 @@ packages: '@speed-highlight/core@1.2.7': resolution: {integrity: sha512-0dxmVj4gxg3Jg879kvFS/msl4s9F3T9UXC1InxgOf7t5NvcPD97u/WTA5vL/IxWHMn7qSxBozqrnnE2wvl1m8g==} - '@stablelib/base64@1.0.1': - resolution: {integrity: sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==} - '@standard-schema/spec@1.0.0': resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} @@ -10492,10 +10335,6 @@ packages: peerDependencies: react: 19.1.0 - '@stripe/stripe-js@5.6.0': - resolution: {integrity: sha512-w8CEY73X/7tw2KKlL3iOk679V9bWseE4GzNz3zlaYxcTjmcmWOathRb0emgo/QQ3eoNzmq68+2Y2gxluAv3xGw==} - engines: {node: '>=12.16'} - '@swc/core-darwin-arm64@1.15.11': resolution: {integrity: sha512-QoIupRWVH8AF1TgxYyeA5nS18dtqMuxNwchjBIwJo3RdwLEFiJq6onOx9JAxHtuPwUkIVuU2Xbp+jCJ7Vzmgtg==} engines: {node: '>=10'} @@ -11485,15 +11324,6 @@ packages: engines: {node: '>=10.0.0'} deprecated: this version has critical issues, please update to the latest version - '@xstate/react@6.0.0': - resolution: {integrity: sha512-xXlLpFJxqLhhmecAXclBECgk+B4zYSrDTl8hTfPZBogkn82OHKbm9zJxox3Z/YXoOhAQhKFTRLMYGdlbhc6T9A==} - peerDependencies: - react: 19.1.0 - xstate: ^5.20.0 - peerDependenciesMeta: - xstate: - optional: true - '@xtuc/ieee754@1.2.0': resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} @@ -11512,34 +11342,6 @@ packages: '@zeit/schemas@2.36.0': resolution: {integrity: sha512-7kjMwcChYEzMKjeex9ZFXkt1AyNov9R5HZtjBKVsmVpw7pa7ZtlCGvCBC2vnnXctaYN+aRI61HjIqeetZW5ROg==} - '@zxcvbn-ts/core@3.0.4': - resolution: {integrity: sha512-aQeiT0F09FuJaAqNrxynlAwZ2mW/1MdXakKWNmGM1Qp/VaY6CnB/GfnMS2T8gB2231Esp1/maCWd8vTG4OuShw==} - - '@zxcvbn-ts/language-common@3.0.4': - resolution: {integrity: sha512-viSNNnRYtc7ULXzxrQIVUNwHAPSXRtoIwy/Tq4XQQdIknBzw4vz36lQLF6mvhMlTIlpjoN/Z1GFu/fwiAlUSsw==} - - abitype@1.1.0: - resolution: {integrity: sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A==} - peerDependencies: - typescript: '>=5.0.4' - zod: ^3.22.0 || ^4.0.0 - peerDependenciesMeta: - typescript: - optional: true - zod: - optional: true - - abitype@1.1.1: - resolution: {integrity: sha512-Loe5/6tAgsBukY95eGaPSDmQHIjRZYQq8PB1MpsNccDIK8WiV+Uw6WzaIXipvaxTEL2yEB0OpEaQv3gs8pkS9Q==} - peerDependencies: - typescript: '>=5.0.4' - zod: ^3.22.0 || ^4.0.0 - peerDependenciesMeta: - typescript: - optional: true - zod: - optional: true - abort-controller-x@0.4.3: resolution: {integrity: sha512-VtUwTNU8fpMwvWGn4xE93ywbogTYsuT+AUxAXOeelbXuQVIwNmC5YLeho9sH4vZ4ITW8414TTAOG1nW6uIVHCA==} @@ -11678,9 +11480,6 @@ packages: ajv@8.17.1: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} - alien-signals@2.0.6: - resolution: {integrity: sha512-P3TxJSe31bUHBiblg59oU1PpaWPtmxF9GhJ/cB7OkgJ0qN/ifFSKUI25/v8ZhsT+lIG6ac8DpTOplXxORX6F3Q==} - anser@1.4.10: resolution: {integrity: sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww==} @@ -11963,6 +11762,76 @@ packages: bcryptjs@2.4.3: resolution: {integrity: sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==} + better-auth@1.5.6: + resolution: {integrity: sha512-QSpJTqaT1XVfWRQe/fm3PgeuwOIlz1nWX/Dx7nsHStJ382bLzmDbQk2u7IT0IJ6wS5SRxfqEE1Ev9TXontgyAQ==} + peerDependencies: + '@lynx-js/react': '*' + '@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0 + '@sveltejs/kit': ^2.0.0 + '@tanstack/react-start': ^1.0.0 + '@tanstack/solid-start': ^1.0.0 + better-sqlite3: ^12.0.0 + drizzle-kit: '>=0.31.4' + drizzle-orm: '>=0.41.0' + mongodb: ^6.0.0 || ^7.0.0 + mysql2: ^3.0.0 + next: ^14.0.0 || ^15.0.0 || ^16.0.0 + pg: ^8.0.0 + prisma: ^5.0.0 || ^6.0.0 || ^7.0.0 + react: 19.1.0 + react-dom: 19.1.0 + solid-js: ^1.0.0 + svelte: ^4.0.0 || ^5.0.0 + vitest: ^2.0.0 || ^3.0.0 || ^4.0.0 + vue: ^3.0.0 + peerDependenciesMeta: + '@lynx-js/react': + optional: true + '@prisma/client': + optional: true + '@sveltejs/kit': + optional: true + '@tanstack/react-start': + optional: true + '@tanstack/solid-start': + optional: true + better-sqlite3: + optional: true + drizzle-kit: + optional: true + drizzle-orm: + optional: true + mongodb: + optional: true + mysql2: + optional: true + next: + optional: true + pg: + optional: true + prisma: + optional: true + react: + optional: true + react-dom: + optional: true + solid-js: + optional: true + svelte: + optional: true + vitest: + optional: true + vue: + optional: true + + better-call@1.3.2: + resolution: {integrity: sha512-4cZIfrerDsNTn3cm+MhLbUePN0gdwkhSXEuG7r/zuQ8c/H7iU0/jSK5TD3FW7U0MgKHce/8jGpPYNO4Ve+4NBw==} + peerDependencies: + zod: ^4.0.0 + peerDependenciesMeta: + zod: + optional: true + better-opn@3.0.2: resolution: {integrity: sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==} engines: {node: '>=12.0.0'} @@ -12050,9 +11919,6 @@ packages: browser-resolve@2.0.0: resolution: {integrity: sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==} - browser-tabs-lock@1.3.0: - resolution: {integrity: sha512-g6nHaobTiT0eMZ7jh16YpD2kcjAp+PInbiVq3M1x6KKaEIVhT4v9oURNIpZLOZ3LQbQ3XYfNhMAb/9hzNLIWrw==} - browserify-aes@1.2.0: resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} @@ -12184,9 +12050,6 @@ packages: caniuse-lite@1.0.30001769: resolution: {integrity: sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==} - caniuse-lite@1.0.30001779: - resolution: {integrity: sha512-U5og2PN7V4DMgF50YPNtnZJGWVLFjjsN3zb6uMT5VGYIewieDj1upwfuVNXf4Kor+89c3iCRJnSzMD5LmTvsfA==} - canvas-confetti@1.9.3: resolution: {integrity: sha512-rFfTURMvmVEX1gyXFgn5QMn81bYk70qa0HLzcIOSVEyl57n6o9ItHeBtUSWdvKAPY0xlvBHno4/v3QPrT83q9g==} @@ -12379,10 +12242,6 @@ packages: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} - clsx@1.2.1: - resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} - engines: {node: '>=6'} - clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} @@ -12532,9 +12391,6 @@ packages: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} - convert-source-map@1.9.0: - resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} - convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} @@ -12563,15 +12419,9 @@ packages: copy-anything@2.0.6: resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} - copy-to-clipboard@3.3.3: - resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} - core-js-compat@3.48.0: resolution: {integrity: sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==} - core-js@3.41.0: - resolution: {integrity: sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==} - core-js@3.47.0: resolution: {integrity: sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg==} @@ -12633,9 +12483,6 @@ packages: resolution: {integrity: sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==} engines: {node: '>= 0.10'} - crypto-js@4.2.0: - resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} - css-select@5.2.2: resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} @@ -13100,10 +12947,6 @@ packages: resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} engines: {node: '>=12'} - dotenv@17.2.2: - resolution: {integrity: sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==} - engines: {node: '>=12'} - dotenv@17.2.3: resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==} engines: {node: '>=12'} @@ -13784,9 +13627,6 @@ packages: fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} - fast-sha256@1.3.0: - resolution: {integrity: sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==} - fast-uri@3.1.0: resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} @@ -13804,10 +13644,6 @@ packages: resolution: {integrity: sha512-Z7Fh2nVQSb2d+poDViM063ix2ZGt9jmY1nWhPfHBOK2Hgnb/OW3P4Et3P/81SEej0J7QbWtJqxO05h8QYfK7LQ==} hasBin: true - fastest-levenshtein@1.0.16: - resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} - engines: {node: '>= 4.9.1'} - fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} @@ -13911,9 +13747,6 @@ packages: resolution: {integrity: sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==} engines: {node: '>= 18.0.0'} - find-root@1.1.0: - resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} - find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -14718,11 +14551,6 @@ packages: isomorphic.js@0.2.5: resolution: {integrity: sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==} - isows@1.0.7: - resolution: {integrity: sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==} - peerDependencies: - ws: '*' - istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} @@ -14830,10 +14658,6 @@ packages: js-base64@3.7.8: resolution: {integrity: sha512-hNngCeKxIUQiEUN3GPJOkz4wF/YvdUdbNL9hsBcMQTkKzboD7T/q3OYOuuPZLUE6dBxSGpwhk5mwuDud7JVAow==} - js-cookie@3.0.5: - resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} - engines: {node: '>=14'} - js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -14951,8 +14775,8 @@ packages: kolorist@1.8.0: resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} - kysely@0.28.8: - resolution: {integrity: sha512-QUOgl5ZrS9IRuhq5FvOKFSsD/3+IA6MLE81/bOOTRA/YQpKDza2sFdN5g6JCB9BOpqMJDGefLCQ9F12hRS13TA==} + kysely@0.28.15: + resolution: {integrity: sha512-r2clcf7HLWvDXaVUEvQymXJY4i3bSOIV3xsL/Upy3ZfSv5HeKsk9tsqbBptLvth5qHEIhxeHTA2jNLyQABkLBA==} engines: {node: '>=20.0.0'} lan-network@0.1.7: @@ -15856,6 +15680,10 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + nanostores@1.2.0: + resolution: {integrity: sha512-F0wCzbsH80G7XXo0Jd9/AVQC7ouWY6idUCTnMwW5t/Rv9W8qmO6endavDwg7TNp5GbugwSukFMVZqzPSrSMndg==} + engines: {node: ^20.0.0 || >=22.0.0} + napi-build-utils@2.0.0: resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} @@ -15893,27 +15721,6 @@ packages: resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} engines: {node: '>= 0.4.0'} - next@15.5.9: - resolution: {integrity: sha512-agNLK89seZEtC5zUHwtut0+tNrc0Xw4FT/Dg+B/VLEo9pAcS9rtTKpek3V6kVcVwsB2YlqMaHdfZL4eLEVYuCg==} - engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - '@playwright/test': ^1.51.1 - babel-plugin-react-compiler: '*' - react: 19.1.0 - react-dom: 19.1.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - '@playwright/test': - optional: true - babel-plugin-react-compiler: - optional: true - sass: - optional: true - next@16.1.1: resolution: {integrity: sha512-QI+T7xrxt1pF6SQ/JYFz95ro/mg/1Znk5vBebsWwbpejj1T0A23hO7GYEaVac9QUOT2BIMiuzm0L99ooq7k0/w==} engines: {node: '>=20.9.0'} @@ -16204,22 +16011,6 @@ packages: outvariant@1.4.3: resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} - ox@0.6.9: - resolution: {integrity: sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug==} - peerDependencies: - typescript: '>=5.4.0' - peerDependenciesMeta: - typescript: - optional: true - - ox@0.9.6: - resolution: {integrity: sha512-8SuCbHPvv2eZLYXrNmC0EC12rdzXQLdhnOMlHDW2wiCPLxBrOOJwX5L5E61by+UjTPOryqQiRSnjIKCI+GykKg==} - peerDependencies: - typescript: '>=5.4.0' - peerDependenciesMeta: - typescript: - optional: true - p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -16682,9 +16473,6 @@ packages: posthog-js@1.297.0: resolution: {integrity: sha512-+kHHe3oTRLPBokks5E2pojDfx0yAzkXLeN8BCfVY9kZ7eaaHuezpFb4DQ7i4hzI5nMFDe5qWotsUO73/GR6lmw==} - preact@10.24.2: - resolution: {integrity: sha512-1cSoF0aCC8uaARATfrlz4VCBqE8LwZwRfLgkxJOQwAlQt6ayTmi0D9OF7nXid1POI5SZidFuG9CnlXbDfLqY/Q==} - preact@10.27.2: resolution: {integrity: sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==} @@ -16862,11 +16650,6 @@ packages: resolution: {integrity: sha512-Uu7ii+FQy4Qf82G4xu7ShHhjhGahEpCWc3x8UavY3CTcWV+ufmmCtwkr7ZKsX42jdL0kr1B5FKUeqJvAn51jzQ==} hasBin: true - qrcode.react@4.2.0: - resolution: {integrity: sha512-QpgqWi8rD9DsS9EP3z7BT+5lY5SFhsqGjpgW5DY/i3mK4M9DTBNz3ErMi8BWYEfI3L0d8GIbGmcdFAS1uIRGjA==} - peerDependencies: - react: 19.1.0 - qs@6.14.1: resolution: {integrity: sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==} engines: {node: '>=0.6'} @@ -17187,9 +16970,6 @@ packages: regenerator-runtime@0.13.11: resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} - regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - regex-recursion@6.0.2: resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==} @@ -17370,6 +17150,9 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + rou3@0.7.12: + resolution: {integrity: sha512-iFE4hLDuloSWcD7mjdCDhx2bKcIsYbtOTpfH5MHHLSKMOUyjqQXTeZVa289uuwEGEKFoE/BAPbhaU4B774nceg==} + roughjs@4.6.6: resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==} @@ -17538,6 +17321,9 @@ packages: server-only@0.0.1: resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==} + set-cookie-parser@3.1.0: + resolution: {integrity: sha512-kjnC1DXBHcxaOaOXBHBeRtltsDG2nUiUni+jP92M9gYdW12rsmx92UsfpH7o5tDRs7I1ZZPSQJQGv3UaRfCiuw==} + set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} @@ -17738,9 +17524,6 @@ packages: resolution: {integrity: sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==} engines: {node: '>=6'} - standardwebhooks@1.0.0: - resolution: {integrity: sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg==} - state-local@1.0.7: resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==} @@ -17892,9 +17675,6 @@ packages: babel-plugin-macros: optional: true - stylis@4.2.0: - resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} - stylis@4.3.6: resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} @@ -18125,9 +17905,6 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - toggle-selection@1.0.6: - resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} - toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} @@ -18599,15 +18376,6 @@ packages: '@types/react': optional: true - use-isomorphic-layout-effect@1.2.1: - resolution: {integrity: sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==} - peerDependencies: - '@types/react': '*' - react: 19.1.0 - peerDependenciesMeta: - '@types/react': - optional: true - use-latest-callback@0.2.6: resolution: {integrity: sha512-FvRG9i1HSo0wagmX63Vrm8SnlUU3LMM3WyZkQ76RnslpBrX694AdG4A0zQBx2B3ZifFA0yv/BaEHGBnEax5rZg==} peerDependencies: @@ -18691,14 +18459,6 @@ packages: victory-vendor@36.9.2: resolution: {integrity: sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==} - viem@2.37.8: - resolution: {integrity: sha512-mL+5yvCQbRIR6QvngDQMfEiZTfNWfd+/QL5yFaOoYbpH3b1Q2ddwF7YG2eI2AcYSh9LE1gtUkbzZLFUAVyj4oQ==} - peerDependencies: - typescript: '>=5.0.4' - peerDependenciesMeta: - typescript: - optional: true - vite-node@1.6.1: resolution: {integrity: sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA==} engines: {node: ^18.0.0 || >=20.0.0} @@ -19199,18 +18959,6 @@ packages: utf-8-validate: optional: true - ws@8.18.3: - resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - ws@8.19.0: resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} engines: {node: '>=10.0.0'} @@ -19263,9 +19011,6 @@ packages: resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} engines: {node: '>=8.0'} - xstate@5.21.0: - resolution: {integrity: sha512-y4wmqxjyAa0tgz4k3m/MgTF1kDOahE5+xLfWt5eh1sk+43DatLhKlI8lQDJZpvihZavjbD3TUgy2PRMphhhqgQ==} - xtend@4.0.2: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} @@ -19387,6 +19132,9 @@ packages: zod@4.1.13: resolution: {integrity: sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==} + zod@4.3.6: + resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + zustand@4.5.7: resolution: {integrity: sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==} engines: {node: '>=12.7.0'} @@ -19402,24 +19150,6 @@ packages: react: optional: true - zustand@5.0.3: - resolution: {integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==} - engines: {node: '>=12.20.0'} - peerDependencies: - '@types/react': ^19 - immer: '>=9.0.6' - react: 19.1.0 - use-sync-external-store: '>=1.2.0' - peerDependenciesMeta: - '@types/react': - optional: true - immer: - optional: true - react: - optional: true - use-sync-external-store: - optional: true - zustand@5.0.8: resolution: {integrity: sha512-gyPKpIaxY9XcO2vSMrLbiER7QMAMGOQZVRdJ6Zi782jkbzZygq5GI9nG8g+sMgitRtndwaBSl7uiqC49o1SSiw==} engines: {node: '>=12.20.0'} @@ -19455,8 +19185,6 @@ snapshots: '@adobe/css-tools@4.3.3': optional: true - '@adraffy/ens-normalize@1.11.1': {} - '@agentclientprotocol/sdk@0.16.1(zod@3.25.76)': dependencies: zod: 3.25.76 @@ -19484,11 +19212,11 @@ snapshots: '@ai-sdk/provider-utils': 1.0.20(zod@3.25.76) zod: 3.25.76 - '@ai-sdk/openai@0.0.66(zod@4.1.13)': + '@ai-sdk/openai@0.0.66(zod@4.3.6)': dependencies: '@ai-sdk/provider': 0.0.24 - '@ai-sdk/provider-utils': 1.0.20(zod@4.1.13) - zod: 4.1.13 + '@ai-sdk/provider-utils': 1.0.20(zod@4.3.6) + zod: 4.3.6 '@ai-sdk/openai@3.0.30(zod@4.1.13)': dependencies: @@ -19505,14 +19233,14 @@ snapshots: optionalDependencies: zod: 3.25.76 - '@ai-sdk/provider-utils@1.0.20(zod@4.1.13)': + '@ai-sdk/provider-utils@1.0.20(zod@4.3.6)': dependencies: '@ai-sdk/provider': 0.0.24 eventsource-parser: 1.1.2 nanoid: 3.3.6 secure-json-parse: 2.7.0 optionalDependencies: - zod: 4.1.13 + zod: 4.3.6 '@ai-sdk/provider-utils@2.2.8(zod@3.25.76)': dependencies: @@ -19528,6 +19256,13 @@ snapshots: secure-json-parse: 2.7.0 zod: 4.1.13 + '@ai-sdk/provider-utils@2.2.8(zod@4.3.6)': + dependencies: + '@ai-sdk/provider': 1.1.3 + nanoid: 3.3.11 + secure-json-parse: 2.7.0 + zod: 4.3.6 + '@ai-sdk/provider-utils@4.0.15(zod@4.1.13)': dependencies: '@ai-sdk/provider': 3.0.8 @@ -19567,6 +19302,16 @@ snapshots: optionalDependencies: zod: 4.1.13 + '@ai-sdk/react@1.2.12(react@19.1.0)(zod@4.3.6)': + dependencies: + '@ai-sdk/provider-utils': 2.2.8(zod@4.3.6) + '@ai-sdk/ui-utils': 1.2.11(zod@4.3.6) + react: 19.1.0 + swr: 2.3.4(react@19.1.0) + throttleit: 2.1.0 + optionalDependencies: + zod: 4.3.6 + '@ai-sdk/ui-utils@1.2.11(zod@3.25.76)': dependencies: '@ai-sdk/provider': 1.1.3 @@ -19581,6 +19326,13 @@ snapshots: zod: 4.1.13 zod-to-json-schema: 3.25.1(zod@4.1.13) + '@ai-sdk/ui-utils@1.2.11(zod@4.3.6)': + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@4.3.6) + zod: 4.3.6 + zod-to-json-schema: 3.25.1(zod@4.3.6) + '@alloc/quick-lru@5.2.0': {} '@antfu/install-pkg@1.1.0': @@ -21132,25 +20884,59 @@ snapshots: '@bare-ts/lib': 0.6.0 commander: 11.1.0 - '@base-org/account@2.0.1(@types/react@19.2.13)(react@19.1.0)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.1.0))(zod@3.25.76)': + '@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0)': dependencies: - '@noble/hashes': 1.4.0 - clsx: 1.2.1 - eventemitter3: 5.0.1 - idb-keyval: 6.2.1 - ox: 0.6.9(typescript@5.9.3)(zod@3.25.76) - preact: 10.24.2 - viem: 2.37.8(typescript@5.9.3)(zod@3.25.76) - zustand: 5.0.3(@types/react@19.2.13)(react@19.1.0)(use-sync-external-store@1.6.0(react@19.1.0)) - transitivePeerDependencies: - - '@types/react' - - bufferutil - - immer - - react - - typescript - - use-sync-external-store - - utf-8-validate - - zod + '@better-auth/utils': 0.3.1 + '@better-fetch/fetch': 1.1.21 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/semantic-conventions': 1.40.0 + '@standard-schema/spec': 1.1.0 + better-call: 1.3.2(zod@4.3.6) + jose: 6.1.3 + kysely: 0.28.15 + nanostores: 1.2.0 + zod: 4.3.6 + optionalDependencies: + '@cloudflare/workers-types': 4.20251014.0 + + '@better-auth/drizzle-adapter@1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.3.1)(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.15)(pg@8.17.2)(sql.js@1.13.0))': + dependencies: + '@better-auth/core': 1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0) + '@better-auth/utils': 0.3.1 + optionalDependencies: + drizzle-orm: 0.44.6(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.15)(pg@8.17.2)(sql.js@1.13.0) + + '@better-auth/kysely-adapter@1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.3.1)(kysely@0.28.15)': + dependencies: + '@better-auth/core': 1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0) + '@better-auth/utils': 0.3.1 + optionalDependencies: + kysely: 0.28.15 + + '@better-auth/memory-adapter@1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.3.1)': + dependencies: + '@better-auth/core': 1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0) + '@better-auth/utils': 0.3.1 + + '@better-auth/mongo-adapter@1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.3.1)': + dependencies: + '@better-auth/core': 1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0) + '@better-auth/utils': 0.3.1 + + '@better-auth/prisma-adapter@1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.3.1)': + dependencies: + '@better-auth/core': 1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0) + '@better-auth/utils': 0.3.1 + + '@better-auth/telemetry@1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))': + dependencies: + '@better-auth/core': 1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0) + '@better-auth/utils': 0.3.1 + '@better-fetch/fetch': 1.1.21 + + '@better-auth/utils@0.3.1': {} + + '@better-fetch/fetch@1.1.21': {} '@biomejs/biome@2.3.11': optionalDependencies: @@ -21250,129 +21036,6 @@ snapshots: '@chevrotain/utils@11.0.3': {} - '@clerk/backend@2.29.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': - dependencies: - '@clerk/shared': 3.27.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@clerk/types': 4.101.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - standardwebhooks: 1.0.0 - tslib: 2.8.1 - transitivePeerDependencies: - - react - - react-dom - - '@clerk/clerk-js@5.97.0(@types/react@19.2.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.1.0))(zod@3.25.76)': - dependencies: - '@base-org/account': 2.0.1(@types/react@19.2.13)(react@19.1.0)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.1.0))(zod@3.25.76) - '@clerk/localizations': 3.25.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@clerk/shared': 3.27.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@clerk/types': 4.101.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@coinbase/wallet-sdk': 4.3.0 - '@emotion/cache': 11.11.0 - '@emotion/react': 11.11.1(@types/react@19.2.13)(react@19.1.0) - '@floating-ui/react': 0.27.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@floating-ui/react-dom': 2.1.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@formkit/auto-animate': 0.8.4 - '@stripe/stripe-js': 5.6.0 - '@swc/helpers': 0.5.17 - '@zxcvbn-ts/core': 3.0.4 - '@zxcvbn-ts/language-common': 3.0.4 - alien-signals: 2.0.6 - browser-tabs-lock: 1.3.0 - copy-to-clipboard: 3.3.3 - core-js: 3.41.0 - crypto-js: 4.2.0 - dequal: 2.0.3 - input-otp: 1.4.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - qrcode.react: 4.2.0(react@19.1.0) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - regenerator-runtime: 0.14.1 - swr: 2.3.4(react@19.1.0) - transitivePeerDependencies: - - '@types/react' - - bufferutil - - immer - - supports-color - - typescript - - use-sync-external-store - - utf-8-validate - - zod - - '@clerk/clerk-react@5.49.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': - dependencies: - '@clerk/shared': 3.27.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@clerk/types': 4.101.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - tslib: 2.8.1 - - '@clerk/elements@0.23.63(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(next@15.5.9(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.57.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.93.2))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': - dependencies: - '@clerk/clerk-react': 5.49.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@clerk/shared': 3.27.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@clerk/types': 4.101.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-form': 0.1.8(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.13)(react@19.1.0) - '@xstate/react': 6.0.0(@types/react@19.2.13)(react@19.1.0)(xstate@5.21.0) - client-only: 0.0.1 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - tslib: 2.8.1 - type-fest: 4.41.0 - xstate: 5.21.0 - optionalDependencies: - next: 15.5.9(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.57.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.93.2) - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' - - '@clerk/localizations@3.25.5(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': - dependencies: - '@clerk/types': 4.101.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - transitivePeerDependencies: - - react - - react-dom - - '@clerk/shared@3.27.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': - dependencies: - '@clerk/types': 4.101.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - dequal: 2.0.3 - glob-to-regexp: 0.4.1 - js-cookie: 3.0.5 - std-env: 3.9.0 - swr: 2.3.4(react@19.1.0) - optionalDependencies: - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - - '@clerk/testing@1.13.30(@playwright/test@1.57.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': - dependencies: - '@clerk/backend': 2.29.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@clerk/shared': 3.27.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@clerk/types': 4.101.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - dotenv: 17.2.2 - optionalDependencies: - '@playwright/test': 1.57.0 - transitivePeerDependencies: - - react - - react-dom - - '@clerk/themes@2.4.21(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': - dependencies: - '@clerk/types': 4.101.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - tslib: 2.8.1 - transitivePeerDependencies: - - react - - react-dom - - '@clerk/types@4.101.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': - dependencies: - '@clerk/shared': 3.27.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - transitivePeerDependencies: - - react - - react-dom - '@cloudflare/kv-asset-handler@0.4.0': dependencies: mime: 3.0.0 @@ -21476,13 +21139,6 @@ snapshots: style-mod: 4.1.3 w3c-keyname: 2.2.8 - '@coinbase/wallet-sdk@4.3.0': - dependencies: - '@noble/hashes': 1.8.0 - clsx: 1.2.1 - eventemitter3: 5.0.1 - preact: 10.27.2 - '@colors/colors@1.5.0': optional: true @@ -21591,72 +21247,6 @@ snapshots: tslib: 2.8.1 optional: true - '@emotion/babel-plugin@11.13.5': - dependencies: - '@babel/helper-module-imports': 7.28.6 - '@babel/runtime': 7.29.2 - '@emotion/hash': 0.9.2 - '@emotion/memoize': 0.9.0 - '@emotion/serialize': 1.3.3 - babel-plugin-macros: 3.1.0 - convert-source-map: 1.9.0 - escape-string-regexp: 4.0.0 - find-root: 1.1.0 - source-map: 0.5.7 - stylis: 4.2.0 - transitivePeerDependencies: - - supports-color - - '@emotion/cache@11.11.0': - dependencies: - '@emotion/memoize': 0.8.1 - '@emotion/sheet': 1.4.0 - '@emotion/utils': 1.4.2 - '@emotion/weak-memoize': 0.3.1 - stylis: 4.2.0 - - '@emotion/hash@0.9.2': {} - - '@emotion/memoize@0.8.1': {} - - '@emotion/memoize@0.9.0': {} - - '@emotion/react@11.11.1(@types/react@19.2.13)(react@19.1.0)': - dependencies: - '@babel/runtime': 7.29.2 - '@emotion/babel-plugin': 11.13.5 - '@emotion/cache': 11.11.0 - '@emotion/serialize': 1.3.3 - '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.1.0) - '@emotion/utils': 1.4.2 - '@emotion/weak-memoize': 0.3.1 - hoist-non-react-statics: 3.3.2 - react: 19.1.0 - optionalDependencies: - '@types/react': 19.2.13 - transitivePeerDependencies: - - supports-color - - '@emotion/serialize@1.3.3': - dependencies: - '@emotion/hash': 0.9.2 - '@emotion/memoize': 0.9.0 - '@emotion/unitless': 0.10.0 - '@emotion/utils': 1.4.2 - csstype: 3.2.3 - - '@emotion/sheet@1.4.0': {} - - '@emotion/unitless@0.10.0': {} - - '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@19.1.0)': - dependencies: - react: 19.1.0 - - '@emotion/utils@1.4.2': {} - - '@emotion/weak-memoize@0.3.1': {} - '@esbuild-kit/core-utils@3.3.2': dependencies: esbuild: 0.18.20 @@ -22555,14 +22145,6 @@ snapshots: react-dom: 19.1.0(react@19.1.0) tabbable: 6.3.0 - '@floating-ui/react@0.27.12(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': - dependencies: - '@floating-ui/react-dom': 2.1.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@floating-ui/utils': 0.2.10 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - tabbable: 6.3.0 - '@floating-ui/react@0.27.16(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@floating-ui/react-dom': 2.1.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -22575,8 +22157,6 @@ snapshots: '@fly/sprites@0.0.1': {} - '@formkit/auto-animate@0.8.4': {} - '@fortawesome/fontawesome-common-types@6.7.2': {} '@fortawesome/fontawesome-common-types@7.1.0': {} @@ -23765,7 +23345,7 @@ snapshots: '@modelcontextprotocol/sdk@1.25.3(hono@4.11.9)(zod@3.25.76)': dependencies: - '@hono/node-server': 1.19.12(hono@4.11.9) + '@hono/node-server': 1.19.9(hono@4.11.9) ajv: 8.17.1 ajv-formats: 3.0.1(ajv@8.17.1) content-type: 1.0.5 @@ -23787,7 +23367,7 @@ snapshots: '@modelcontextprotocol/sdk@1.25.3(hono@4.11.9)(zod@4.1.13)': dependencies: - '@hono/node-server': 1.19.12(hono@4.11.9) + '@hono/node-server': 1.19.9(hono@4.11.9) ajv: 8.17.1 ajv-formats: 3.0.1(ajv@8.17.1) content-type: 1.0.5 @@ -23850,72 +23430,35 @@ snapshots: '@neophi/sieve-cache@1.5.0': {} - '@next/env@15.5.9': - optional: true - '@next/env@16.1.1': {} - '@next/swc-darwin-arm64@15.5.7': - optional: true - '@next/swc-darwin-arm64@16.1.1': optional: true - '@next/swc-darwin-x64@15.5.7': - optional: true - '@next/swc-darwin-x64@16.1.1': optional: true - '@next/swc-linux-arm64-gnu@15.5.7': - optional: true - '@next/swc-linux-arm64-gnu@16.1.1': optional: true - '@next/swc-linux-arm64-musl@15.5.7': - optional: true - '@next/swc-linux-arm64-musl@16.1.1': optional: true - '@next/swc-linux-x64-gnu@15.5.7': - optional: true - '@next/swc-linux-x64-gnu@16.1.1': optional: true - '@next/swc-linux-x64-musl@15.5.7': - optional: true - '@next/swc-linux-x64-musl@16.1.1': optional: true - '@next/swc-win32-arm64-msvc@15.5.7': - optional: true - '@next/swc-win32-arm64-msvc@16.1.1': optional: true - '@next/swc-win32-x64-msvc@15.5.7': - optional: true - '@next/swc-win32-x64-msvc@16.1.1': optional: true - '@noble/ciphers@1.3.0': {} - - '@noble/curves@1.9.1': - dependencies: - '@noble/hashes': 1.8.0 - - '@noble/curves@1.9.7': - dependencies: - '@noble/hashes': 1.8.0 - - '@noble/hashes@1.4.0': {} + '@noble/ciphers@2.1.1': {} - '@noble/hashes@1.8.0': {} + '@noble/hashes@2.0.1': {} '@nodelib/fs.scandir@2.1.5': dependencies: @@ -24735,20 +24278,6 @@ snapshots: '@types/react': 19.2.13 '@types/react-dom': 19.2.3(@types/react@19.2.13) - '@radix-ui/react-form@0.1.8(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.13)(react@19.1.0) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.13)(react@19.1.0) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.13)(react@19.1.0) - '@radix-ui/react-label': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - optionalDependencies: - '@types/react': 19.2.13 - '@types/react-dom': 19.2.3(@types/react@19.2.13) - '@radix-ui/react-icons@1.3.2(react@19.1.0)': dependencies: react: 19.1.0 @@ -25884,19 +25413,6 @@ snapshots: '@sandbox-agent/cli-win32-x64': 0.4.2 optional: true - '@scure/base@1.2.6': {} - - '@scure/bip32@1.7.0': - dependencies: - '@noble/curves': 1.9.7 - '@noble/hashes': 1.8.0 - '@scure/base': 1.2.6 - - '@scure/bip39@1.6.0': - dependencies: - '@noble/hashes': 1.8.0 - '@scure/base': 1.2.6 - '@sec-ant/readable-stream@0.4.1': {} '@secure-exec/core@0.2.1': @@ -26872,8 +26388,6 @@ snapshots: '@speed-highlight/core@1.2.7': {} - '@stablelib/base64@1.0.1': {} - '@standard-schema/spec@1.0.0': {} '@standard-schema/spec@1.1.0': {} @@ -26891,8 +26405,6 @@ snapshots: transitivePeerDependencies: - typescript - '@stripe/stripe-js@5.6.0': {} - '@swc/core-darwin-arm64@1.15.11': optional: true @@ -27494,7 +27006,7 @@ snapshots: '@types/pg@8.16.0': dependencies: - '@types/node': 22.19.15 + '@types/node': 20.19.13 pg-protocol: 1.11.0 pg-types: 2.2.0 @@ -28216,16 +27728,6 @@ snapshots: '@xmldom/xmldom@0.8.11': {} - '@xstate/react@6.0.0(@types/react@19.2.13)(react@19.1.0)(xstate@5.21.0)': - dependencies: - react: 19.1.0 - use-isomorphic-layout-effect: 1.2.1(@types/react@19.2.13)(react@19.1.0) - use-sync-external-store: 1.6.0(react@19.1.0) - optionalDependencies: - xstate: 5.21.0 - transitivePeerDependencies: - - '@types/react' - '@xtuc/ieee754@1.2.0': optional: true @@ -28257,22 +27759,6 @@ snapshots: '@zeit/schemas@2.36.0': {} - '@zxcvbn-ts/core@3.0.4': - dependencies: - fastest-levenshtein: 1.0.16 - - '@zxcvbn-ts/language-common@3.0.4': {} - - abitype@1.1.0(typescript@5.9.3)(zod@3.25.76): - optionalDependencies: - typescript: 5.9.3 - zod: 3.25.76 - - abitype@1.1.1(typescript@5.9.3)(zod@3.25.76): - optionalDependencies: - typescript: 5.9.3 - zod: 3.25.76 - abort-controller-x@0.4.3: {} abort-controller@3.0.0: @@ -28306,7 +27792,7 @@ snapshots: acorn-walk@8.3.4: dependencies: - acorn: 8.15.0 + acorn: 8.16.0 acorn@8.14.0: {} @@ -28320,7 +27806,7 @@ snapshots: transitivePeerDependencies: - zod - actor-core@0.6.3(eventsource@3.0.7)(ws@8.18.3): + actor-core@0.6.3(eventsource@3.0.7)(ws@8.19.0): dependencies: cbor-x: 1.6.0 hono: 4.11.9 @@ -28329,7 +27815,7 @@ snapshots: zod: 3.25.76 optionalDependencies: eventsource: 3.0.7 - ws: 8.18.3 + ws: 8.19.0 agent-base@6.0.2: dependencies: @@ -28367,6 +27853,18 @@ snapshots: optionalDependencies: react: 19.1.0 + ai@4.3.19(react@19.1.0)(zod@4.3.6): + dependencies: + '@ai-sdk/provider': 1.1.3 + '@ai-sdk/provider-utils': 2.2.8(zod@4.3.6) + '@ai-sdk/react': 1.2.12(react@19.1.0)(zod@4.3.6) + '@ai-sdk/ui-utils': 1.2.11(zod@4.3.6) + '@opentelemetry/api': 1.9.0 + jsondiffpatch: 0.6.0 + zod: 4.3.6 + optionalDependencies: + react: 19.1.0 + ai@6.0.93(zod@4.1.13): dependencies: '@ai-sdk/gateway': 3.0.51(zod@4.1.13) @@ -28427,8 +27925,6 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - alien-signals@2.0.6: {} - anser@1.4.10: {} ansi-align@3.0.1: @@ -28719,6 +28215,7 @@ snapshots: '@babel/runtime': 7.29.2 cosmiconfig: 7.1.0 resolve: 1.22.11 + optional: true babel-plugin-polyfill-corejs2@0.4.16(@babel/core@7.29.0): dependencies: @@ -28847,6 +28344,47 @@ snapshots: bcryptjs@2.4.3: {} + better-auth@1.5.6(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-sqlite3@12.8.0)(drizzle-kit@0.31.5)(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.15)(pg@8.17.2)(sql.js@1.13.0))(next@16.1.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.57.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.93.2))(pg@8.17.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@20.19.13)(jiti@1.21.7)(less@4.4.1)(lightningcss@1.32.0)(msw@2.12.10(@types/node@20.19.13)(typescript@5.9.3))(sass@1.93.2)(stylus@0.62.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)): + dependencies: + '@better-auth/core': 1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0) + '@better-auth/drizzle-adapter': 1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.3.1)(drizzle-orm@0.44.6(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.15)(pg@8.17.2)(sql.js@1.13.0)) + '@better-auth/kysely-adapter': 1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.3.1)(kysely@0.28.15) + '@better-auth/memory-adapter': 1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.3.1) + '@better-auth/mongo-adapter': 1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.3.1) + '@better-auth/prisma-adapter': 1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.3.1) + '@better-auth/telemetry': 1.5.6(@better-auth/core@1.5.6(@better-auth/utils@0.3.1)(@better-fetch/fetch@1.1.21)(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(better-call@1.3.2(zod@3.25.76))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0)) + '@better-auth/utils': 0.3.1 + '@better-fetch/fetch': 1.1.21 + '@noble/ciphers': 2.1.1 + '@noble/hashes': 2.0.1 + better-call: 1.3.2(zod@4.3.6) + defu: 6.1.4 + jose: 6.1.3 + kysely: 0.28.15 + nanostores: 1.2.0 + zod: 4.3.6 + optionalDependencies: + better-sqlite3: 12.8.0 + drizzle-kit: 0.31.5 + drizzle-orm: 0.44.6(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.15)(pg@8.17.2)(sql.js@1.13.0) + next: 16.1.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.57.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.93.2) + pg: 8.17.2 + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@20.19.13)(jiti@1.21.7)(less@4.4.1)(lightningcss@1.32.0)(msw@2.12.10(@types/node@20.19.13)(typescript@5.9.3))(sass@1.93.2)(stylus@0.62.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) + transitivePeerDependencies: + - '@cloudflare/workers-types' + - '@opentelemetry/api' + + better-call@1.3.2(zod@4.3.6): + dependencies: + '@better-auth/utils': 0.3.1 + '@better-fetch/fetch': 1.1.21 + rou3: 0.7.12 + set-cookie-parser: 3.1.0 + optionalDependencies: + zod: 4.3.6 + better-opn@3.0.2: dependencies: open: 8.4.2 @@ -28957,10 +28495,6 @@ snapshots: dependencies: resolve: 1.22.11 - browser-tabs-lock@1.3.0: - dependencies: - lodash: 4.17.23 - browserify-aes@1.2.0: dependencies: buffer-xor: 1.0.3 @@ -29109,9 +28643,6 @@ snapshots: caniuse-lite@1.0.30001769: {} - caniuse-lite@1.0.30001779: - optional: true - canvas-confetti@1.9.3: {} capital-case@1.0.4: @@ -29357,8 +28888,6 @@ snapshots: clone@1.0.4: {} - clsx@1.2.1: {} - clsx@2.1.1: {} cmdk@1.1.1(@types/react-dom@19.2.3(@types/react@19.2.13))(@types/react@19.2.13)(react-dom@19.1.0(react@19.1.0))(react@19.1.0): @@ -29504,8 +29033,6 @@ snapshots: content-type@1.0.5: {} - convert-source-map@1.9.0: {} - convert-source-map@2.0.0: {} cookie-es@1.2.2: {} @@ -29527,16 +29054,10 @@ snapshots: dependencies: is-what: 3.14.1 - copy-to-clipboard@3.3.3: - dependencies: - toggle-selection: 1.0.6 - core-js-compat@3.48.0: dependencies: browserslist: 4.28.1 - core-js@3.41.0: {} - core-js@3.47.0: {} core-util-is@1.0.3: {} @@ -29569,6 +29090,7 @@ snapshots: parse-json: 5.2.0 path-type: 4.0.0 yaml: 1.10.2 + optional: true cpu-features@0.0.10: dependencies: @@ -29635,8 +29157,6 @@ snapshots: randombytes: 2.1.0 randomfill: 1.0.4 - crypto-js@4.2.0: {} - css-select@5.2.2: dependencies: boolbase: 1.0.0 @@ -30086,8 +29606,6 @@ snapshots: dotenv@16.6.1: {} - dotenv@17.2.2: {} - dotenv@17.2.3: {} drizzle-kit@0.31.5: @@ -30099,7 +29617,7 @@ snapshots: transitivePeerDependencies: - supports-color - drizzle-orm@0.38.4(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/react@19.2.13)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.8)(pg@8.17.2)(react@19.1.0)(sql.js@1.13.0): + drizzle-orm@0.38.4(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/react@19.2.13)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.15)(pg@8.17.2)(react@19.1.0)(sql.js@1.13.0): optionalDependencies: '@cloudflare/workers-types': 4.20251014.0 '@opentelemetry/api': 1.9.0 @@ -30109,12 +29627,12 @@ snapshots: '@types/sql.js': 1.4.9 better-sqlite3: 12.8.0 bun-types: 1.3.11 - kysely: 0.28.8 + kysely: 0.28.15 pg: 8.17.2 react: 19.1.0 sql.js: 1.13.0 - drizzle-orm@0.44.6(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.8)(pg@8.17.2)(sql.js@1.13.0): + drizzle-orm@0.44.6(@cloudflare/workers-types@4.20251014.0)(@opentelemetry/api@1.9.0)(@types/better-sqlite3@7.6.13)(@types/pg@8.16.0)(@types/sql.js@1.4.9)(better-sqlite3@12.8.0)(bun-types@1.3.11)(kysely@0.28.15)(pg@8.17.2)(sql.js@1.13.0): optionalDependencies: '@cloudflare/workers-types': 4.20251014.0 '@opentelemetry/api': 1.9.0 @@ -30123,7 +29641,7 @@ snapshots: '@types/sql.js': 1.4.9 better-sqlite3: 12.8.0 bun-types: 1.3.11 - kysely: 0.28.8 + kysely: 0.28.15 pg: 8.17.2 sql.js: 1.13.0 @@ -30862,8 +30380,6 @@ snapshots: fast-safe-stringify@2.1.1: {} - fast-sha256@1.3.0: {} - fast-uri@3.1.0: {} fast-xml-builder@1.1.2: @@ -30885,8 +30401,6 @@ snapshots: path-expression-matcher: 1.2.1 strnum: 2.2.0 - fastest-levenshtein@1.0.16: {} - fastq@1.20.1: dependencies: reusify: 1.1.0 @@ -30991,8 +30505,6 @@ snapshots: transitivePeerDependencies: - supports-color - find-root@1.1.0: {} - find-up@4.1.0: dependencies: locate-path: 5.0.0 @@ -31755,7 +31267,8 @@ snapshots: dependencies: postcss: 8.5.6 - idb-keyval@6.2.1: {} + idb-keyval@6.2.1: + optional: true ieee754@1.2.1: {} @@ -31940,10 +31453,6 @@ snapshots: isomorphic.js@0.2.5: {} - isows@1.0.7(ws@8.18.3): - dependencies: - ws: 8.18.3 - istanbul-lib-coverage@3.2.2: {} istanbul-lib-instrument@5.2.1: @@ -32077,8 +31586,6 @@ snapshots: js-base64@3.7.8: {} - js-cookie@3.0.5: {} - js-tokens@4.0.0: {} js-tokens@9.0.1: {} @@ -32216,8 +31723,7 @@ snapshots: kolorist@1.8.0: {} - kysely@0.28.8: - optional: true + kysely@0.28.15: {} lan-network@0.1.7: {} @@ -33643,6 +33149,8 @@ snapshots: nanoid@3.3.6: {} + nanostores@1.2.0: {} + napi-build-utils@2.0.0: {} natural-compare@1.4.0: {} @@ -33668,35 +33176,7 @@ snapshots: netmask@2.0.2: {} - next@15.5.9(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.57.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.93.2): - dependencies: - '@next/env': 15.5.9 - '@swc/helpers': 0.5.15 - caniuse-lite: 1.0.30001779 - postcss: 8.4.31 - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - styled-jsx: 5.1.6(@babel/core@7.29.0)(react@19.1.0) - optionalDependencies: - '@next/swc-darwin-arm64': 15.5.7 - '@next/swc-darwin-x64': 15.5.7 - '@next/swc-linux-arm64-gnu': 15.5.7 - '@next/swc-linux-arm64-musl': 15.5.7 - '@next/swc-linux-x64-gnu': 15.5.7 - '@next/swc-linux-x64-musl': 15.5.7 - '@next/swc-win32-arm64-msvc': 15.5.7 - '@next/swc-win32-x64-msvc': 15.5.7 - '@opentelemetry/api': 1.9.0 - '@playwright/test': 1.57.0 - babel-plugin-react-compiler: 1.0.0 - sass: 1.93.2 - sharp: 0.34.5 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - optional: true - - next@16.1.1(@opentelemetry/api@1.9.0)(@playwright/test@1.57.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.93.2): + next@16.1.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.57.0)(babel-plugin-react-compiler@1.0.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.93.2): dependencies: '@next/env': 16.1.1 '@swc/helpers': 0.5.15 @@ -34024,35 +33504,6 @@ snapshots: outvariant@1.4.3: {} - ox@0.6.9(typescript@5.9.3)(zod@3.25.76): - dependencies: - '@adraffy/ens-normalize': 1.11.1 - '@noble/curves': 1.9.7 - '@noble/hashes': 1.8.0 - '@scure/bip32': 1.7.0 - '@scure/bip39': 1.6.0 - abitype: 1.1.1(typescript@5.9.3)(zod@3.25.76) - eventemitter3: 5.0.1 - optionalDependencies: - typescript: 5.9.3 - transitivePeerDependencies: - - zod - - ox@0.9.6(typescript@5.9.3)(zod@3.25.76): - dependencies: - '@adraffy/ens-normalize': 1.11.1 - '@noble/ciphers': 1.3.0 - '@noble/curves': 1.9.1 - '@noble/hashes': 1.8.0 - '@scure/bip32': 1.7.0 - '@scure/bip39': 1.6.0 - abitype: 1.1.1(typescript@5.9.3)(zod@3.25.76) - eventemitter3: 5.0.1 - optionalDependencies: - typescript: 5.9.3 - transitivePeerDependencies: - - zod - p-limit@2.3.0: dependencies: p-try: 2.2.0 @@ -34509,8 +33960,6 @@ snapshots: preact: 10.27.2 web-vitals: 4.2.4 - preact@10.24.2: {} - preact@10.27.2: {} prebuild-install@7.1.3: @@ -34658,10 +34107,6 @@ snapshots: qrcode-terminal@0.11.0: {} - qrcode.react@4.2.0(react@19.1.0): - dependencies: - react: 19.1.0 - qs@6.14.1: dependencies: side-channel: 1.1.0 @@ -35061,8 +34506,6 @@ snapshots: regenerator-runtime@0.13.11: {} - regenerator-runtime@0.14.1: {} - regex-recursion@6.0.2: dependencies: regex-utilities: 2.3.0 @@ -35347,6 +34790,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.57.1 fsevents: 2.3.3 + rou3@0.7.12: {} + roughjs@4.6.6: dependencies: hachure-fill: 0.5.2 @@ -35547,6 +34992,8 @@ snapshots: server-only@0.0.1: {} + set-cookie-parser@3.1.0: {} + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 @@ -35805,11 +35252,6 @@ snapshots: dependencies: type-fest: 0.7.1 - standardwebhooks@1.0.0: - dependencies: - '@stablelib/base64': 1.0.1 - fast-sha256: 1.3.0 - state-local@1.0.7: {} statuses@1.5.0: {} @@ -35945,8 +35387,6 @@ snapshots: optionalDependencies: '@babel/core': 7.29.0 - stylis@4.2.0: {} - stylis@4.3.6: {} stylus@0.62.0: @@ -36211,8 +35651,6 @@ snapshots: dependencies: is-number: 7.0.0 - toggle-selection@1.0.6: {} - toidentifier@1.0.1: {} token-types@6.1.2: @@ -36839,12 +36277,6 @@ snapshots: optionalDependencies: '@types/react': 19.2.13 - use-isomorphic-layout-effect@1.2.1(@types/react@19.2.13)(react@19.1.0): - dependencies: - react: 19.1.0 - optionalDependencies: - '@types/react': 19.2.13 - use-latest-callback@0.2.6(react@19.1.0): dependencies: react: 19.1.0 @@ -36928,23 +36360,6 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - viem@2.37.8(typescript@5.9.3)(zod@3.25.76): - dependencies: - '@noble/curves': 1.9.1 - '@noble/hashes': 1.8.0 - '@scure/bip32': 1.7.0 - '@scure/bip39': 1.6.0 - abitype: 1.1.0(typescript@5.9.3)(zod@3.25.76) - isows: 1.0.7(ws@8.18.3) - ox: 0.9.6(typescript@5.9.3)(zod@3.25.76) - ws: 8.18.3 - optionalDependencies: - typescript: 5.9.3 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - zod - vite-node@1.6.1(@types/node@22.19.10)(less@4.4.1)(lightningcss@1.32.0)(sass@1.93.2)(stylus@0.62.0)(terser@5.46.0): dependencies: cac: 6.7.14 @@ -37819,8 +37234,6 @@ snapshots: ws@8.18.0: {} - ws@8.18.3: {} - ws@8.19.0: {} wsl-utils@0.1.0: @@ -37860,8 +37273,6 @@ snapshots: xmlbuilder@15.1.1: {} - xstate@5.21.0: {} - xtend@4.0.2: {} xxhash-wasm@1.1.0: {} @@ -37961,6 +37372,10 @@ snapshots: dependencies: zod: 4.1.13 + zod-to-json-schema@3.25.1(zod@4.3.6): + dependencies: + zod: 4.3.6 + zod-to-ts@1.2.0(typescript@5.9.3)(zod@3.25.76): dependencies: typescript: 5.9.3 @@ -37974,6 +37389,8 @@ snapshots: zod@4.1.13: {} + zod@4.3.6: {} + zustand@4.5.7(@types/react@19.2.13)(react@19.1.0): dependencies: use-sync-external-store: 1.6.0(react@19.1.0) @@ -37981,12 +37398,6 @@ snapshots: '@types/react': 19.2.13 react: 19.1.0 - zustand@5.0.3(@types/react@19.2.13)(react@19.1.0)(use-sync-external-store@1.6.0(react@19.1.0)): - optionalDependencies: - '@types/react': 19.2.13 - react: 19.1.0 - use-sync-external-store: 1.6.0(react@19.1.0) - zustand@5.0.8(@types/react@19.2.13)(react@19.1.0)(use-sync-external-store@1.6.0(react@19.1.0)): optionalDependencies: '@types/react': 19.2.13