UNPKG

@trpc/server

Version:

The tRPC server library

1 lines • 8.55 kB
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/adapters/fastify/fastifyRequestHandler.ts","../../../src/adapters/fastify/fastifyTRPCPlugin.ts"],"sourcesContent":["/**\n * If you're making an adapter for tRPC and looking at this file for reference, you should import types and functions from `@trpc/server` and `@trpc/server/http`\n *\n * @example\n * ```ts\n * import type { AnyTRPCRouter } from '@trpc/server'\n * import type { HTTPBaseHandlerOptions } from '@trpc/server/http'\n * ```\n */\nimport type { FastifyReply, FastifyRequest } from 'fastify';\n// @trpc/server\nimport type { AnyRouter } from '../../@trpc/server';\n// @trpc/server/http\nimport {\n resolveResponse,\n type HTTPBaseHandlerOptions,\n type ResolveHTTPRequestOptionsContextFn,\n} from '../../@trpc/server/http';\n// @trpc/server/node-http\nimport type { NodeHTTPRequest } from '../node-http';\nimport {\n incomingMessageToRequest,\n type NodeHTTPCreateContextOption,\n} from '../node-http';\n\n/** The options of the Fastify adapter's request handler. */\nexport type FastifyHandlerOptions<\n TRouter extends AnyRouter,\n TRequest extends FastifyRequest,\n TResponse extends FastifyReply,\n> = HTTPBaseHandlerOptions<TRouter, TRequest> & {\n /**\n * The largest request body, in bytes. A larger one gets a\n * `PAYLOAD_TOO_LARGE` error. It applies to bodies tRPC streams, such as\n * `multipart/form-data`; JSON bodies are read by Fastify, so limit them\n * with Fastify's `bodyLimit`.\n */\n maxBodySize?: number;\n} & NodeHTTPCreateContextOption<TRouter, TRequest, TResponse>;\n\ntype FastifyRequestHandlerOptions<\n TRouter extends AnyRouter,\n TRequest extends FastifyRequest,\n TResponse extends FastifyReply,\n> = FastifyHandlerOptions<TRouter, TRequest, TResponse> & {\n req: TRequest;\n res: TResponse;\n path: string;\n};\n\n/**\n * Handles one Fastify request for a router. `fastifyTRPCPlugin` uses it;\n * call it yourself to mount tRPC on your own route.\n */\nexport async function fastifyRequestHandler<\n TRouter extends AnyRouter,\n TRequest extends FastifyRequest,\n TResponse extends FastifyReply,\n>(opts: FastifyRequestHandlerOptions<TRouter, TRequest, TResponse>) {\n const createContext: ResolveHTTPRequestOptionsContextFn<TRouter> = async (\n innerOpts,\n ) => {\n return await opts.createContext?.({\n ...opts,\n ...innerOpts,\n });\n };\n\n const incomingMessage: NodeHTTPRequest = opts.req.raw;\n\n // monkey-path body to the IncomingMessage\n if ('body' in opts.req) {\n incomingMessage.body = opts.req.body;\n }\n const req = incomingMessageToRequest(incomingMessage, opts.res.raw, {\n maxBodySize: opts.maxBodySize ?? null,\n });\n\n const res = await resolveResponse({\n ...opts,\n req,\n error: null,\n createContext,\n onError(o) {\n opts?.onError?.({\n ...o,\n req: opts.req,\n });\n },\n });\n\n await opts.res.send(res);\n}\n","/**\n * If you're making an adapter for tRPC and looking at this file for reference, you should import types and functions from `@trpc/server` and `@trpc/server/http`\n *\n * @example\n * ```ts\n * import type { AnyTRPCRouter } from '@trpc/server'\n * import type { HTTPBaseHandlerOptions } from '@trpc/server/http'\n * ```\n */\n/// <reference types=\"@fastify/websocket\" />\nimport type { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify';\n// @trpc/server\nimport type { AnyRouter } from '../../@trpc/server';\n// @trpc/server/http\nimport type { NodeHTTPCreateContextFnOptions } from '../node-http';\n// @trpc/server/ws\nimport { getWSConnectionHandler, type WSSHandlerOptions } from '../ws';\nimport type { FastifyHandlerOptions } from './fastifyRequestHandler';\nimport { fastifyRequestHandler } from './fastifyRequestHandler';\n\n/**\n * The options of `fastifyTRPCPlugin`.\n * @see https://trpc.io/docs/server/adapters/fastify#fastify-plugin-options\n */\nexport interface FastifyTRPCPluginOptions<TRouter extends AnyRouter> {\n /** The path the router is served at, such as `/trpc`. */\n prefix?: string;\n /**\n * Whether to serve WebSockets too. Needs `@fastify/websocket` to be\n * registered first.\n * @see https://trpc.io/docs/server/adapters/fastify#enable-websockets\n */\n useWSS?: boolean;\n /**\n * The router and handler options. `keepAlive`, `dangerouslyDisablePong`\n * and `experimental_encoder` only apply with `useWSS`.\n */\n trpcOptions: FastifyHandlerOptions<TRouter, FastifyRequest, FastifyReply> &\n Pick<\n WSSHandlerOptions<TRouter>,\n 'keepAlive' | 'dangerouslyDisablePong' | 'experimental_encoder'\n >;\n}\n\n/**\n * What `createContext` gets in the Fastify adapter: `req`, `res` and the\n * request's `info`. With `useWSS`, WebSocket connections get the raw\n * `IncomingMessage` as `req` and the `WebSocket` as `res` instead.\n * @see https://trpc.io/docs/server/adapters/fastify#create-the-context\n */\nexport type CreateFastifyContextOptions = NodeHTTPCreateContextFnOptions<\n FastifyRequest,\n FastifyReply\n>;\n\n/**\n * A Fastify plugin that serves a router over HTTP, and over WebSockets\n * with `useWSS`.\n * @example\n * ```ts\n * server.register(fastifyTRPCPlugin, {\n * prefix: '/trpc',\n * trpcOptions: { router: appRouter, createContext },\n * });\n * ```\n * @see https://trpc.io/docs/server/adapters/fastify#create-fastify-server\n */\nexport function fastifyTRPCPlugin<TRouter extends AnyRouter>(\n fastify: FastifyInstance,\n opts: FastifyTRPCPluginOptions<TRouter>,\n done: (err?: Error) => void,\n) {\n fastify.removeContentTypeParser('application/json');\n fastify.addContentTypeParser(\n 'application/json',\n { parseAs: 'string' },\n function (_, body, _done) {\n _done(null, body);\n },\n );\n fastify.removeContentTypeParser('multipart/form-data');\n fastify.addContentTypeParser(\n 'multipart/form-data',\n {},\n function (_, body, _done) {\n _done(null, body);\n },\n );\n\n let prefix = opts.prefix ?? '';\n\n // https://github.com/fastify/fastify-plugin/blob/fe079bef6557a83794bf437e14b9b9edb8a74104/plugin.js#L11\n // @ts-expect-error property 'default' does not exists on type ...\n if (typeof fastifyTRPCPlugin.default !== 'function') {\n prefix = ''; // handled by fastify internally\n }\n\n fastify.all(`${prefix}/:path`, async (req, res) => {\n const path = (req.params as any).path;\n await fastifyRequestHandler({ ...opts.trpcOptions, req, res, path });\n });\n\n if (opts.useWSS) {\n const trpcOptions =\n opts.trpcOptions as unknown as WSSHandlerOptions<TRouter>;\n\n const onConnection = getWSConnectionHandler<TRouter>({\n ...trpcOptions,\n });\n\n fastify.get(prefix ?? '/', { websocket: true }, (socket, req) => {\n // keepalive is registered by getWSConnectionHandler, which every\n // adapter goes through — registering it here as well gave each socket\n // two ping intervals and two pong-wait timers\n onConnection(socket, req.raw);\n });\n }\n\n done();\n}\n"],"mappings":";;;;;;;;;AAsDA,eAAsB,sBAIpB,MAAkE;;CAClE,MAAM,gBAA6D,OACjE,cACG;;EACH,OAAO,QAAA,sBAAM,KAAK,mBAAA,QAAA,wBAAA,KAAA,IAAA,KAAA,IAAA,oBAAA,KAAA,MAAA,eAAA,eAAA,CAAA,GACb,IAAA,GACA,SACL,CAAC;CACH;CAEA,MAAM,kBAAmC,KAAK,IAAI;CAGlD,IAAI,UAAU,KAAK,KACjB,gBAAgB,OAAO,KAAK,IAAI;CAElC,MAAM,MAAM,yBAAyB,iBAAiB,KAAK,IAAI,KAAK,EAClE,cAAA,oBAAa,KAAK,iBAAA,QAAA,sBAAA,KAAA,IAAA,oBAAe,KACnC,CAAC;CAED,MAAM,MAAM,MAAM,gBAAA,eAAA,eAAA,CAAA,GACb,IAAA,GAAA,CAAA,GAAA;EACH;EACA,OAAO;EACP;EACA,QAAQ,GAAG;;GACT,SAAA,QAAA,SAAA,KAAA,MAAA,gBAAA,KAAM,aAAA,QAAA,kBAAA,KAAA,KAAA,cAAA,KAAA,MAAA,eAAA,eAAA,CAAA,GACD,CAAA,GAAA,CAAA,GAAA,EACH,KAAK,KAAK,IAAA,CACZ,CAAC;EACH;CACF,CAAA,CAAC;CAED,MAAM,KAAK,IAAI,KAAK,GAAG;AACzB;;;;;;;;;;;;;;;ACzBA,SAAgB,kBACd,SACA,MACA,MACA;;CACA,QAAQ,wBAAwB,kBAAkB;CAClD,QAAQ,qBACN,oBACA,EAAE,SAAS,SAAS,GACpB,SAAU,GAAG,MAAM,OAAO;EACxB,MAAM,MAAM,IAAI;CAClB,CACF;CACA,QAAQ,wBAAwB,qBAAqB;CACrD,QAAQ,qBACN,uBACA,CAAC,GACD,SAAU,GAAG,MAAM,OAAO;EACxB,MAAM,MAAM,IAAI;CAClB,CACF;CAEA,IAAI,UAAA,eAAS,KAAK,YAAA,QAAA,iBAAA,KAAA,IAAA,eAAU;CAI5B,IAAI,OAAO,kBAAkB,YAAY,YACvC,SAAS;CAGX,QAAQ,IAAI,GAAG,OAAO,SAAS,OAAO,KAAK,QAAQ;EACjD,MAAM,OAAQ,IAAI,OAAe;EACjC,MAAM,sBAAA,eAAA,eAAA,CAAA,GAA2B,KAAK,WAAA,GAAA,CAAA,GAAA;GAAa;GAAK;GAAK;EAAK,CAAA,CAAC;CACrE,CAAC;CAED,IAAI,KAAK,QAAQ;;EACf,MAAM,cACJ,KAAK;EAEP,MAAM,eAAe,uBAAA,eAAA,CAAA,GAChB,WACL,CAAC;EAED,QAAQ,KAAA,UAAI,YAAA,QAAA,YAAA,KAAA,IAAA,UAAU,KAAK,EAAE,WAAW,KAAK,IAAI,QAAQ,QAAQ;GAI/D,aAAa,QAAQ,IAAI,GAAG;EAC9B,CAAC;CACH;CAEA,KAAK;AACP"}