honojs-middleware/packages/trpc-server
Luis Cadillo f5ef5ac97d
docs(trpc): add custom endpoint configuration example (#538)
This PR adds documentation for configuring custom endpoints with the @hono/trpc-server middleware. Ensuring the endpoint parameter matches the middleware's path helps avoid issues like the one described in [honojs/middleware#166](https://github.com/honojs/middleware/issues/166).
2024-05-23 22:03:33 +09:00
..
src feat(trpc-server): use c.body to create response to avoid header loss (#517) 2024-05-16 07:16:16 +09:00
test refactor: format (#497) 2024-05-04 11:33:29 +09:00
CHANGELOG.md Version Packages (#526) 2024-05-16 07:27:17 +09:00
README.md docs(trpc): add custom endpoint configuration example (#538) 2024-05-23 22:03:33 +09:00
jest.config.js feat: introduce tRPC server middleware (#36) 2023-02-04 23:37:15 +09:00
package.json Version Packages (#526) 2024-05-16 07:27:17 +09:00
tsconfig.cjs.json feat: introduce tRPC server middleware (#36) 2023-02-04 23:37:15 +09:00
tsconfig.esm.json feat: introduce tRPC server middleware (#36) 2023-02-04 23:37:15 +09:00
tsconfig.json feat: introduce tRPC server middleware (#36) 2023-02-04 23:37:15 +09:00

README.md

tRPC Server Middleware for Hono

tRPC Server Middleware adapts a tRPC server as middleware for Hono. Hono works on almost any JavaScript runtime, including Cloudflare Workers, Deno, and Bun. So, with this middleware, the same code will run as tRPC server.

Install

npm install @hono/trpc-server

Usage

Router:

import { initTRPC } from '@trpc/server'
import { z } from 'zod'

const t = initTRPC.create()

const publicProcedure = t.procedure
const router = t.router

export const appRouter = router({
  hello: publicProcedure.input(z.string().nullish()).query(({ input }) => {
    return `Hello ${input ?? 'World'}!`
  }),
})

export type AppRouter = typeof appRouter

Hono app using tRPC Server Middleware:

import { Hono } from 'hono'
import { trpcServer } from '@hono/trpc-server' // Deno 'npm:@hono/trpc-server'
import { appRouter } from './router'

const app = new Hono()

app.use(
  '/trpc/*',
  trpcServer({
    router: appRouter,
  })
)

export default app

Client:

import { createTRPCProxyClient, httpBatchLink } from '@trpc/client'
import type { AppRouter } from './router'

const client = createTRPCProxyClient<AppRouter>({
  links: [
    httpBatchLink({
      url: 'http://localhost:8787/trpc',
    }),
  ],
})

console.log(await client.hello.query('Hono'))

Context

You can also access c.env from hono context from the trpc ctx. eg. here's an example using cloudflare D1 binding available as env.DB

import { initTRPC } from '@trpc/server'
import { z } from 'zod'

type Env = {
  DB: D1Database;
}
type HonoContext = {
  env: Env,
};

const t = initTRPC.context<HonoContext>().create()

const publicProcedure = t.procedure
const router = t.router

export const appRouter = router({
  usersCount: publicProcedure.query(({ input, ctx }) => {
    const result = await ctx.env.DB.prepare("SELECT count(*) from user;").all();
    return result.results[0].count;
  }),
})

export type AppRouter = typeof appRouter

For further control, you can optionally specify a createContext that in this case will receive the hono context as 2nd argument:

app.use(
  '/trpc/*',
  trpcServer({
    router: appRouter,
    createContext: (_opts, c) => ({
      // c is the hono context
      var1: c.env.MY_VAR1,
      var2: c.req.header('X-VAR2'),
    })
  })
)

Custom Endpoints

To set up custom endpoints ensure the endpoint parameter matches the middleware's path. This alignment allows @trpc/server to accurately extract your procedure paths.

import { Hono } from 'hono'
import { trpcServer } from '@hono/trpc-server'
import { appRouter } from './router'

const app = new Hono()

// Custom endpoint configuration
app.use(
  '/api/trpc/*',
  trpcServer({
    endpoint: '/api/trpc',
    router: appRouter,
  })
)

export default app

Author

Yusuke Wada https://github.com/yusukebe

License

MIT