Context
The context mechanism provides a type-safe dependency injection pattern. It lets you provide required dependencies explicitly or inject them dynamically through middleware.
Initial Context
Use initial context for values that come from the environment. Declare it with .$context, then provide it when executing the procedure:
const const base: Builder<{
env: {
DB_URL: string;
};
} & object, Record<never, never>>
base = const os: Builder<DefaultInitialContext & object, Record<never, never>>The oRPC procedure builder. Chain methods like `.input`, `.use`, and `.handler`
to define procedures, then compose them into routers.os.Builder<DefaultInitialContext & object, Record<never, never>>.$context<{
env: {
DB_URL: string;
};
}>(): Builder<{
env: {
DB_URL: string;
};
} & object, Record<never, never>>
$context<{ env: {
DB_URL: string;
}
env: { type DB_URL: stringDB_URL: string } }>()
export const const getting: DecoratedProcedure<{
env: {
DB_URL: string;
};
} & object, object, InitialInputSchema, Schema<void>, Record<never, never>, never>
getting = const base: Builder<{
env: {
DB_URL: string;
};
} & object, Record<never, never>>
base
.Builder<{ env: { DB_URL: string; }; } & object, Record<never, never>>.handler<void>(handler: ProcedureHandler<{
env: {
DB_URL: string;
};
} & object, unknown, void, ORPCErrorConstructorMap<Record<never, never>>>): DecoratedProcedure<{
env: {
DB_URL: string;
};
} & object, object, InitialInputSchema, Schema<void>, Record<never, never>, never>
handler(async ({ context: {
env: {
DB_URL: string;
};
} & object
context }) => {
var console: Consoleconsole.Console.log(...data: any[]): voidThe **`console.log()`** static method outputs a message to the console.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static)log(context: {
env: {
DB_URL: string;
};
} & object
context.env: {
DB_URL: string;
}
env)
})
Default Initial Context
To avoid repeating .$context declarations, you can define a default initial context type globally.
declare module '@orpc/server' {
export interface DefaultInitialContext {
env: { DB_URL: string }
}
}
Injected Context
Injected context is injected at runtime through middleware:
const const base: BuilderWithMiddlewares<DefaultInitialContext & object, {
env: {
DB_URL: string;
};
}, Record<never, never>>
base = const os: Builder<DefaultInitialContext & object, Record<never, never>>The oRPC procedure builder. Chain methods like `.input`, `.use`, and `.handler`
to define procedures, then compose them into routers.os.Builder<DefaultInitialContext & object, Record<never, never>>.use<{
env: {
DB_URL: string;
};
}, DefaultInitialContext & object, Record<never, never>>(middleware: Middleware<DefaultInitialContext & object, {
env: {
DB_URL: string;
};
}, unknown, unknown, Record<never, never>>): BuilderWithMiddlewares<DefaultInitialContext & object, {
env: {
DB_URL: string;
};
}, Record<never, never>>
use(async ({ next: MiddlewareNext<unknown>Invoke to continue the middleware chain.next }) => next: MiddlewareNext
<{
env: {
DB_URL: string;
};
}>(options: {
context: {
env: {
DB_URL: string;
};
};
}) => MiddlewareResult<{
env: {
DB_URL: string;
};
}, unknown>
Invoke to continue the middleware chain.next({
context: {
env: {
DB_URL: string;
};
}
context: {
env: {
DB_URL: string;
}
env: { type DB_URL: stringDB_URL: const env: {
DB_URL: string;
}
env.type DB_URL: stringDB_URL },
},
}))
export const const getting: DecoratedProcedure<DefaultInitialContext & object, {
env: {
DB_URL: string;
};
}, InitialInputSchema, Schema<void>, Record<never, never>, never>
getting = const base: BuilderWithMiddlewares<DefaultInitialContext & object, {
env: {
DB_URL: string;
};
}, Record<never, never>>
base.BuilderWithMiddlewares<DefaultInitialContext & object, { env: { DB_URL: string; }; }, Record<never, never>>['handler']<void>(handler: ProcedureHandler<Omit<DefaultInitialContext & object, "env"> & {
env: {
DB_URL: string;
};
}, unknown, void, ORPCErrorConstructorMap<Record<never, never>>>): DecoratedProcedure<DefaultInitialContext & object, {
env: {
DB_URL: string;
};
}, InitialInputSchema, Schema<void>, Record<never, never>, never>
handler(async ({ context: Omit<DefaultInitialContext & object, "env"> & {
env: {
DB_URL: string;
};
}
context }) => {
var console: Consoleconsole.Console.log(...data: any[]): voidThe **`console.log()`** static method outputs a message to the console.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static)log(context: Omit<DefaultInitialContext & object, "env"> & {
env: {
DB_URL: string;
};
}
context.env: {
DB_URL: string;
}
env)
})
Combining Initial and Injected Context
In many cases, you will use both. Use initial context for environment-specific values, such as database URLs, and injected context for runtime data, such as authenticated users.
const const base: Builder<{
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object, Record<never, never>>
base = const os: Builder<DefaultInitialContext & object, Record<never, never>>The oRPC procedure builder. Chain methods like `.input`, `.use`, and `.handler`
to define procedures, then compose them into routers.os.Builder<DefaultInitialContext & object, Record<never, never>>.$context<{
headers: Headers;
env: {
JWT_SECRET: string;
};
}>(): Builder<{
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object, Record<never, never>>
$context<{ headers: Headersheaders: Headers, env: {
JWT_SECRET: string;
}
env: { type JWT_SECRET: stringJWT_SECRET: string } }>()
const const requireAuth: DecoratedMiddleware<{
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object, {
user: {
userId: number;
};
}, unknown, any, Record<never, never>>
requireAuth = const base: Builder<{
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object, Record<never, never>>
base.Builder<{ headers: Headers; env: { JWT_SECRET: string; }; } & object, Record<never, never>>.middleware<{
user: {
userId: number;
};
}, unknown, any>(middleware: Middleware<{
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object, {
user: {
userId: number;
};
}, unknown, any, Record<never, never>>): DecoratedMiddleware<{
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object, {
user: {
userId: number;
};
}, unknown, any, Record<never, never>>
middleware(async ({ context: {
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object
context, next: MiddlewareNext<any>Invoke to continue the middleware chain.next }) => {
const const user: {
userId: number;
} | null
user = function parseJWT(token: string | undefined, secret: string): {
userId: number;
} | null
parseJWT(
context: {
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object
context.headers: Headersheaders.Headers.get(name: string): string | nullThe **`get()`** method of the Headers interface returns a byte string of all the values of a header within a Headers object with a given name. If the requested header doesn't exist in the Headers object, it returns null.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/Headers/get)get('authorization')?.String.split(separator: string | RegExp, limit?: number): string[] (+1 overload)Split a string into substrings using the specified separator and return them as an array.split(' ')[1],
context: {
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object
context.env: {
JWT_SECRET: string;
}
env.type JWT_SECRET: stringJWT_SECRET
)
if (!const user: {
userId: number;
} | null
user) {
throw new new ORPCError<"UNAUTHORIZED", unknown>(code: "UNAUTHORIZED", options?: ORPCErrorOptions<unknown> | undefined): ORPCError<"UNAUTHORIZED", unknown>Typed error carrying a `code`, a `message`, and optional `data`.
Throw it from handlers or middleware to produce typed error responses on the client.ORPCError('UNAUTHORIZED')
}
return next: MiddlewareNext
<{
user: {
userId: number;
};
}>(options: {
context: {
user: {
userId: number;
};
};
}) => MiddlewareResult<{
user: {
userId: number;
};
}, any>
Invoke to continue the middleware chain.next({ context: {
user: {
userId: number;
};
}
context: { user: {
userId: number;
}
user } })
})
const const getting: DecoratedProcedure<{
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object, {
user: {
userId: number;
};
}, InitialInputSchema, Schema<void>, Record<never, never>, never>
getting = const base: Builder<{
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object, Record<never, never>>
base
.Builder<{ headers: Headers; env: { JWT_SECRET: string; }; } & object, Record<never, never>>.use<{
user: {
userId: number;
};
}, {
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object, Record<never, never>>(middleware: Middleware<{
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object, {
user: {
userId: number;
};
}, unknown, unknown, Record<never, never>>): BuilderWithMiddlewares<{
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object, {
user: {
userId: number;
};
}, Record<never, never>>
use(const requireAuth: DecoratedMiddleware<{
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object, {
user: {
userId: number;
};
}, unknown, any, Record<never, never>>
requireAuth)
.BuilderWithMiddlewares<{ headers: Headers; env: { JWT_SECRET: string; }; } & object, { user: { userId: number; }; }, Record<never, never>>['handler']<void>(handler: ProcedureHandler<Omit<{
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object, "user"> & {
user: {
userId: number;
};
}, unknown, void, ORPCErrorConstructorMap<Record<never, never>>>): DecoratedProcedure<{
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object, {
user: {
userId: number;
};
}, InitialInputSchema, Schema<void>, Record<never, never>, never>
handler(async ({ context: Omit<{
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object, "user"> & {
user: {
userId: number;
};
}
context }) => {
var console: Consoleconsole.Console.log(...data: any[]): voidThe **`console.log()`** static method outputs a message to the console.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static)log(context: Omit<{
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object, "user"> & {
user: {
userId: number;
};
}
context.env: {
JWT_SECRET: string;
}
env)
var console: Consoleconsole.Console.log(...data: any[]): voidThe **`console.log()`** static method outputs a message to the console.
[MDN Reference](https://developer.mozilla.org/docs/Web/API/console/log_static)log(context: Omit<{
headers: Headers;
env: {
JWT_SECRET: string;
};
} & object, "user"> & {
user: {
userId: number;
};
}
context.user: {
userId: number;
}
user)
})