Skip to content

feat: pass adapter options to tRPC HTTP adapters - #118

Open
yardenhochman wants to merge 1 commit into
KevinEdry:mainfrom
yardenhochman:feat/adapter-options-passthrough
Open

yardenhochman wants to merge 1 commit into
KevinEdry:mainfrom
yardenhochman:feat/adapter-options-passthrough

Conversation

@yardenhochman

Copy link
Copy Markdown

Summary

TRPCModule.forRoot can now pass adapter-specific HTTP options through to the active tRPC Express or Fastify adapter. This keeps the existing behavior when adapterOptions is omitted and preserves NestJS tRPC's ownership of the router, context, and error handler.

Problem

TRPCModule.forRoot exposes context, errorFormatter, and transformer, but it has no way to configure the underlying adapter's other options. For example, tRPC v11's allowMethodOverride lets a query procedure accept POST instead of GET. This matters when a query accepts a bulk array of IDs that exceeds URL-length limits, or contains PII that should not appear in query strings or access logs.

The current workarounds require patching the driver or mounting translation middleware before NestJS tRPC's own mount point.

Solution

Add an optional, typed adapterOptions field and pass it to both HTTP adapters. The adapter options are spread first, followed by the module-owned router, createContext, and onError values, so callers cannot override them. This is a non-breaking change.

TRPCModule.forRoot({
  adapterOptions: {
    allowMethodOverride: true,
  },
});

Validation

  • bun run test — 17 suites and 78 tests passed
  • ts-heavy bun run build — passed

@vercel

vercel Bot commented Sep 3, 2026

Copy link
Copy Markdown

@yardenhochman is attempting to deploy a commit to the Kevin's Projects Team on Vercel.

A member of the Team first needs to authorize it.

@vercel

vercel Bot commented Sep 8, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
nestjs-trpc-docs Ready Ready Preview Sep 8, 2026 9:01pm UTC

Request Review

@KevinEdry

Copy link
Copy Markdown
Owner

Thanks — the passthrough is something the library genuinely needs, and the ownership handling (module keys always win) is the right instinct. I want to change the shape before it merges, though, because this PR surfaced a bigger inconsistency in the options API that I'd rather fix once than paper over.

Today forRoot already passes some tRPC options flat (transformer, errorFormatter), and this PR adds a nested bag for adapter options — which leaves users with two differently-shaped channels and a "which one does my option go in?" question that tracks tRPC's internal layering (root config vs adapter). I don't want the module's API to expose that split. The shape I want instead is a single trpc key that holds everything tRPC, spelled exactly as tRPC spells it:

TRPCModule.forRoot({
  basePath: '/trpc',
  context: AppContext,        // DI class, module-owned
  onError: AppErrorHandler,   // DI class, module-owned
  trpc: {
    transformer: superjson,
    allowMethodOverride: true,
    responseMeta: (opts) => ({ ... }),
  },
});

The rule this gives users: NestJS-shaped options (DI classes, autoSchemaFile, basePath) sit at the top level; anything you'd pass to tRPC itself goes in trpc. router, createContext, and onError stay excluded from the trpc key's type — the module owns those via DI.

What that means concretely, beyond this PR's diff:

  • The module routes trpc keys internally: a small explicit list of root-config keys (transformer, errorFormatter, sse, jsonl) goes to initTRPC.create(), everything else to the active HTTP adapter.
  • Strip the reserved keys (router/createContext/onError) at runtime before spreading, not just in the type — the "cannot be overridden" guarantee should hold from plain JS too.
  • Existing top-level transformer/errorFormatter keep working for now with a deprecation warning, removed in the next major.
  • Driver tests pinning the contract: an option like allowMethodOverride reaches the adapter call, and a reserved key in trpc loses to the module-owned value.

That's a fair bit more than you signed up for, so no pressure either way: happy to have you rework this PR to that shape, or I'll take it from here and credit this PR for the design push. Let me know which you'd prefer.

This branch was successfully deployed

1 active deployment
Preview — e41c4dad Deployed Sep 8, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants