createORPCClient(link)
Creates a fully type-safe client-side client from a ClientLink.
import type { RouterClient } from '@orpc/server'
import { createORPCClient } from '@orpc/client'
import { RPCLink } from '@orpc/client/fetch'
const link = new RPCLink({
url: 'https://api.example.com',
})
export const orpc: RouterClient<typeof router> = createORPCClient(link)
// Call procedures:
const planets = await orpc.planet.list({ limit: 10 })
Options
Base path for all calls. Useful for calling a subset of the router.const planetClient = createORPCClient(link, { path: ['planet'] })
await planetClient.list({ limit: 5 })
createSafeClient(client)
Wraps every procedure call with the safe() utility. Instead of throwing, it returns { data, error, isDefined } tuples.
import { createSafeClient } from '@orpc/client'
const safeClient = createSafeClient(orpc)
const { data, error, isDefined } = await safeClient.planet.find({ id: 1 })
if (error) {
if (isDefined) {
// typed ORPCError
console.log(error.code, error.data)
} else {
// undefined/unknown error
}
} else {
console.log(data)
}
RPCLink
The standard link for calling oRPC servers over HTTP.
import { RPCLink } from '@orpc/client/fetch' // for Fetch, Edge, and Node.js 18+
Constructor options
new RPCLink({
url: 'https://api.example.com',
headers: {
Authorization: 'Bearer token',
},
fetch: customFetch, // optional custom fetch implementation
})
The base URL of your oRPC server.
Static headers or an async function that returns headers per request.headers: async () => ({
Authorization: `Bearer ${await getToken()}`,
})
Custom fetch implementation. Defaults to the global fetch.
Array of client-side plugins for request/response transformation.
DynamicLink
A link that dynamically resolves to another link based on the request path, input, and context. Useful for routing to different backends or switching between environments.
import { DynamicLink } from '@orpc/client'
import { RPCLink } from '@orpc/client/fetch'
const dynamicLink = new DynamicLink(async (options, path, input) => {
if (path[0] === 'admin') {
return new RPCLink({ url: 'https://admin.api.example.com' })
}
return new RPCLink({ url: 'https://api.example.com' })
})
const orpc = createORPCClient(dynamicLink)
Resolver signature
new DynamicLink<TClientContext>(
resolver: (
options: ClientOptions<TClientContext>,
path: readonly string[],
input: unknown,
) => Promisable<ClientLink<TClientContext>>
)
ORPCError
The error class used throughout oRPC. Thrown by servers and received by clients.
import { ORPCError } from '@orpc/client'
Properties
| Property | Type | Description |
|---|
code | string | Error code (e.g. 'NOT_FOUND', 'UNAUTHORIZED') |
status | number | HTTP status code |
message | string | Human-readable message |
data | TData | Optional typed payload attached to the error |
defined | boolean | true if the error was declared in an error map |
cause | unknown | Underlying cause (standard ErrorOptions) |
toJSON()
Serializes the error to a plain object for transport:
error.toJSON()
// => { defined, code, status, message, data }
Common error codes
| Code | Status |
|---|
BAD_REQUEST | 400 |
UNAUTHORIZED | 401 |
FORBIDDEN | 403 |
NOT_FOUND | 404 |
CONFLICT | 409 |
UNPROCESSABLE_CONTENT | 422 |
TOO_MANY_REQUESTS | 429 |
INTERNAL_SERVER_ERROR | 500 |
isDefinedError(error)
Narrowing helper. Returns true if error is an ORPCError with defined === true (i.e., declared in an error map).
import { isDefinedError } from '@orpc/client'
try {
await orpc.planet.find({ id: 999 })
} catch (err) {
if (isDefinedError(err)) {
// err is ORPCError<any, any> with .defined === true
console.log(err.code) // 'NOT_FOUND'
}
}
safe(promise)
Wraps a promise and returns a [error, data, isDefined] tuple instead of throwing.
import { safe } from '@orpc/client'
const [error, data] = await safe(orpc.planet.find({ id: 1 }))
if (error) {
console.log('Error:', error.message)
} else {
console.log('Planet:', data)
}
Return type
A 4-tuple (also accessible as named properties):
type SafeResult<TOutput, TError> =
// Success
| [error: null, data: TOutput, isDefined: false, isSuccess: true]
// Undefined (untyped) error
| [error: Exclude<TError, ORPCError<any, any>>, data: undefined, isDefined: false, isSuccess: false]
// Defined (typed) ORPCError
| [error: Extract<TError, ORPCError<any, any>>, data: undefined, isDefined: true, isSuccess: false]
Each element is also available as a named property: result.error, result.data, result.isDefined, result.isSuccess.
Client plugins
Client plugins implement the StandardLinkPlugin<T> interface from @orpc/client/standard. Built-in plugins are available from @orpc/client/plugins:
import {
ClientRetryPlugin,
BatchLinkPlugin,
DedupeRequestsPlugin,
RetryAfterPlugin,
SimpleCsrfProtectionLinkPlugin,
} from '@orpc/client/plugins'
Pass plugins to RPCLink:
import { RPCLink } from '@orpc/client/fetch'
import { ClientRetryPlugin } from '@orpc/client/plugins'
const link = new RPCLink({
url: 'https://api.example.com',
plugins: [new ClientRetryPlugin({ default: { retry: 3 } })],
})