kitcn
Version:
kitcn - React Query integration and CLI tools for Convex
89 lines (87 loc) • 2.97 kB
JavaScript
import { t as getToken } from "../../token-oA2EMtPA.js";
import { n as defaultIsUnauthorized } from "../../error-Bvo7YEhk.js";
import { t as createCallerFactory } from "../../caller-factory-NEfgD5E0.js";
//#region src/auth-nextjs/index.ts
/** biome-ignore-all lint/suspicious/noExplicitAny: lib */
/**
* Next.js + Better Auth wrapper for Convex caller factory.
*/
const TRAILING_COLON_RE = /:$/;
const handler = async (request, siteUrl) => {
const requestUrl = new URL(request.url);
const nextUrl = `${siteUrl}${requestUrl.pathname}${requestUrl.search}`;
const headers = new Headers(request.headers);
headers.set("accept-encoding", "application/json");
headers.set("host", new URL(siteUrl).host);
headers.set("x-forwarded-host", requestUrl.host);
headers.set("x-forwarded-proto", requestUrl.protocol.replace(TRAILING_COLON_RE, ""));
headers.set("x-better-auth-forwarded-host", requestUrl.host);
headers.set("x-better-auth-forwarded-proto", requestUrl.protocol.replace(TRAILING_COLON_RE, ""));
const body = request.method !== "GET" && request.method !== "HEAD" ? await request.arrayBuffer() : void 0;
return fetch(nextUrl, {
body,
headers,
method: request.method,
redirect: "manual"
});
};
const nextJsHandler = (siteUrl) => ({
GET: (request) => handler(request, siteUrl),
POST: (request) => handler(request, siteUrl)
});
/**
* Create Convex caller factory with Better Auth integration for Next.js.
*
* @example
* ```ts
* // server.ts
* export const { createContext, createCaller, handler } = convexBetterAuth({
* api,
* convexSiteUrl: env.NEXT_PUBLIC_CONVEX_SITE_URL,
* }); // JWT caching enabled by default
*
* // rsc.tsx
* const createRSCContext = cache(async () => {
* const heads = await headers();
* return createContext({ headers: heads });
* });
* export const caller = createCaller(createRSCContext);
*
* // app/page.tsx - single call!
* const posts = await caller.posts.list();
* ```
*/
function convexBetterAuth(opts) {
const auth = opts.auth ?? {};
const jwtCacheEnabled = auth.jwtCache !== false;
const { createContext, createCaller } = createCallerFactory({
api: opts.api,
auth: jwtCacheEnabled ? {
getToken: (siteUrl, headers, getTokenOpts) => {
const mutableHeaders = new Headers(headers);
mutableHeaders.delete("content-length");
mutableHeaders.delete("transfer-encoding");
mutableHeaders.set("accept-encoding", "identity");
return getToken(siteUrl, mutableHeaders, {
basePath: auth.basePath,
...getTokenOpts,
jwtCache: {
enabled: true,
expirationToleranceSeconds: auth.expirationToleranceSeconds,
isAuthError: auth.isUnauthorized ?? defaultIsUnauthorized
}
});
},
isUnauthorized: auth.isUnauthorized ?? defaultIsUnauthorized
} : void 0,
convexSiteUrl: opts.convexSiteUrl,
convexUrl: opts.convexUrl
});
return {
createCaller,
createContext,
handler: nextJsHandler(opts.convexSiteUrl)
};
}
//#endregion
export { convexBetterAuth };