kitcn
Version:
kitcn - React Query integration and CLI tools for Convex
117 lines (91 loc) • 2.76 kB
Markdown
**Create:** `src/lib/convex/server.ts`
```ts
import { api } from "@convex/api";
import { convexBetterAuth } from "kitcn/auth/nextjs";
export const { createContext, createCaller, handler } = convexBetterAuth({
api,
convexSiteUrl: process.env.NEXT_PUBLIC_CONVEX_SITE_URL!,
});
```
**Create:** `src/app/api/auth/[...all]/route.ts`
```ts
import { handler } from "@/lib/convex/server";
export const { GET, POST } = handler;
```
**Create:** `src/lib/convex/rsc.tsx`
```tsx
import "server-only";
import { api } from "@convex/api";
import type { FetchQueryOptions } from "@tanstack/react-query";
import {
dehydrate,
HydrationBoundary,
QueryClient,
} from "@tanstack/react-query";
import {
createServerCRPCProxy,
getServerQueryClientOptions,
} from "kitcn/rsc";
import { headers } from "next/headers";
import { cache } from "react";
import { hydrationConfig } from "./query-client";
import { createCaller, createContext } from "./server";
const createRSCContext = cache(async () =>
createContext({ headers: await headers() })
);
export const caller = createCaller(createRSCContext);
export const crpc = createServerCRPCProxy({ api });
function createServerQueryClient() {
return new QueryClient({
defaultOptions: {
...hydrationConfig,
...getServerQueryClientOptions({
getToken: caller.getToken,
convexSiteUrl: process.env.NEXT_PUBLIC_CONVEX_SITE_URL!,
}),
},
});
}
export const getQueryClient = cache(createServerQueryClient);
export function prefetch<T extends { queryKey: readonly unknown[] }>(
queryOptions: T
): void {
void getQueryClient().prefetchQuery(queryOptions);
}
export function preloadQuery<
TQueryFnData = unknown,
TError = Error,
TData = TQueryFnData,
TQueryKey extends readonly unknown[] = readonly unknown[],
>(
options: FetchQueryOptions<TQueryFnData, TError, TData, TQueryKey>
): Promise<TData> {
return getQueryClient().fetchQuery(options);
}
export function HydrateClient({ children }: { children: React.ReactNode }) {
const queryClient = getQueryClient();
const dehydratedState = dehydrate(queryClient);
return (
<HydrationBoundary state={dehydratedState}>{children}</HydrationBoundary>
);
}
```
```tsx
// app/(app)/layout.tsx
import { AppConvexProvider } from "@/lib/convex/convex-provider";
import { caller } from "@/lib/convex/rsc";
export default async function AppLayout({
children,
}: {
children: React.ReactNode;
}) {
const token = await caller.getToken();
return <AppConvexProvider token={token}>{children}</AppConvexProvider>;
}
```