Back to Trpc

Link Options Reference

packages/client/skills/links/references/link-options.md

11.16.014.6 KB
Original Source

Link Options Reference

Terminating link that sends one tRPC operation per HTTP request.

ts
import { httpLink } from '@trpc/client';

httpLink({
  url: 'http://localhost:3000/trpc',
  fetch: customFetch,
  transformer: superjson,
  headers: { Authorization: 'Bearer token' },
  methodOverride: 'POST',
});
OptionTypeDefaultDescription
urlstring | URLrequiredServer endpoint URL
fetchtypeof fetchglobal fetchFetch ponyfill
transformerDataTransformerOptionsnoneData transformer (e.g. superjson)
headersHTTPHeaders | (opts: { op: Operation }) => HTTPHeaders | Promise<HTTPHeaders>{}Static headers object or per-request callback
methodOverride'POST'noneForce all requests as POST

Terminating link that batches multiple operations into a single HTTP request.

ts
import { httpBatchLink } from '@trpc/client';

httpBatchLink({
  url: 'http://localhost:3000/trpc',
  maxURLLength: 2083,
  maxItems: 10,
  headers({ opList }) {
    return { Authorization: `Bearer ${opList[0]?.context.token}` };
  },
  transformer: superjson,
});
OptionTypeDefaultDescription
urlstring | URLrequiredServer endpoint URL
fetchtypeof fetchglobal fetchFetch ponyfill
transformerDataTransformerOptionsnoneData transformer
headersHTTPHeaders | (opts: { opList: Operation[] }) => HTTPHeaders | Promise<HTTPHeaders>{}Headers callback receives opList (array), not op
maxURLLengthnumberInfinitySplit batch if URL exceeds this length
maxItemsnumberInfinityMaximum operations per batch
methodOverride'POST'noneForce all requests as POST

Terminating link similar to httpBatchLink but streams responses as they arrive instead of waiting for all to complete.

ts
import { httpBatchStreamLink } from '@trpc/client';

httpBatchStreamLink({
  url: 'http://localhost:3000/trpc',
  maxURLLength: 2083,
  maxItems: 10,
  transformer: superjson,
  streamHeader: 'accept',
});
OptionTypeDefaultDescription
All httpBatchLink optionsInherits all httpBatchLink options
streamHeader'trpc-accept' | 'accept''trpc-accept'Header used to signal streaming. Use 'accept' to avoid CORS preflight on cross-origin requests.

Sends trpc-accept: application/jsonl (or Accept: application/jsonl). Response arrives as transfer-encoding: chunked with content-type: application/jsonl. Cannot set response headers (including cookies) after stream begins.

Non-terminating link that branches the link chain based on a condition.

ts
import {
  httpBatchLink,
  httpLink,
  httpSubscriptionLink,
  splitLink,
} from '@trpc/client';

splitLink({
  condition: (op) => op.type === 'subscription',
  true: httpSubscriptionLink({ url }),
  false: httpBatchLink({ url }),
});
OptionTypeDefaultDescription
condition(op: Operation) => booleanrequiredRoute predicate
trueTRPCLink | TRPCLink[]requiredLink(s) for condition=true. Must include a terminating link.
falseTRPCLink | TRPCLink[]requiredLink(s) for condition=false. Must include a terminating link.

Each branch creates its own sub-chain, so both branches need a terminating link.

Non-terminating link that logs operations to the console.

ts
import { loggerLink } from '@trpc/client';

loggerLink({
  enabled: (opts) =>
    (process.env.NODE_ENV === 'development' && typeof window !== 'undefined') ||
    (opts.direction === 'down' && opts.result instanceof Error),
  colorMode: 'ansi',
});
OptionTypeDefaultDescription
enabled(opts: { direction: 'up' | 'down'; result?: unknown }) => boolean() => trueControl when logging is active
logger(opts: LoggerOpts) => voidbuilt-in pretty loggerCustom log function
console{ log: Function; error: Function }globalThis.consoleConsole implementation
colorMode'ansi' | 'css' | 'none''css' in browser, 'ansi' in NodeColor output mode
withContextbooleanfalse (true if css)Include operation context in log

Non-terminating link that retries failed operations.

ts
import { retryLink } from '@trpc/client';

retryLink({
  retry(opts) {
    if (opts.error.data?.code === 'INTERNAL_SERVER_ERROR') {
      return opts.attempts <= 3;
    }
    return false;
  },
  retryDelayMs: (attempt) => Math.min(1000 * 2 ** attempt, 30000),
});
OptionTypeDefaultDescription
retry(opts: { op, error, attempts }) => booleanrequiredReturn true to retry
retryDelayMs(attempt: number) => number() => 0Delay between retries in ms

When used with subscriptions that use tracked(), automatically includes the last known event ID on retry.

Terminating link for WebSocket connections. Requires a TRPCWebSocketClient.

ts
import { createWSClient, wsLink } from '@trpc/client';

const wsClient = createWSClient({
  url: 'ws://localhost:3000',
  connectionParams: () => ({ token: 'supersecret' }),
  lazy: { enabled: true, closeMs: 10_000 },
  keepAlive: { enabled: true, intervalMs: 5_000, pongTimeoutMs: 1_000 },
});

wsLink<AppRouter>({
  client: wsClient,
  transformer: superjson,
});
OptionTypeDefaultDescription
clientTRPCWebSocketClientrequiredWebSocket client from createWSClient
transformerDataTransformerOptionsnoneData transformer

createWSClient Options

OptionTypeDefaultDescription
urlstring | (() => MaybePromise<string>)requiredWebSocket server URL
connectionParamsRecord<string, string> | null | (() => MaybePromise<Record<string, string> | null>)nullAuth params sent as first message, available in createContext()
WebSockettypeof WebSocketglobal WebSocketWebSocket ponyfill
retryDelayMs(attemptIndex: number) => numberexponential backoffReconnection delay
onOpen() => voidnoneConnection opened callback
onError(evt?: Event) => voidnoneConnection error callback
onClose(cause?: { code?: number }) => voidnoneConnection closed callback
lazy.enabledbooleanfalseClose WS after inactivity
lazy.closeMsnumber0Idle timeout before closing
keepAlive.enabledbooleanfalseSend ping messages
keepAlive.intervalMsnumber5000Ping interval
keepAlive.pongTimeoutMsnumber1000Close if no pong within this time

Terminating link for Server-Sent Events (SSE) subscriptions.

ts
import { httpSubscriptionLink } from '@trpc/client';
import { EventSourcePolyfill } from 'event-source-polyfill';

httpSubscriptionLink({
  url: 'http://localhost:3000/trpc',
  connectionParams: async () => ({ token: 'supersecret' }),
  transformer: superjson,
  EventSource: EventSourcePolyfill,
  eventSourceOptions: async ({ op }) => ({
    headers: {
      authorization: 'Bearer token',
    },
  }),
});
OptionTypeDefaultDescription
urlstring | (() => string | Promise<string>)requiredServer endpoint URL
connectionParamsRecord<string, string> | null | (() => MaybePromise<...>)noneSerialized as URL query param
transformerDataTransformerOptionsnoneData transformer
EventSourceEventSource constructorglobal EventSourceEventSource ponyfill for custom headers
eventSourceOptionsEventSourceInit | ((opts: { op }) => EventSourceInit | Promise<EventSourceInit>)noneOptions passed to EventSource constructor

For cross-domain cookies, use eventSourceOptions: () => ({ withCredentials: true }).

Terminating link for direct procedure calls without HTTP. Useful for testing and server-side usage.

ts
import { unstable_localLink } from '@trpc/client';
import { appRouter } from './server';

unstable_localLink({
  router: appRouter,
  createContext: async () => ({ db: prisma }),
  onError: (opts) => console.error('Error:', opts.error),
});
OptionTypeDefaultDescription
routerAnyRouterrequiredtRPC router instance
createContext() => Promise<Context>requiredContext factory per call
onError(opts: ErrorHandlerOptions) => voidnoneError handler
transformerDataTransformerOptionsnoneData transformer