# rpc.do

> Managed RPC implementation for the .do platform with oauth.do authentication and cli.do tooling

Latest version **0.3.0** (published 2026-09-29) · MIT license · 0 weekly downloads

## Install

```sh
npm install rpc.do
pnpm add rpc.do
yarn add rpc.do
bun add rpc.do
```

Provides the command `rpc.do`.

## Health

**Score 70/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; recently updated; high maintenance score; high quality score.

Warnings: low downloads; pre 1.0.

## Facts

| | |
|---|---|
| Version | 0.3.0 |
| Published | 2026-09-29 |
| First published | 2025-12-04 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=20.0.0 |
| Dependencies | 1 |
| Unpacked size | 483.6 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 1 |
| Author | Platform.do |
| Maintainers | nathanclevenger |
| Keywords | rpc, proxy, capnweb, transport, websocket, http, cloudflare, workers |

## Links

- npm: https://www.npmjs.com/package/rpc.do
- Repository: https://github.com/dot-do/rpc.do
- Homepage: https://rpc.do
- Issues: https://github.com/dot-do/rpc.do/issues
- npm.io page: https://npm.io/package/rpc.do

## Dependencies (1)

- [capnweb](https://npm.io/package/capnweb.md) ^0.12.0

## Alternatives

- [@opentelemetry/exporter-zipkin](https://npm.io/package/@opentelemetry/exporter-zipkin.md) — 14.8M weekly downloads
- [pusher-js](https://npm.io/package/pusher-js.md) — 2.0M weekly downloads
- [browserify](https://npm.io/package/browserify.md) — 1.7M weekly downloads
- [sqs-consumer](https://npm.io/package/sqs-consumer.md) — 1.7M weekly downloads
- [@sanity/eventsource](https://npm.io/package/@sanity/eventsource.md) — 930.8K weekly downloads

## Recent versions

- 0.3.0 (latest) — 2026-09-29
- 0.2.4 — 2026-01-31
- 0.2.3 — 2026-01-26
- 0.2.2 — 2026-01-26
- 0.2.1 — 2026-01-24
- 0.2.0 — 2026-01-23
- 0.1.4 — 2025-12-11
- 0.1.3 — 2025-12-11
- 0.1.2 — 2025-12-05
- 0.1.1 — 2025-12-04
- 0.1.0 — 2025-12-04

## README

# rpc.do

Access your Durable Object's SQL, storage, and collections remotely -- same API locally and over the network.

[![npm](https://img.shields.io/npm/v/rpc.do)](https://npmjs.com/package/rpc.do)
![CI](https://github.com/dot-do/rpc.do/actions/workflows/ci.yml/badge.svg)
[![codecov](https://codecov.io/gh/dot-do/rpc.do/branch/main/graph/badge.svg)](https://codecov.io/gh/dot-do/rpc.do)

```bash
npm install rpc.do
```

## The Idea

Inside a Durable Object you write `this.sql`, `this.storage`, `this.collection('users')`. With rpc.do, the exact same API works remotely:

```typescript
import { RPC } from 'rpc.do'

const $ = RPC('https://my-do.workers.dev')

// SQL -- tagged templates with automatic parameterization
const users = await $.sql`SELECT * FROM users WHERE active = ${true}`.all()
const user  = await $.sql`SELECT * FROM users WHERE id = ${id}`.first()
await $.sql`UPDATE users SET name = ${name} WHERE id = ${id}`.run()

// Storage -- key-value, same as this.storage inside the DO
const config = await $.storage.get('config')
await $.storage.put('config', { theme: 'dark' })

// Collections -- MongoDB-style queries on DO SQLite
const admins = await $.collection('users').find({ role: 'admin', active: true })
await $.collection('users').put('user-123', { name: 'Alice', role: 'admin' })

// Custom RPC methods -- whatever you define on your DO class
const result = await $.users.create({ name: 'Alice', email: 'alice@co.com' })
```

No code generation. No schema files. The proxy accumulates property paths at runtime and the server dispatches them to your Durable Object.

## Why rpc.do?

rpc.do is not another REST/GraphQL/tRPC alternative. It is purpose-built for Cloudflare Durable Objects.

- **Same API locally and remotely** -- `$.sql`, `$.storage`, `$.collection` mirror the DO's internal APIs so your mental model stays the same whether you are inside the DO or calling from a Worker, browser, or CLI.
- **Purpose-built for Durable Objects** -- First-class access to DO SQLite, KV storage, collections, schema introspection, and WebSocket hibernation. Not a generic RPC bolted onto DOs.
- **Built on capnweb** -- Promise pipelining, pass-by-reference, and batched calls over HTTP or WebSocket. Multiple calls in a single round trip.
- **Zero-config type generation** -- Point `npx rpc.do generate` at your DO source and get a fully typed client. No schema language to learn.
- **Lightweight** -- ~3KB core. Proxy-based, no build step, no runtime dependencies beyond your transport.

## Packages

The system is split into two packages with distinct roles:

| Package | Role | Install |
|---------|------|---------|
| [`@dotdo/rpc`](./core/README.md) | **Server** -- Extend your Durable Object with RPC, SQL, collections, events, and WebSocket hibernation | `npm i @dotdo/rpc` |
| [`rpc.do`](https://npmjs.com/package/rpc.do) | **Client** -- Connect to any `@dotdo/rpc`-powered DO from a Worker, browser, Node, or CLI | `npm i rpc.do` |

### Server: `@dotdo/rpc`

Define your Durable Object by extending `DurableRPC`. Every public method and namespace becomes callable over RPC, and the built-in SQL, storage, and collections are automatically exposed:

```typescript
import { DurableRPC } from '@dotdo/rpc'

export class UserService extends DurableRPC {
  users = this.collection<User>('users')

  async createUser(id: string, data: User) {
    this.users.put(id, data)
    return { id, ...data }
  }

  async getActiveUsers() {
    return this.users.find({ active: true })
  }

  admin = {
    listAll: () => this.users.list(),
    count:   () => this.users.count(),
  }
}
```

### Client: `rpc.do`

Connect from anywhere. The client auto-selects transport from the URL scheme:

```typescript
import { RPC } from 'rpc.do'

// HTTP (https://)
const $ = RPC('https://my-do.workers.dev')

// WebSocket (wss://) -- real-time, hibernation-aware
const $ = RPC('wss://my-do.workers.dev')

// Typed client
const $ = RPC<UserServiceAPI>('https://my-do.workers.dev')
const user = await $.getActiveUsers()  // fully typed
```

## How to Connect

rpc.do supports multiple transports. The URL-based `RPC(url)` API handles the common cases automatically. For advanced scenarios, use explicit transports:

```typescript
import { RPC, http, capnweb, binding, composite } from 'rpc.do'

// HTTP -- request/response, serverless-friendly
const $ = RPC(http('https://my-do.workers.dev'))

// capnweb WebSocket -- real-time, pipelining, bidirectional
const $ = RPC(capnweb('wss://my-do.workers.dev'))

// Cloudflare Service Binding -- zero-latency worker-to-DO
const $ = RPC(binding(env.MY_DO))

// Fallback chain -- try WebSocket, fall back to HTTP
const $ = RPC(composite(
  capnweb('wss://my-do.workers.dev'),
  http('https://my-do.workers.dev')
))
```

### Authentication

```typescript
// Bearer token
const $ = RPC('https://my-do.workers.dev', { auth: 'sk_live_xxx' })

// oauth.do integration
import { oauthProvider } from 'rpc.do/auth'
const $ = RPC('https://my-do.workers.dev', { auth: oauthProvider() })
```

### Error Handling

```typescript
import { ConnectionError, RPCError } from 'rpc.do/errors'

try {
  await $.users.get({ id: '123' })
} catch (error) {
  if (error instanceof ConnectionError && error.retryable) {
    // Retry the operation
  }
}
```

## Documentation

- [Getting Started Guide](docs/GETTING_STARTED.md) -- Step-by-step tutorial
- [API Reference](docs/API_REFERENCE.md) -- Complete API documentation
- [Architecture](docs/ARCHITECTURE.md) -- Technical design and internals
- [Troubleshooting](docs/TROUBLESHOOTING.md) -- Common issues and solutions
- [Performance Benchmarks](BENCHMARKS.md) -- Latency, throughput, and bundle size analysis
- [rpc.do vs Alternatives](docs/COMPARISON.md) -- Decision guide for choosing RPC tools
- [Migrating from tRPC](docs/MIGRATING_FROM_TRPC.md)
- [Migrating from gRPC](docs/MIGRATING_FROM_GRPC.md)
- [React Integration](docs/REACT_INTEGRATION.md)

## License

MIT

---
_Source: https://npm.io/package/rpc.do · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
