- Spec files
npm-tanstack--react-start
Describes: pkg:npm/@tanstack/react-start@1.132.x
- Description
- Modern full-stack React framework with SSR, streaming, server functions, and API routes powered by TanStack Router and Vite.
- Author
- tessl
- Last updated
How to use
npx @tessl/cli registry install tessl/npm-tanstack--react-start@1.132.0
rpc-system.md docs/
1# RPC System23The RPC (Remote Procedure Call) system provides type-safe client-server communication with automatic serialization and request handling. It enables seamless function calls between client and server environments with full type safety and error handling.45## Capabilities67### Create Client RPC89Creates client-side RPC functions that can communicate with server-side endpoints.1011```typescript { .api }12/**13* Creates a client-side RPC function for server communication14* @param functionId - Unique identifier for the RPC function15* @param fetcher - Function that handles the actual HTTP request16* @returns ClientRpc instance for making server calls17*/18function createClientRpc(19functionId: string,20fetcher: (...args: any[]) => Promise<any>21): ClientRpc;2223interface ClientRpc {24(...args: any[]): Promise<any>;25functionId: string;26url: string;27}28```2930**Usage Examples:**3132```typescript33import { createClientRpc } from "@tanstack/react-start/client-rpc";3435// Basic RPC function36const getUserRpc = createClientRpc(37"getUser",38async (id: string) => {39const response = await fetch(`/api/functions/getUser`, {40method: "POST",41headers: { "Content-Type": "application/json" },42body: JSON.stringify({ id })43});44return response.json();45}46);4748// Use in React component49function UserProfile({ userId }: { userId: string }) {50const [user, setUser] = useState(null);5152useEffect(() => {53getUserRpc(userId).then(setUser);54}, [userId]);5556return user ? <div>{user.name}</div> : <div>Loading...</div>;57}5859// Advanced RPC with error handling60const createUserRpc = createClientRpc(61"createUser",62async (userData: { name: string; email: string }) => {63try {64const response = await fetch("/api/functions/createUser", {65method: "POST",66headers: { "Content-Type": "application/json" },67body: JSON.stringify(userData)68});6970if (!response.ok) {71throw new Error(`HTTP ${response.status}: ${response.statusText}`);72}7374return response.json();75} catch (error) {76console.error("RPC call failed:", error);77throw error;78}79}80);81```8283### Create Server RPC8485Creates server-side RPC functions that can be called from client code.8687```typescript { .api }88/**89* Creates a server-side RPC function with split import functionality90* @param functionId - Unique identifier for the RPC function91* @param splitImportFn - Function that handles dynamic imports and execution92* @returns ServerRpc instance with URL and function metadata93*/94function createServerRpc(95functionId: string,96splitImportFn: (...args: any[]) => any97): ServerRpc;9899interface ServerRpc {100(...args: any[]): any;101url: string;102functionId: string;103[TSS_SERVER_FUNCTION]: true;104}105```106107**Usage Examples:**108109```typescript110import { createServerRpc } from "@tanstack/react-start/server-rpc";111112// Basic server RPC113const getUserServerRpc = createServerRpc(114"getUser",115async (id: string) => {116// Dynamic import for server-only code117const { db } = await import("./database");118return db.user.findUnique({ where: { id } });119}120);121122// RPC with complex business logic123const processOrderServerRpc = createServerRpc(124"processOrder",125async (orderData: {126items: Array<{ id: string; quantity: number }>;127customerId: string;128paymentMethod: string;129}) => {130// Split imports for server-only dependencies131const [132{ db },133{ paymentProcessor },134{ inventoryManager },135{ emailService }136] = await Promise.all([137import("./database"),138import("./payment"),139import("./inventory"),140import("./email")141]);142143// Process order with full server-side logic144const order = await db.order.create({145data: {146customerId: orderData.customerId,147items: {148create: orderData.items.map(item => ({149productId: item.id,150quantity: item.quantity151}))152}153}154});155156// Process payment157const payment = await paymentProcessor.charge({158amount: order.total,159method: orderData.paymentMethod,160customerId: orderData.customerId161});162163// Update inventory164await inventoryManager.decrementStock(orderData.items);165166// Send confirmation email167await emailService.sendOrderConfirmation(orderData.customerId, order);168169return { order, payment };170}171);172```173174### Server Function Fetcher175176Utilities for handling server function requests and responses.177178```typescript { .api }179/**180* Server function fetcher for handling RPC requests181* @param url - The URL to fetch from182* @param options - Fetch options including method and body183* @returns Promise resolving to the response184*/185interface ServerFnFetcher {186(url: string, options: ServerFnFetchOptions): Promise<Response>;187}188189interface ServerFnFetchOptions {190method: string;191headers?: HeadersInit;192body?: BodyInit;193}194```195196## RPC Configuration and Environment197198### Environment Variables199200The RPC system uses environment variables for configuration:201202```typescript203// Server configuration204process.env.TSS_APP_BASE = "/"; // Base path for the application205process.env.TSS_SERVER_FN_BASE = "api/functions"; // Base path for server functions206```207208### URL Generation209210RPC functions automatically generate URLs based on configuration:211212```typescript213// Generated URL structure214const baseUrl = `${TSS_APP_BASE}/${TSS_SERVER_FN_BASE}/`;215const functionUrl = baseUrl + functionId;216217// Example: /api/functions/getUser218```219220## Advanced Usage Patterns221222### RPC with Authentication223224```typescript225import { createClientRpc } from "@tanstack/react-start/client-rpc";226227// Authenticated RPC calls228const createAuthenticatedRpc = (functionId: string) =>229createClientRpc(functionId, async (...args) => {230const token = localStorage.getItem("auth-token");231232const response = await fetch(`/api/functions/${functionId}`, {233method: "POST",234headers: {235"Content-Type": "application/json",236"Authorization": `Bearer ${token}`237},238body: JSON.stringify(args)239});240241if (response.status === 401) {242// Handle authentication error243window.location.href = "/login";244throw new Error("Authentication required");245}246247return response.json();248});249250const getUserRpc = createAuthenticatedRpc("getUser");251const updateUserRpc = createAuthenticatedRpc("updateUser");252```253254### RPC with Caching255256```typescript257import { createClientRpc } from "@tanstack/react-start/client-rpc";258259// Cached RPC calls260const cache = new Map();261262const createCachedRpc = (functionId: string, cacheTTL = 5 * 60 * 1000) =>263createClientRpc(functionId, async (...args) => {264const cacheKey = `${functionId}:${JSON.stringify(args)}`;265const cached = cache.get(cacheKey);266267if (cached && Date.now() - cached.timestamp < cacheTTL) {268return cached.data;269}270271const response = await fetch(`/api/functions/${functionId}`, {272method: "POST",273headers: { "Content-Type": "application/json" },274body: JSON.stringify(args)275});276277const data = await response.json();278cache.set(cacheKey, { data, timestamp: Date.now() });279280return data;281});282283const getUserRpc = createCachedRpc("getUser", 10 * 60 * 1000); // 10 minute cache284```285286### Server RPC with Validation287288```typescript289import { createServerRpc } from "@tanstack/react-start/server-rpc";290291const validateUserInput = (data: unknown) => {292if (!data || typeof data !== "object") {293throw new Error("Invalid input");294}295296const { name, email } = data as any;297if (!name || typeof name !== "string") {298throw new Error("Name is required");299}300if (!email || !email.includes("@")) {301throw new Error("Valid email is required");302}303304return { name, email };305};306307const createUserServerRpc = createServerRpc(308"createUser",309async (input: unknown) => {310// Validate input311const userData = validateUserInput(input);312313// Import server dependencies314const { db } = await import("./database");315const { hashPassword } = await import("./crypto");316const { sendWelcomeEmail } = await import("./email");317318// Create user with validated data319const user = await db.user.create({320data: {321name: userData.name,322email: userData.email,323passwordHash: await hashPassword("temporary")324}325});326327// Send welcome email asynchronously328sendWelcomeEmail(user.email, user.name).catch(console.error);329330return { user: { id: user.id, name: user.name, email: user.email } };331}332);333```334335### RPC Error Handling336337```typescript338import { createClientRpc } from "@tanstack/react-start/client-rpc";339340const createRobustRpc = (functionId: string, maxRetries = 3) =>341createClientRpc(functionId, async (...args) => {342let lastError;343344for (let attempt = 1; attempt <= maxRetries; attempt++) {345try {346const response = await fetch(`/api/functions/${functionId}`, {347method: "POST",348headers: { "Content-Type": "application/json" },349body: JSON.stringify(args)350});351352if (!response.ok) {353if (response.status >= 500 && attempt < maxRetries) {354// Retry on server errors355await new Promise(resolve =>356setTimeout(resolve, Math.pow(2, attempt) * 1000)357);358continue;359}360361const errorData = await response.json().catch(() => ({}));362throw new Error(errorData.message || `HTTP ${response.status}`);363}364365return response.json();366} catch (error) {367lastError = error;368if (attempt === maxRetries) break;369370// Exponential backoff for retries371await new Promise(resolve =>372setTimeout(resolve, Math.pow(2, attempt) * 1000)373);374}375}376377throw lastError;378});379380const getUserRpc = createRobustRpc("getUser");381```382383## Types384385```typescript { .api }386// RPC function types387interface ClientRpc {388(...args: any[]): Promise<any>;389functionId: string;390url: string;391}392393interface ServerRpc {394(...args: any[]): any;395url: string;396functionId: string;397[TSS_SERVER_FUNCTION]: true;398}399400// Server function marker401declare const TSS_SERVER_FUNCTION: unique symbol;402403// Fetch options for server functions404interface ServerFnFetchOptions {405method: string;406headers?: HeadersInit;407body?: BodyInit;408}409410// Server function fetcher type411interface ServerFnFetcher {412(url: string, options: ServerFnFetchOptions): Promise<Response>;413}414415// RPC stream types416interface RscStream {417// React Server Component stream handling418read(): Promise<any>;419pipe(destination: any): any;420}421422// Fetcher data types423interface FetcherData {424url: string;425method: string;426headers: Headers;427body?: any;428}429430interface FetcherBaseOptions {431method?: string;432headers?: HeadersInit;433}434435// Compiled fetcher types436interface CompiledFetcherFnOptions {437method: string;438headers?: HeadersInit;439body?: BodyInit;440}441442interface CompiledFetcherFn {443(url: string, options: CompiledFetcherFnOptions): Promise<Response>;444}445446interface Fetcher {447fn: CompiledFetcherFn;448options: CompiledFetcherFnOptions;449}450451// Optional and required fetcher types452interface OptionalFetcher {453fetcher?: Fetcher;454}455456interface RequiredFetcher {457fetcher: Fetcher;458}459```