tRPC
tRPC é um framework para construir APIs em TypeScript com segurança de tipos de ponta a ponta. Usando tRPC, atualizações nas entradas e saídas das operações da API são refletidas imediatamente no código do cliente e visíveis em sua IDE sem necessidade de reconstruir o projeto.
O gerador de API tRPC cria uma nova API tRPC com configuração de infraestrutura AWS CDK. O backend gerado utiliza AWS Lambda para implantação serverless e inclui validação de esquema usando Zod. Configura AWS Lambda Powertools para observabilidade, incluindo logging, rastreamento com AWS X-Ray e métricas no CloudWatch.
Uso
Gerar uma API tRPC
Você pode gerar uma nova API tRPC de duas formas:
- Instale o Nx Console VSCode Plugin se ainda não o fez
- Abra o console Nx no VSCode
- Clique em
Generate (UI)
na seção "Common Nx Commands" - Procure por
@aws/nx-plugin - ts#trpc-api
- Preencha os parâmetros obrigatórios
- Clique em
Generate
pnpm nx g @aws/nx-plugin:ts#trpc-api
yarn nx g @aws/nx-plugin:ts#trpc-api
npx nx g @aws/nx-plugin:ts#trpc-api
bunx nx g @aws/nx-plugin:ts#trpc-api
Você também pode realizar uma execução simulada para ver quais arquivos seriam alterados
pnpm nx g @aws/nx-plugin:ts#trpc-api --dry-run
yarn nx g @aws/nx-plugin:ts#trpc-api --dry-run
npx nx g @aws/nx-plugin:ts#trpc-api --dry-run
bunx nx g @aws/nx-plugin:ts#trpc-api --dry-run
Opções
Parâmetro | Tipo | Padrão | Descrição |
---|---|---|---|
name Obrigatório | string | - | The name of the API (required). Used to generate class names and file paths. |
computeType | string | ServerlessApiGatewayRestApi | The type of compute to use to deploy this API. Choose between ServerlessApiGatewayRestApi (default) or ServerlessApiGatewayHttpApi. |
auth | string | IAM | The method used to authenticate with your API. Choose between IAM (default), Cognito or None. |
directory | string | packages | The directory to store the application in. |
Saída do Gerador
O gerador criará a seguinte estrutura de projeto no diretório <directory>/<api-name>
:
Directoryschema
Directorysrc
- index.ts Ponto de entrada do esquema
Directoryprocedures
- echo.ts Definições de esquema compartilhadas para o procedimento “echo”, usando Zod
- tsconfig.json Configuração TypeScript
- project.json Configuração do projeto e targets de build
Directorybackend
Directorysrc
- init.ts Inicialização do backend tRPC
- router.ts Definição do roteador tRPC (ponto de entrada do handler Lambda)
Directoryprocedures Procedimentos (ou operações) expostos pela API
- echo.ts Exemplo de procedimento
Directorymiddleware
- error.ts Middleware para tratamento de erros
- logger.ts Middleware para configurar AWS Powertools para logging em Lambda
- tracer.ts Middleware para configurar AWS Powertools para rastreamento em Lambda
- metrics.ts Middleware para configurar AWS Powertools para métricas em Lambda
- local-server.ts Ponto de entrada do adaptador standalone tRPC para servidor de desenvolvimento local
Directoryclient
- index.ts Cliente type-safe para chamadas máquina-a-máquina
- tsconfig.json Configuração TypeScript
- project.json Configuração do projeto e targets de build
O gerador também criará constructs CDK para implantação da API, localizados no diretório packages/common/constructs
.
Implementando sua API tRPC
Como visto acima, existem dois componentes principais em uma API tRPC: schema
e backend
, definidos como pacotes individuais no workspace.
Schema
O pacote schema define os tipos compartilhados entre clientes e servidor. Esses tipos são definidos usando Zod, uma biblioteca de declaração e validação de esquemas com foco em TypeScript.
Um exemplo de esquema:
import { z } from 'zod';
// Definição do esquemaexport const UserSchema = z.object({ name: z.string(), height: z.number(), dateOfBirth: z.string().datetime(),});
// Tipo TypeScript correspondenteexport type User = z.TypeOf<typeof UserSchema>;
O tipo User
acima é equivalente a:
interface User { name: string; height: number; dateOfBirth: string;}
Esquemas são validados automaticamente pela API tRPC em runtime, eliminando a necessidade de lógica de validação manual.
Zod oferece utilitários poderosos como .merge
, .pick
, .omit
e outros. Mais informações na documentação do Zod.
Backend
A pasta backend
contém a implementação da API, onde são definidas operações, entradas, saídas e implementações.
O ponto de entrada principal está em src/router.ts
, que contém o handler Lambda que roteia requisições para os procedimentos. Cada procedimento define input, output e implementação.
O roteador de exemplo possui uma operação echo
:
import { echo } from './procedures/echo.js';
export const appRouter = router({ echo,});
O procedimento echo
em src/procedures/echo.ts
:
export const echo = publicProcedure .input(EchoInputSchema) .output(EchoOutputSchema) .query((opts) => ({ result: opts.input.message }));
Explicação:
publicProcedure
define um método público com middleware configurado emsrc/middleware
input
aceita um esquema Zod para validação automáticaoutput
define o esquema de saída, gerando erros de tipo se não conformadoquery
define a implementação para operações não mutativas. Usemutation
para operações mutativas
Novas operações devem ser registradas em src/router.ts
.
Personalizando sua API tRPC
Erros
Retorne erros lançando TRPCError
:
throw new TRPCError({ code: 'NOT_FOUND', message: 'Recurso não encontrado',});
Organização de Operações
Agrupe operações com roteadores aninhados:
const appRouter = router({ users: router({ get: getUser, list: listUsers, }),})
Clientes acessam como client.users.list.query()
.
Logging
O logger AWS Powertools está em src/middleware/logger.ts
e é acessado via opts.ctx.logger
:
export const echo = publicProcedure .query(async (opts) => { opts.ctx.logger.info('Operação chamada com input', opts.input); });
Consulte a documentação do Logger.
Métricas
Métricas são acessadas via opts.ctx.metrics
:
export const echo = publicProcedure .query(async (opts) => { opts.ctx.metrics.addMetric('Invocations', 'Count', 1); });
Veja documentação de Métricas.
Rastreamento com X-Ray
O tracer está em src/middleware/tracer.ts
e é acessado via opts.ctx.tracer
:
export const echo = publicProcedure .query(async (opts) => { const subSegment = opts.ctx.tracer.getSegment()!.addNewSubsegment('MyAlgorithm'); subSegment.close(); });
Consulte documentação do Tracer.
Middleware Customizado
Exemplo de middleware para extrair identidade do usuário:
// Código REST permanece inalterado
// Código HTTP permanece inalterado
Implantando a API tRPC
Use o construct CDK gerado em common/constructs
:
import { MyApi } from ':my-scope/common-constructs`;
export class ExampleStack extends Stack { constructor(scope: Construct, id: string) { const api = new MyApi(this, 'MyApi', { integrations: MyApi.defaultIntegrations(this).build(), }); }}
Para autenticação Cognito:
import { MyApi, UserIdentity } from ':my-scope/common-constructs';
export class ExampleStack extends Stack { constructor(scope: Construct, id: string) { const identity = new UserIdentity(this, 'Identity'); const api = new MyApi(this, 'MyApi', { identity, }); }}
Concessão de Acesso (IAM)
Para autenticação IAM:
api.grantInvokeAccess(myIdentityPool.authenticatedRole);
Servidor Local
Execute o servidor local com:
pnpm nx run @my-scope/my-api:serve
yarn nx run @my-scope/my-api:serve
npx nx run @my-scope/my-api:serve
bunx nx run @my-scope/my-api:serve
Invocando a API
Crie um cliente type-safe:
import { createMyApiClient } from ':my-scope/my-api';
const client = createMyApiClient({ url: 'https://my-api-url.example.com/' });await client.echo.query({ message: 'Hello world!' });
Para React, use o gerador API Connection.
Mais Informações
Consulte a documentação do tRPC.