import { createTRPCReact, httpBatchLink } from "@trpc/react-query"; import { createTRPCProxyClient } from "@trpc/client"; import { inferRouterInputs, inferRouterOutputs } from "@trpc/server"; import { extractSubdomain, isReservedSubdomain } from "@micprotocol/shared-types"; import type { AppRouter } from "@micprotocol/api"; export const trpc = createTRPCReact(); const API_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:4000"; type AuthTokenGetter = () => Promise; type WorkspaceIdGetter = () => string | null; /** * Create a tRPC React client that sends both the auth token and the * active workspace ID on every request. * * @param getAuthToken – async function returning the session token (or null) * @param getWorkspaceId – sync function returning the currently active * workspace ID from React context (or null) */ export function getTrpcClient( getAuthToken?: AuthTokenGetter, getWorkspaceId?: WorkspaceIdGetter, ) { return trpc.createClient({ links: [ httpBatchLink({ url: `${API_URL}/trpc`, async headers() { const token = getAuthToken ? await getAuthToken() : null; const workspaceId = getWorkspaceId ? getWorkspaceId() : null; const headers: Record = {}; if (token) { headers.Authorization = `Bearer ${token}`; } if (workspaceId) { headers["x-workspace-id"] = workspaceId; } if (typeof window !== "undefined") { const subdomain = extractSubdomain(window.location.hostname); if (subdomain && !isReservedSubdomain(subdomain)) { headers["x-subdomain"] = subdomain; } } return headers; }, // Send cookies with requests fetch(url, options) { return fetch(url, { ...options, credentials: "include", }); }, }), ], }); } // Utility to create a server-side client (for RSC) export function getServerTrpcClient() { return createTRPCProxyClient({ links: [ httpBatchLink({ url: `${API_URL}/trpc`, }), ], }); } // Types for router inputs/outputs export type RouterInputs = inferRouterInputs; export type RouterOutputs = inferRouterOutputs;