Skip to content

Context in oRPC

oRPC’s context mechanism provides a type-safe dependency injection pattern. It lets you supply required dependencies either explicitly or dynamically through middleware. There are two types:

  • Initial Context: Provided explicitly when invoking a procedure.
  • Execution Context: Generated during procedure execution, typically by middleware.

Initial Context

Initial context is used to define required dependencies (usually environment-specific) that must be passed when calling a procedure.

ts
const 
base
=
os
.
$context
<{
headers
: Headers,
env
: {
DB_URL
: string } }>()
const
getting
=
base
.
handler
(async ({
context
}) => {
console
.
log
(
context
.
env
)
}) export const
router
= {
getting
}

When calling that requires initial context, pass it explicitly:

ts
import { 
RPCHandler
} from '@orpc/server/fetch'
const
handler
= new
RPCHandler
(
router
)
export default function
fetch
(
request
: Request) {
handler
.
handle
(
request
, {
context
: { // <-- you must pass initial context here
headers
:
request
.
headers
,
env
: {
DB_URL
: '***'
} } }) }

Execution context

Execution context is computed during the process lifecycle—usually via middleware. It can be used independently or combined with initial context.

ts
import { 
cookies
,
headers
} from 'next/headers'
const
base
=
os
.
use
(async ({
next
}) =>
next
({
context
: {
headers
: await
headers
(),
cookies
: await
cookies
(),
}, })) const
getting
=
base
.
handler
(async ({
context
}) => {
context
.
cookies
.
set
('key', 'value')
}) export const
router
= {
getting
}

When using execution context, you don’t need to pass any context manually:

ts
import { 
RPCHandler
} from '@orpc/server/fetch'
const
handler
= new
RPCHandler
(
router
)
export default function
fetch
(
request
: Request) {
handler
.
handle
(
request
) // <-- no need to pass anything more
}

Combining Initial and Execution Context

Often you need both static and dynamic dependencies. Use initial context for environment-specific values (e.g., database URLs) and middleware (execution context) for runtime data (e.g., user authentication).

ts
const 
base
=
os
.
$context
<{
headers
: Headers,
env
: {
DB_URL
: string } }>()
const
requireAuth
=
base
.
middleware
(async ({
context
,
next
}) => {
const
user
=
parseJWT
(
context
.
headers
.
get
('authorization')?.
split
(' ')[1])
if (
user
) {
return
next
({
context
: {
user
} })
} throw new
ORPCError
('UNAUTHORIZED')
}) const
dbProvider
=
base
.
middleware
(async ({
context
,
next
}) => {
const
client
= new
Client
(
context
.
env
.
DB_URL
)
try { await
client
.
connect
()
return
next
({
context
: {
db
:
client
} })
} finally { await
client
.
disconnect
()
} }) const
getting
=
base
.
use
(
dbProvider
)
.
use
(
requireAuth
)
.
handler
(async ({
context
}) => {
console
.
log
(
context
.
db
)
console
.
log
(
context
.
user
)
})

Released under the MIT License.