feat: introduce tRPC server middleware (#36)

* feat: introduce tRPC server middleware

* chore: add changeset
pull/37/head
Yusuke Wada 2023-02-04 23:37:15 +09:00 committed by GitHub
parent f05c6094d2
commit e7c60b3492
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 238 additions and 72 deletions

View File

@ -0,0 +1,5 @@
---
'@hono/trpc-server': patch
---
Initial release

View File

@ -0,0 +1,25 @@
name: ci-trpc-server
on:
push:
branches: [main]
paths:
- 'packages/trpc-server/**'
pull_request:
branches: ['*']
paths:
- 'packages/trpc-server/**'
jobs:
ci:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./packages/trpc-server
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.x
- run: yarn install --frozen-lockfile
- run: yarn build
- run: yarn test

View File

@ -12,6 +12,7 @@
"build:graphql-server": "yarn workspace @hono/graphql-server build",
"build:sentry": "yarn workspace @hono/sentry build",
"build:firebase-auth": "yarn workspace @hono/firebase-auth build",
"build:trpc-server": "yarn workspace @hono/trpc-server build",
"build": "run-p build:*"
},
"license": "MIT",

View File

@ -1,13 +0,0 @@
# tRPC Adapter Middleware for Hono
## Usage
```ts
```
## Author
## License
MIT

View File

@ -1,30 +0,0 @@
{
"name": "@honojs/trpc-adapter",
"version": "0.0.0",
"description": "tRPC Adapter Middleware for Hono",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"test": "jest",
"build": "rimraf dist && tsc",
"prerelease": "yarn build && yarn test",
"release": "yarn publish"
},
"license": "MIT",
"private": false,
"publishConfig": {
"registry": "https://registry.npmjs.org",
"access": "public"
},
"repository": {
"type": "git",
"url": "https://github.com/honojs/middleware.git"
},
"homepage": "https://honojs.dev",
"dependencies": {
"hono": "^2.3.0"
}
}

View File

@ -1,15 +0,0 @@
import { Hono } from 'hono'
import { trpcAdapter } from '../src'
describe('tRPC Adapter Middleware', () => {
const app = new Hono()
app.use('/trpc/*', trpcAdapter())
app.get('/trpc', (c) => c.text('Here is dummy endpoint'))
it('Should return 200 response', async () => {
const res = await app.request('http://localhost/trpc')
expect(res).not.toBeNull()
expect(res.status).toBe(200)
})
})

View File

@ -1,7 +0,0 @@
import type { Handler } from 'hono'
export const trpcAdapter = (): Handler => {
return async (_c, next) => {
await next()
}
}

View File

@ -0,0 +1,76 @@
# tRPC Server Middleware for Hono
tRPC Server Middleware adapts a [tRPC](https://trpc.io) 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:
```ts
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:
```ts
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:
```ts
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'))
```
## Author
Yusuke Wada <https://github.com/yusukebe>
## License
MIT

View File

@ -0,0 +1,42 @@
{
"name": "@hono/trpc-server",
"version": "0.0.0",
"description": "tRPC Server Middleware for Hono",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"types": "dist/esm/index.d.ts",
"files": [
"dist"
],
"scripts": {
"test": "jest",
"build:cjs": "tsc -p tsconfig.cjs.json",
"build:esm": "tsc -p tsconfig.esm.json",
"build": "rimraf dist && yarn build:cjs && yarn build:esm",
"prerelease": "yarn build && yarn test",
"release": "yarn publish"
},
"license": "MIT",
"private": false,
"publishConfig": {
"registry": "https://registry.npmjs.org",
"access": "public"
},
"repository": {
"type": "git",
"url": "https://github.com/honojs/middleware.git"
},
"homepage": "https://honojs.dev",
"peerDependencies": {
"@trpc/server": "^10.10.0",
"hono": "^2.7.5"
},
"devDependencies": {
"@trpc/server": "^10.10.0",
"hono": "^2.7.5",
"zod": "^3.20.2"
},
"engines": {
"node": ">=16.0.0"
}
}

View File

@ -0,0 +1,19 @@
import type { AnyRouter } from '@trpc/server'
import { fetchRequestHandler } from '@trpc/server/adapters/fetch'
import type { MiddlewareHandler } from 'hono'
type tRPCOptions = {
endpoint?: string
router: AnyRouter
}
export const trpcServer = ({ router, endpoint = '/trpc' }: tRPCOptions): MiddlewareHandler => {
return async (c) => {
const res = fetchRequestHandler({
endpoint: endpoint,
req: c.req,
router: router,
})
return res
}
}

View File

@ -0,0 +1,43 @@
import { initTRPC } from '@trpc/server'
import { Hono } from 'hono'
import { z } from 'zod'
import { trpcServer } from '../src'
describe('tRPC Adapter Middleware', () => {
const t = initTRPC.create()
const publicProcedure = t.procedure
const router = t.router
const appRouter = router({
hello: publicProcedure.input(z.string().nullish()).query(({ input }) => {
return `Hello ${input ?? 'World'}`
}),
})
const app = new Hono()
app.use(
'/trpc/*',
trpcServer({
router: appRouter,
})
)
it('Should return 200 response', async () => {
const searchParams = new URLSearchParams({
input: JSON.stringify({ '0': 'Hono' }),
batch: '1',
})
const req = new Request(`http://localhost/trpc/hello?${searchParams.toString()}`)
const res = await app.request(req)
expect(res.status).toBe(200)
expect(await res.json()).toEqual([
{
result: {
data: 'Hello Hono',
},
},
])
})
})

View File

@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "CommonJS",
"declaration": false,
"outDir": "./dist/cjs"
}
}

View File

@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "ESNext",
"declaration": true,
"outDir": "./dist/esm"
}
}

View File

@ -2,7 +2,6 @@
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist",
},
"include": [
"src/**/*.ts"

View File

@ -1511,6 +1511,11 @@
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
"@trpc/server@^10.10.0":
version "10.10.0"
resolved "https://registry.yarnpkg.com/@trpc/server/-/server-10.10.0.tgz#0b494335140d4fd5e1452f7b57dcc9b8886720a4"
integrity sha512-tCTqcqBT+3nebYFTHtwM877qo5xQPtVlptxKdUzMVWleWT4lFTL4oddk45qVURToci2iMbVJjd4jQU9y9/XwlQ==
"@types/acorn@^4.0.0":
version "4.0.6"
resolved "https://registry.yarnpkg.com/@types/acorn/-/acorn-4.0.6.tgz#d61ca5480300ac41a7d973dd5b84d0a591154a22"
@ -5185,12 +5190,7 @@ hono@3.0.0-rc.9:
resolved "https://registry.yarnpkg.com/hono/-/hono-3.0.0-rc.9.tgz#6077bc67fce850dca99cd58452bda21ff8984da8"
integrity sha512-gW/I51Uay6RhrDhtRN/3WTg7ALT3VRdk0NZBdGpkEOgF+TrzFwmWHDbzHUPa9MffiXSlrkFtMmJVvdKO3Iab8Q==
hono@^2.3.0:
version "2.6.2"
resolved "https://registry.yarnpkg.com/hono/-/hono-2.6.2.tgz#1e32a4b4b3bf557a8aa87e392b00b505a1ec1fdd"
integrity sha512-Y4Uv6dPPx6u7TNoWN245tLw8jycBf97w0FJGJoEMdgdBqQEv1dqIvg5IfDhiYMkimSIt4SXxmMgiyPf2wzwFWQ==
hono@^2.6.1:
hono@^2.6.1, hono@^2.7.5:
version "2.7.5"
resolved "https://registry.yarnpkg.com/hono/-/hono-2.7.5.tgz#2b0c39d39a057575962a7025373be4304dedca9c"
integrity sha512-UYrhUT1Xtalh7Xw/YGXee25wlWMiVIRfr0FbAJMEMyRpX9TFZ/6JKmVdCK7ioRnhAw7PfWBasjSBhdNXQ8/okQ==
@ -10806,6 +10806,11 @@ zod@3.19.1:
resolved "https://registry.yarnpkg.com/zod/-/zod-3.19.1.tgz#112f074a97b50bfc4772d4ad1576814bd8ac4473"
integrity sha512-LYjZsEDhCdYET9ikFu6dVPGp2YH9DegXjdJToSzD9rO6fy4qiRYFoyEYwps88OseJlPyl2NOe2iJuhEhL7IpEA==
zod@^3.20.2:
version "3.20.2"
resolved "https://registry.yarnpkg.com/zod/-/zod-3.20.2.tgz#068606642c8f51b3333981f91c0a8ab37dfc2807"
integrity sha512-1MzNQdAvO+54H+EaK5YpyEy0T+Ejo/7YLHS93G3RnYWh5gaotGHwGeN/ZO687qEDU2y4CdStQYXVHIgrUl5UVQ==
zwitch@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7"