Convert Figma logo to code with AI

unnoq logoorpc

Typesafe APIs Made Simple 🪄

2,419
49
2,419
21

Top Related Projects

42,942

C++ based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)

10,671

Apache Thrift

10,153

ZeroMQ core engine in C++, implements ZMTP/3.1

40,939

The java implementation of Apache Dubbo. An RPC and microservice framework.

Quick Overview

ORPC (Object Remote Procedure Call) is a lightweight RPC framework for Rust. It allows for seamless communication between Rust applications across networks, enabling remote method invocation and object-oriented programming paradigms in distributed systems.

Pros

  • Type-safe and efficient remote procedure calls in Rust
  • Supports both synchronous and asynchronous communication
  • Integrates well with Rust's ownership and borrowing system
  • Minimal runtime overhead compared to other RPC frameworks

Cons

  • Limited documentation and examples available
  • Relatively new project, which may lead to potential instability or breaking changes
  • Smaller community compared to more established RPC frameworks
  • May have a steeper learning curve for developers new to Rust or RPC concepts

Code Examples

  1. Defining a remote service:
#[orpc::service]
trait MyService {
    async fn hello(&self, name: String) -> String;
}
  1. Implementing the service:
struct MyServiceImpl;

#[orpc::async_trait]
impl MyService for MyServiceImpl {
    async fn hello(&self, name: String) -> String {
        format!("Hello, {}!", name)
    }
}
  1. Creating a client and making a remote call:
let client = MyServiceClient::connect("127.0.0.1:8080").await?;
let result = client.hello("Alice".to_string()).await?;
println!("Server response: {}", result);

Getting Started

To use ORPC in your Rust project, add the following to your Cargo.toml:

[dependencies]
orpc = "0.1"

Then, in your Rust code:

use orpc::prelude::*;

#[orpc::service]
trait MyService {
    async fn greet(&self, name: String) -> String;
}

// Implement the service and use it in your application

For more detailed usage instructions and examples, refer to the project's documentation and examples in the repository.

Competitor Comparisons

42,942

C++ based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)

Pros of gRPC

  • Mature and widely adopted, with extensive documentation and community support
  • High performance due to Protocol Buffers serialization and HTTP/2 transport
  • Built-in support for multiple programming languages and platforms

Cons of gRPC

  • Steeper learning curve, especially for developers new to Protocol Buffers
  • More complex setup and configuration compared to simpler RPC frameworks
  • Limited browser support without additional proxies or workarounds

Code Comparison

gRPC (Protocol Buffers definition):

syntax = "proto3";

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

ORPC (JavaScript definition):

const greeter = {
  sayHello: async (name) => {
    return { message: `Hello, ${name}!` };
  }
};

While gRPC requires a separate Protocol Buffers definition, ORPC allows for simpler, language-native definitions. gRPC offers more structured and typed interfaces, whereas ORPC provides a more flexible and lightweight approach to RPC.

10,671

Apache Thrift

Pros of Thrift

  • Mature and widely adopted, with extensive language support
  • Robust ecosystem and community backing from Apache
  • Efficient binary serialization for high-performance RPC

Cons of Thrift

  • Steeper learning curve due to complex IDL and generated code
  • Less flexibility in protocol customization
  • Heavier implementation compared to lightweight alternatives

Code Comparison

Thrift IDL example:

service Calculator {
  i32 add(1: i32 num1, 2: i32 num2)
}

ORPC IDL example:

#[orpc::service]
trait Calculator {
    async fn add(&self, num1: i32, num2: i32) -> i32;
}

The ORPC approach uses Rust-native syntax and attributes, making it more intuitive for Rust developers. Thrift's IDL is language-agnostic but requires learning a separate syntax.

Thrift generates language-specific code from the IDL, while ORPC leverages Rust's type system and async features directly. This results in a more seamless integration with Rust codebases for ORPC, but Thrift offers broader language support.

Both frameworks aim to simplify RPC implementations, but they cater to different use cases and developer preferences. Thrift is better suited for polyglot environments, while ORPC provides a more Rust-centric experience.

10,153

ZeroMQ core engine in C++, implements ZMTP/3.1

Pros of libzmq

  • Mature and widely-used messaging library with extensive documentation
  • Supports multiple programming languages and platforms
  • High-performance and scalable for distributed systems

Cons of libzmq

  • Steeper learning curve due to its complexity and feature-rich nature
  • Requires more setup and configuration for basic use cases
  • Larger codebase and potential overhead for simpler projects

Code Comparison

libzmq:

zmq::context_t context(1);
zmq::socket_t socket(context, ZMQ_REQ);
socket.connect("tcp://localhost:5555");
zmq::message_t request(5);
memcpy(request.data(), "Hello", 5);
socket.send(request);

orpc:

let mut client = Client::connect("localhost:8080")?;
let response: String = client.call("echo", &"Hello".to_string())?;
println!("Response: {}", response);

Summary

libzmq is a powerful and versatile messaging library suitable for complex distributed systems, while orpc appears to be a simpler RPC framework focused on ease of use. libzmq offers more features and language support but may be overkill for basic RPC needs. orpc seems to provide a more straightforward API for simple remote procedure calls, potentially making it easier to implement for smaller projects or those primarily using Rust.

40,939

The java implementation of Apache Dubbo. An RPC and microservice framework.

Pros of Dubbo

  • Mature and widely adopted in enterprise environments
  • Extensive feature set including load balancing, service governance, and monitoring
  • Strong community support and regular updates

Cons of Dubbo

  • Steeper learning curve due to its comprehensive nature
  • Heavier footprint, which may be overkill for smaller projects
  • Primarily Java-focused, with limited support for other languages

Code Comparison

ORPC (Python):

@orpc.service
class MyService:
    def hello(self, name: str) -> str:
        return f"Hello, {name}!"

Dubbo (Java):

@Service
public class MyServiceImpl implements MyService {
    public String hello(String name) {
        return "Hello, " + name + "!";
    }
}

Key Differences

  • ORPC is more lightweight and focused on simplicity, while Dubbo offers a more comprehensive ecosystem
  • ORPC is primarily designed for Python, whereas Dubbo is Java-centric with some multi-language support
  • Dubbo provides more built-in features for service discovery and load balancing, while ORPC relies on external tools for these functionalities

Use Cases

  • Choose ORPC for smaller Python projects prioritizing simplicity and ease of use
  • Opt for Dubbo in large-scale Java enterprise applications requiring robust service governance and scalability

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

oRPC logo

Typesafe APIs Made Simple 🪄

oRPC is a powerful combination of RPC and OpenAPI, makes it easy to build APIs that are end-to-end type-safe and adhere to OpenAPI standards


Highlights

  • 🔗 End-to-End Type Safety: Ensure type-safe inputs, outputs, and errors from client to server.
  • 📘 First-Class OpenAPI: Built-in support that fully adheres to the OpenAPI standard.
  • 📝 Contract-First Development: Optionally define your API contract before implementation.
  • ⚙️ Framework Integrations: Seamlessly integrate with TanStack Query (React, Vue, Solid, Svelte, Angular), Pinia Colada, and more.
  • 🚀 Server Actions: Fully compatible with React Server Actions on Next.js, TanStack Start, and other platforms.
  • 🔠 Standard Schema Support: Works out of the box with Zod, Valibot, ArkType, and other schema validators.
  • 🗃️ Native Types: Supports native types like Date, File, Blob, BigInt, URL, and more.
  • ⏱️ Lazy Router: Enhance cold start times with our lazy routing feature.
  • 📡 SSE & Streaming: Enjoy full type-safe support for SSE and streaming.
  • 🌍 Multi-Runtime Support: Fast and lightweight on Cloudflare, Deno, Bun, Node.js, and beyond.
  • 🔌 Extendability: Easily extend functionality with plugins, middleware, and interceptors.
  • 🛡️ Reliability: Well-tested, TypeScript-based, production-ready, and MIT licensed.

Documentation

You can find the full documentation here.

Packages

Overview

This is a quick overview of how to use oRPC. For more details, please refer to the documentation.

  1. Define your router:

    import type { IncomingHttpHeaders } from 'node:http'
    import { ORPCError, os } from '@orpc/server'
    import { z } from 'zod'
    
    const PlanetSchema = z.object({
      id: z.number().int().min(1),
      name: z.string(),
      description: z.string().optional(),
    })
    
    export const listPlanet = os
      .input(
        z.object({
          limit: z.number().int().min(1).max(100).optional(),
          cursor: z.number().int().min(0).default(0),
        }),
      )
      .handler(async ({ input }) => {
        // your list code here
        return [{ id: 1, name: 'name' }]
      })
    
    export const findPlanet = os
      .input(PlanetSchema.pick({ id: true }))
      .handler(async ({ input }) => {
        // your find code here
        return { id: 1, name: 'name' }
      })
    
    export const createPlanet = os
      .$context<{ headers: IncomingHttpHeaders }>()
      .use(({ context, next }) => {
        const user = parseJWT(context.headers.authorization?.split(' ')[1])
    
        if (user) {
          return next({ context: { user } })
        }
    
        throw new ORPCError('UNAUTHORIZED')
      })
      .input(PlanetSchema.omit({ id: true }))
      .handler(async ({ input, context }) => {
        // your create code here
        return { id: 1, name: 'name' }
      })
    
    export const router = {
      planet: {
        list: listPlanet,
        find: findPlanet,
        create: createPlanet
      }
    }
    
  2. Create your server:

    import { createServer } from 'node:http'
    import { RPCHandler } from '@orpc/server/node'
    import { CORSPlugin } from '@orpc/server/plugins'
    
    const handler = new RPCHandler(router, {
      plugins: [new CORSPlugin()]
    })
    
    const server = createServer(async (req, res) => {
      const result = await handler.handle(req, res, {
        context: { headers: req.headers }
      })
    
      if (!result.matched) {
        res.statusCode = 404
        res.end('No procedure matched')
      }
    })
    
    server.listen(
      3000,
      '127.0.0.1',
      () => console.log('Listening on 127.0.0.1:3000')
    )
    
  3. Create your client:

    import type { RouterClient } from '@orpc/server'
    import { createORPCClient } from '@orpc/client'
    import { RPCLink } from '@orpc/client/fetch'
    
    const link = new RPCLink({
      url: 'http://127.0.0.1:3000',
      headers: { Authorization: 'Bearer token' },
    })
    
    export const orpc: RouterClient<typeof router> = createORPCClient(link)
    
  4. Consume your API:

    import { orpc } from './client'
    
    const planets = await orpc.planet.list({ limit: 10 })
    
  5. Generate OpenAPI Spec:

    import { OpenAPIGenerator } from '@orpc/openapi'
    import { ZodToJsonSchemaConverter } from '@orpc/zod'
    
    const generator = new OpenAPIGenerator({
      schemaConverters: [new ZodToJsonSchemaConverter()]
    })
    
    const spec = await generator.generate(router, {
      info: {
        title: 'Planet API',
        version: '1.0.0'
      }
    })
    
    console.log(spec)
    

Sponsors

References

oRPC is inspired by existing solutions that prioritize type safety and developer experience. Special acknowledgments to:

  • tRPC: For pioneering the concept of end-to-end type-safe RPC and influencing the development of type-safe APIs.
  • ts-rest: For its emphasis on contract-first development and OpenAPI integration, which have greatly inspired oRPC’s feature set.

License

Distributed under the MIT License. See LICENSE for more information.

NPM DownloadsLast 30 Days