Built-in middleware
The middleware in @trpc12/trpc/middleware, for logging, rate limits, locks and durable calls, and how to apply it.
@trpc12/trpc/middleware has middleware for common jobs. Each one is ordinary middleware: apply it with .use() on a procedure or a base procedure, and give the handler the layer it needs, if any.
import { function onError(fn: (error: AnyTrpcError, opts: AnyOpts) => MaybePromise<void>): MiddlewareFunction<unknown, unknown, unknown, {}, never>onError } from '@trpc12/trpc/middleware';
const const logged: ProcedureBuilder<With<RootDef<Context, {}>, {
ctx: Context;
ctxAdded: {};
inputOut: Unset;
errors: never;
shorts: never;
}>>
logged = const t: TrpcRoot<Context, {}, RootDef<Context, {}>>t.TrpcRoot<Context, {}, RootDef<Context, {}>>.procedure: ProcedureBuilder<RootDef<Context, {}>>procedure.ProcedureBuilder<RootDef<Context, {}>>.use<{}, never, never, Unset, object>(fn: MiddlewareFunction<{
user: User | null;
} & object, undefined, {}, {}, never, never, Unset>): ProcedureBuilder<With<RootDef<Context, {}>, {
ctx: Context;
ctxAdded: {};
inputOut: Unset;
errors: never;
shorts: never;
}>> (+1 overload)
use(
function onError(fn: (error: AnyTrpcError, opts: AnyOpts) => MaybePromise<void>): MiddlewareFunction<unknown, unknown, unknown, {}, never>onError((err: AnyTrpcErrorerr, opts: AnyOptsopts) => var console: Consoleconsole.Console.error(...data: any[]): voiderror(opts: AnyOptsopts.MiddlewareOpts<unknown, unknown, unknown>.path: stringpath, err: AnyTrpcErrorerr.TrpcError<string, any>.code: stringcode)),
);| Middleware | Does | Needs on the handler |
|---|---|---|
| Lifecycle hooks | onStart, onSuccess, onError and onFinish run code around each call, for logs and metrics | nothing |
| Rate limiting | rateLimit() fails calls past a limit per key, and sets the RateLimit headers | a RateLimiter layer, in memory or Redis |
| Locks | experimental_lock() runs calls with the same key one at a time, across instances | an experimental_Locker layer, in memory, Redis or Durable Objects |
| Durable calls | experimental_durable() keeps a call's result, so a client that lost the response gets it instead of running the mutation twice | a BackingPersistence layer |
To add middleware, context, meta and errors to every procedure of an app from a package, see Extensions.