Skip to content
 
 

Latest commit

 

History

1,312 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.
  • 🔍 First-Class OpenTelemetry: Seamlessly integrate with OpenTelemetry for observability.
  • ⚙️ Framework Integrations: Seamlessly integrate with TanStack Query (React, Vue, Solid, Svelte, Angular), SWR, 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.

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 * as 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/zod4'
    
    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

If you find oRPC valuable and would like to support its development, you can do so here: GitHub Sponsors.

Special Sponsor

ScreenshotOne.com
ScreenshotOne.com

Premium Sponsor

MisskeyHQ
MisskeyHQ

Organization Sponsor

LN Markets
LN Markets

Sponsor

Reece McDonald
Reece McDonald
あわわわとーにゅ
あわわわとーにゅ
nk
nk
supastarter
supastarter
Dexter Miguel
Dexter Miguel
herrfugbaum
herrfugbaum
Ryota Murakami
Ryota Murakami
David Cramer
David Cramer
Valerii Petryniak
Valerii Petryniak
Valerii Strilets
Valerii Strilets
Kyle Mistele
Kyle Mistele
christ12938
christ12938
Ryan Soderberg
Ryan Soderberg
shota
shota
Ellis Driscoll
Ellis Driscoll
Hoang Nguyen
Hoang Nguyen
Orestis Ioannou
Orestis Ioannou

Backer

David Walsh
David Walsh
Robbe Vaes
Robbe Vaes
Aidan Sunbury
Aidan Sunbury
soonoo
soonoo
Kevin Porten
Kevin Porten
Denis
Denis
Christopher Kapic
Christopher Kapic
Tom Ballinger
Tom Ballinger
Sam
Sam
Titoine
Titoine
Igor Makowski
Igor Makowski
hanayashiki
hanayashiki
Lev Dubinets
Lev Dubinets
Kelly Peilin Chan
Kelly Peilin Chan
Guy Ariely
Guy Ariely
Alex
Alex
Andrey Gubanov
Andrey Gubanov

Past Sponsors

Maxie IPV4Address Zuplo motopods Francisco Hermida Théo LUDWIG Abhay Ramesh shr.ink oü 0x4e32 Ryuz happyboy yicchi Saksham Roman Hrynevych rokitg Omar Khatib Yu-Sabo Bapusaheb Patil grim Nelson Lai Lê Cao Nguyên Robert Soriano Andrew Peters Ryan Vogel SKostyukovich Peter Adam Fabworks Novak Antonijevic Laduni Estu Syalwa Chen, Zhi-Yuan Illarion Koperski Anees Iqbal Sefa Eyeoglu natt Adam Tkaczyk plancraft Nicholas

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.

About

Typesafe APIs Made Simple 🪄

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages