oRPC
background

Middleware

The powerful and flexible way to reuse logic across procedures in oRPC.

Introduction

Middleware in oRPC is both powerful and flexible, enabling you to accomplish many tasks efficiently.

import { ,  } from '@orpc/server'
 
export type  = { ?: { : string } }
 
// global osw completely optional, needed when you want to use context
export const  /** os with ... */ = .<>()
 
const  = .(async (, , ) => {
    .(async () => {
        // Invoked after successful handler execution
        // Other callbacks: onError, onFinish
    })
 
    if (!.) {
        throw new ({
            : 'UNAUTHORIZED',
            : 'You need to log in first',
        })
    }
 
    return {
        : {
            : .,
        }
    }
})
 
// Now every procedure or router defined in this oRPC will be protected by authMiddleware
const  = .()

Typed Input

Middleware can expect specific input types, opening up many possibilities:

import { ,  } from '@orpc/server'
import {  } from 'zod' 
 
const  = 
    .(async (: {: string}, , ) => { 
        // Now you can specify the input type for middleware
    })
 

    .(.({ : .() }))
    .(canEditPostMiddleware) // ❗ mismatched input type
Argument of type 'DecoratedMiddleware<Record<string, unknown> | undefined, undefined, { id: string; }, unknown>' is not assignable to parameter of type 'Middleware<Record<string, unknown> | undefined, undefined, { postId: string; }, unknown>'. Types of parameters 'input' and 'input' are incompatible. Property 'id' is missing in type '{ postId: string; }' but required in type '{ id: string; }'.
.(, () => ({ : . })) // ✅ map the input to match expected type

Concatenation

You can merge or extend middlewares using concatenation:

import {  } from '@orpc/server'
 
const  = .(async (, , ) => {})
const  = .(async (, , ) => {})
 
const  = .() // Merge middleware
 
const  = .((, , ) => {}) // Extend middleware

Extra Context

Extra context is created by middlewares and automatically merges with the global context, enhancing developer experience:

import { ,  } from '@orpc/server'
 
type  = {
    ?: {
        : string
    }
}
 
const  = .<>()
 
// Any procedure using this middleware will infer context.user as NonNullable<typeof context['user']>
const  = 
    .(async (, , ) => {
        if (!.) {
            throw new ({ : 'UNAUTHORIZED' })
        }
 
        return {
            : {
                : .
            }
        }
    })
 
const  = 
    .()
    .((, , ) => {
 
        const : <typeof ['user']> = .
 
        return {
            : {
                : 'hi'
            }
        }
    })
    .(async (, , ) => {
        
        const : <typeof ['user']> = .
        const : string = .
 
    })

Fundamentals

In oRPC, middleware is simply a JavaScript function, making it easy to customize:

import { ,  } from '@orpc/server'
 
export type  = { ?: { : string } }
 
const  = .<>().(async (, , ) => {})
 
// This is equivalent to:
 
const  = async (: unknown, : , : <unknown>): <void> => {
 
}

On this page