rspc

repository·main·Indexed 23 days ago

https://github.com/specta-rs/rspc

A high-performance, TRPC-inspired server framework for Rust designed to provide type-safe communication between a Rust backend and a client. It allows developers to define routers with queries and mutations, featuring per-request context, middleware, and router merging. The ecosystem includes support for Binario serialization, a caching middleware with custom store implementations, and integration examples for Next.js (with @tanstack/react-query) and Tauri. Note: rspc is no longer being maintained.

Tokens
17K
Snippets
28
Records
123
Agent score
79%

What's inside rspc

  1. What is rspc?

    main

    rspc is a high-performance, easy-to-use TRPC-like server framework for Rust. It allows you to define routers and attach procedures (queries and mutations) that can be easily consumed by clients, providing a type-safe bridge between Rust and frontend environments.

    Note: rspc is no longer being maintained.

  2. Use Binario for serialization in rspc

    main

    The rspc-binario crate is a proof of concept that demonstrates rspc's ability to support serialization libraries other than Serde. It allows you to use Binario for serialization and deserialization within your rspc setup.

    CAUTION

    This crate is a proof of concept. It is not intended for production use and will likely remain that way.

  3. Core features of rspc

    main

    rspc provides several key capabilities for building type-safe APIs:

    • Per Request Context: Allows you to attach data like database connections or authentication information to every request.
    • Middleware: Supports intercepting requests with support for context switching.
    • Merging Routers: Enables modular code organization by allowing you to define separate routers in different files and merge them into a single main router.
  4. Explore rspc usage patterns in Next.js

    main

    The Next.js example repository contains several files demonstrating different rspc integration patterns:

    • Client Setup: src/rspc.ts demonstrates how to initialize the rspc client and generate React hooks.
    • Global Configuration: pages/__app.tsx shows how to wrap your application with the necessary global provider.
    • Data Fetching (Client-side):
      • pages/using-use-query.tsx demonstrates using the useQuery hook for fetching data.
      • pages/using-use-mutation.tsx demonstrates using the useMutation hook for performing side effects.
      • pages/using-use-subscription.tsx demonstrates using the useSubscription hook for real-time updates.
    • Server-side Rendering (SSR): pages/using-ssp.tsx shows how to execute queries on the server side.
  5. Use the Tauri + Solid + Typescript template

    main
    This template provides a starting point for developing applications using Tauri, Solid, and TypeScript within a Vite environment. It is designed to demonstrate how to integrate rspc into a desktop application stack using these technologies.
  6. What is a Procedure in rspc?

    main

    A Procedure is the fundamental unit of work in rspc. It encapsulates a single server-side operation that a client can invoke.

    Composition

    A procedure is built from two main components:

    1. Middleware: A sequence of functions that can intercept the request, modify the state, or perform side effects before/after the resolver.
    2. Resolver: The core logic of the operation, which can be a query, mutation, or subscription.

    Type Safety

    Procedures are highly type-safe, leveraging Specta to ensure that input types, output types, and error types are correctly mapped and can be exported for client-side type generation. They support both standard Serde-compatible types and custom types via the ResolverInput and ResolverOutput traits.

  7. Define invalidation strategies with the Invalidate enum

    main

    The Invalidate<T> enum defines how a procedure should trigger invalidation when an event occurs. You can specify whether to do nothing, invalidate everything, or target specific inputs.

    Variants:

    • Invalidate::None: No invalidation occurs.
    • Invalidate::Any: Triggers a global invalidation (implementation pending).
    • Invalidate::One(T): Invalidates based on a single input of type T.
    • Invalidate::Many(Vec<T>): Invalidates based on a collection of inputs of type T.
    // Example of possible usage patterns
    Invalidate::None
    Invalidate::Any
    Invalidate::One(input)
    Invalidate::Many(vec![input1, input2])
  8. What can be returned from an rspc procedure?

    main

    In rspc, any type returned from a procedure handler must implement the ResolverOutput trait.

    By default, rspc provides an implementation for any type that satisfies the following bounds:

    • serde::Serialize
    • specta::Type
    • Send + Sync + 'static

    When you return a value (or a Future that resolves to a value), rspc converts it into a ProcedureStream which is then used by the internal execution engine. If your handler returns a Stream, rspc will flatten it into a ProcedureStream automatically.

    If you need to return a custom type that doesn't meet the default bounds, you must manually implement ResolverOutput and define how it converts into a ProcedureOutput (via into_procedure_result).

    // Standard usage with types that implement Serialize and specta::Type
    <Procedure>::builder().query(|_, _: ()| async move { 
        MyCoolThing("Hello, World!".to_string()) 
    });