UNPKG

kitcn

Version:

kitcn - React Query integration and CLI tools for Convex

149 lines (118 loc) 4.06 kB
## 8.B TanStack Start CLI-first flow: scaffold the app, run `kitcn add auth --yes`, then treat the files below as the generated reference output. They are not a separate manual install path. After changing plugins or auth fields in `<functionsDir>/auth.ts`, refresh auth-owned schema blocks with `bunx kitcn add auth --schema --yes`. Keep `bunx kitcn dev` running as the local Convex + codegen loop. ### 8.B.1 Auth client + auth server helpers **Create:** `src/lib/convex/auth-client.ts` ```ts import { createAuthClient } from "better-auth/react"; import { convexClient } from "kitcn/auth/client"; import { createAuthMutations } from "kitcn/react"; export const authClient = createAuthClient({ baseURL: typeof window === "undefined" ? (import.meta.env.VITE_SITE_URL as string | undefined) : window.location.origin, plugins: [convexClient()], }); export const { useSignInMutationOptions, useSignOutMutationOptions, useSignUpMutationOptions, } = createAuthMutations(authClient); ``` **Create:** `src/lib/convex/auth-server.ts` ```ts import { convexBetterAuthReactStart } from "kitcn/auth/start/server"; export const { handler, getToken, fetchAuthQuery, fetchAuthMutation, fetchAuthAction, } = convexBetterAuthReactStart({ convexUrl: import.meta.env.VITE_CONVEX_URL!, convexSiteUrl: import.meta.env.VITE_CONVEX_SITE_URL!, }); ``` For client-side route loaders that fetch protected Convex queries through the router `queryClient`, prime the shared Convex client in the root `beforeLoad` before child loaders run: ```tsx import type { QueryClient } from "@tanstack/react-query"; import { createRootRouteWithContext } from "@tanstack/react-router"; import { createServerFn } from "@tanstack/react-start"; import { syncConvexAuthForStartLoader } from "kitcn/auth/start"; import type { ConvexQueryClient } from "kitcn/react"; import { getToken } from "@/lib/convex/auth-server"; const getLoaderToken = createServerFn({ method: "GET" }).handler(async () => { return await getToken(); }); export const Route = createRootRouteWithContext<{ convexQueryClient: ConvexQueryClient; queryClient: QueryClient; }>()({ beforeLoad: async ({ context }) => { return await syncConvexAuthForStartLoader({ convex: context.convexQueryClient, getToken: getLoaderToken, }); }, }); ``` Use `runServerCall` or `fetchAuthQuery` for server-side loaders. Use `syncConvexAuthForStartLoader` only for client/router loaders that execute shared `ConvexQueryClient` queries before `ConvexAuthProvider` mounts. ### 8.B.2 Auth API endpoint **Create:** `src/routes/api/auth/$.ts` ```ts import { createFileRoute } from "@tanstack/react-router"; import { handler } from "@/lib/convex/auth-server"; export const Route = createFileRoute("/api/auth/$" as never)({ server: { handlers: { GET: ({ request }) => handler(request), POST: ({ request }) => handler(request), }, }, }); ``` ### 8.B.3 Caller/context and providers **Create:** `src/lib/convex/server.ts` ```ts import { api } from "@convex/api"; import { getRequestHeaders } from "@tanstack/react-start/server"; import { createCallerFactory } from "kitcn/server"; import { getToken } from "@/lib/convex/auth-server"; const { createContext, createCaller } = createCallerFactory({ api, convexSiteUrl: import.meta.env.VITE_CONVEX_SITE_URL!, auth: { getToken: async () => { return { token: await getToken(), }; }, }, }); type ServerCaller = ReturnType<typeof createCaller>; async function makeContext() { const headers = await getRequestHeaders(); return createContext({ headers }); } function createServerCaller(): ServerCaller { return createCaller(async () => { return await makeContext(); }); } export function runServerCall<T>(fn: (caller: ServerCaller) => Promise<T> | T) { const caller = createServerCaller(); return fn(caller); } ``` Use the docs pattern from `tanstack-start.mdx` for: - `src/routes/__root.tsx` shell/provider wiring - `src/lib/convex/convex-provider.tsx`