跳至正文
Wener Notes

trpc

约 2 分钟阅读
  • @trpc/next - NextJS
  • spec
  • 参考
      • 使用 meta 定义路由
        • .meta({openapi: { method: 'GET', path: '/say-hello', headers: [] } })
      • 使用 zod 定义 input 和 output
      • 创建新的路由
      • 路由忽略大小写,忽略 Trailing slashes
      • API Handler
        • createOpenApiNextHandler
        • createOpenApiHttpHandler - node
        • createExpressMiddleware
        • ⚠️ 暂不支持 fastify -
      • generateOpenApiDocument 生成 Schema
bash
npm add @trpc/client @trpc/server
依赖包
TypeScript
import * as trpc from '@trpc/server';
import { z } from 'zod';

const appRouter = trpc
  .router()
  .query('getUser', {
    input: (val: unknown) => {
      if (typeof val === 'string') return val;
      throw new Error(`Invalid input: ${typeof val}`);
    },
    async resolve(req) {
      req.input; // string
      return { id: req.input, name: 'Bilbo' };
    },
  })
  .mutation('createUser', {
    // validate input with Zod
    input: z.object({ name: z.string().min(5) }),
    async resolve(req) {
      // use your ORM of choice
      return await UserModel.create({
        data: req.input,
      });
    },
  });

export type AppRouter = typeof appRouter;

fastify

context.ts
import { inferAsyncReturnType } from '@trpc/server';
import { CreateFastifyContextOptions } from '@trpc/server/adapters/fastify';

export function createContext({ req, res }: CreateFastifyContextOptions) {
  const user = { name: req.headers.username ?? 'anonymous' };

  return { req, res, user };
}

export type Context = inferAsyncReturnType<typeof createContext>;
TypeScript
import { fastifyTRPCPlugin } from '@trpc/server/adapters/fastify';
import fastify from 'fastify';
import { createContext } from './context';
import { appRouter } from './router';
import ws from '@fastify/websocket';

const server = fastify({
  maxParamLength: 5000,
});

// 支持 subscription
server.register(ws);

server.register(fastifyTRPCPlugin, {
  prefix: '/trpc',
  trpcOptions: { router: appRouter, createContext },
});

(async () => {
  try {
    await server.listen(3000);
  } catch (err) {
    server.log.error(err);
    process.exit(1);
  }
})();

openapi

TypeScript
import { initTRPC } from '@trpc/server';
import { OpenApiMeta } from 'trpc-openapi';
const t = initTRPC.meta<OpenApiMeta>().create();
export const appRouter = t.router({
  sayHello: t.procedure
    // 定义接口
    .meta({ /* 👉 */ openapi: { method: 'GET', path: '/say-hello' } })
    .input(z.object({ name: z.string() }))
    .output(z.object({ greeting: z.string() }))
    .query(({ input }) => {
      return { greeting: `Hello ${input.name}!` };
    });
});

// 生成
export const openApiDocument = generateOpenApiDocument(appRouter, {
  title: 'tRPC OpenAPI',
  version: '1.0.0',
  baseUrl: 'http://localhost:3000',
});

import http from 'http';
import { createOpenApiHttpHandler } from 'trpc-openapi';

// 服务端
const server = http.createServer(createOpenApiHttpHandler({ router: appRouter })); /* 👈 */
server.listen(3000);

FAQ

Rollup typing

typebox

TypeScript
import { TypeCompiler } from '@sinclair/typebox/compiler';
import { Type, TSchema } from '@sinclair/typebox';
import { initTRPC } from '@trpc/server';

export function Compile<T extends TSchema>(schema: T, references: TSchema[] = []) {
  const check = TypeCompiler.Compile(schema, references);
  return (input: unknown) => {
    if (check.Check(input)) return input;
    throw Error('Invalid Input');
  };
}

const t = initTRPC.create();

const appRouter = t.router({
  hello: t.procedure.input(Compile(Type.Number())).query(({ input }) => {
    console.log(input);
  }),
});

关联信息

反向链接、本文链接的其他页面和外部资料。

反向链接

  • zod
    笔记 · tRPC

    colinhacks/zod · adpoted by: tRPC · 参考 · zod.dev · StefanTerdell/zod-to-json-schema · fabien0102/ts-to-zod · asteasolutions/zod-to-openapi

站内链接

  • Typescript FAQ
    笔记 · bundle/rollup d.ts · bundlerollup dts

    部分类型参数推导 #26242 · monorepo 类型问题 TypeScript#25376 · 目前就 npm monorepo 工作相对正常 · interface 定义 static · TypeScript#34516 · specifying interface implements clauses #33892

参考资料

GitHub9 条
其他外链1 条
最近更新commit 2de2575编辑