Pular para o conteúdo

Contribua com um Gerador

Vamos criar um novo gerador para contribuir com o @aws/nx-plugin. Nosso objetivo será gerar um novo procedimento para uma API tRPC.

Primeiro, vamos clonar o plugin:

Terminal window
git clone git@github.com:awslabs/nx-plugin-for-aws.git

Em seguida, instalar e construir:

Terminal window
cd nx-plugin-for-aws
pnpm i
pnpm nx run-many --target build --all

Vamos criar o novo gerador em packages/nx-plugin/src/trpc/procedure.

Fornecemos um gerador para criar novos geradores, permitindo que você scaffold seu novo gerador rapidamente! Execute este gerador com:

  1. Instale o Nx Console VSCode Plugin se ainda não o fez
  2. Abra o console Nx no VSCode
  3. Clique em Generate (UI) na seção "Common Nx Commands"
  4. Procure por @aws/nx-plugin - ts#nx-generator
  5. Preencha os parâmetros obrigatórios
    • pluginProject: @aws/nx-plugin
    • name: ts#trpc-api#procedure
    • directory: trpc/procedure
    • description: Adds a procedure to a tRPC API
  6. Clique em Generate

Os seguintes arquivos serão gerados para você:

  • Directorypackages/nx-plugin/src/trpc/procedure
    • schema.json Define as entradas do gerador
    • schema.d.ts Interface TypeScript correspondente ao schema
    • generator.ts Função executada pelo Nx como gerador
    • generator.spec.ts Testes para o gerador
  • Directorydocs/src/content/docs/guides/
    • trpc-procedure.mdx Documentação do gerador
  • packages/nx-plugin/generators.json Atualizado para incluir o gerador

Vamos atualizar o schema para adicionar as propriedades necessárias:

{
"$schema": "https://json-schema.org/schema",
"$id": "tRPCProcedure",
"title": "Adds a procedure to a tRPC API",
"type": "object",
"properties": {
"project": {
"type": "string",
"description": "tRPC API project",
"x-prompt": "Select the tRPC API project to add the procedure to",
"x-dropdown": "projects",
"x-priority": "important"
},
"procedure": {
"description": "The name of the new procedure",
"type": "string",
"x-prompt": "What would you like to call your new procedure?",
"x-priority": "important",
},
"type": {
"description": "The type of procedure to generate",
"type": "string",
"x-prompt": "What type of procedure would you like to generate?",
"x-priority": "important",
"default": "query",
"enum": ["query", "mutation"]
}
},
"required": ["project", "procedure"]
}

O gerador já está configurado em packages/nx-plugin/generators.json:

...
"generators": {
...
"ts#trpc-api#procedure": {
"factory": "./src/trpc/procedure/generator",
"schema": "./src/trpc/procedure/schema.json",
"description": "Adds a procedure to a tRPC API"
}
},
...

Para adicionar um procedimento a uma API tRPC, precisamos:

  1. Criar um arquivo TypeScript para o novo procedimento
  2. Adicionar o procedimento ao router

Usaremos o utilitário generateFiles com um template EJS para gerar o arquivo:

files/procedures/__procedureNameKebabCase__.ts.template
import { publicProcedure } from '../init.js';
import { z } from 'zod';
export const <%- procedureNameCamelCase %> = publicProcedure
.input(z.object({
// TODO: define input
}))
.output(z.object({
// TODO: define output
}))
.<%- procedureType %>(async ({ input, ctx }) => {
// TODO: implement!
return {};
});

Atualizamos o gerador para passar as variáveis necessárias:

procedure/generator.ts
import {
generateFiles,
joinPathFragments,
readProjectConfiguration,
Tree,
} from '@nx/devkit';
import { TrpcProcedureSchema } from './schema';
import { formatFilesInSubtree } from '../../utils/format';
import camelCase from 'lodash.camelcase';
import kebabCase from 'lodash.kebabcase';
export const trpcProcedureGenerator = async (
tree: Tree,
options: TrpcProcedureSchema,
) => {
const projectConfig = readProjectConfiguration(tree, options.project);
const procedureNameCamelCase = camelCase(options.procedure);
const procedureNameKebabCase = kebabCase(options.procedure);
generateFiles(
tree,
joinPathFragments(__dirname, 'files'),
projectConfig.sourceRoot,
{
procedureNameCamelCase,
procedureNameKebabCase,
procedureType: options.type,
},
);
await formatFilesInSubtree(tree);
};
export default trpcProcedureGenerator;

Em seguida, queremos que o gerador conecte o novo procedimento ao router. Isso significa ler e atualizar o código-fonte do usuário!

Usamos GritQL para buscar e transformar código-fonte de forma declarativa. O helper addDestructuredImport adiciona imports nomeados, e applyGritQL aplica um padrão GritQL para adicionar o procedimento ao objeto literal do router.

procedure/generator.ts
import {
generateFiles,
joinPathFragments,
readProjectConfiguration,
Tree,
} from '@nx/devkit';
import { TrpcProcedureSchema } from './schema';
import { formatFilesInSubtree } from '../../utils/format';
import camelCase from 'lodash.camelcase';
import kebabCase from 'lodash.kebabcase';
import { addDestructuredImport, applyGritQL } from '../../utils/ast';
export const trpcProcedureGenerator = async (
tree: Tree,
options: TrpcProcedureSchema,
) => {
const projectConfig = readProjectConfiguration(tree, options.project);
const procedureNameCamelCase = camelCase(options.procedure);
const procedureNameKebabCase = kebabCase(options.procedure);
generateFiles(
tree,
joinPathFragments(__dirname, 'files'),
projectConfig.sourceRoot,
{
procedureNameCamelCase,
procedureNameKebabCase,
procedureType: options.type,
},
);
const routerPath = joinPathFragments(projectConfig.sourceRoot, 'router.ts');
await addDestructuredImport(
tree,
routerPath,
[procedureNameCamelCase],
`./procedures/${procedureNameKebabCase}.js`,
);
await applyGritQL(
tree,
routerPath,
`\`router({ $props })\` => \`router({ $props, ${procedureNameCamelCase} })\` where { $props <: not contains \`${procedureNameCamelCase}\` }`,
);
await formatFilesInSubtree(tree);
};
export default trpcProcedureGenerator;

Agora que implementamos o gerador, vamos compilá-lo para garantir que esteja disponível para testarmos em nosso projeto:

Terminal window
pnpm nx compile @aws/nx-plugin

Para testar o gerador, vamos vincular nosso Nx Plugin for AWS local a uma base de código existente.

Em um diretório separado, crie um novo workspace de teste:

Terminal window
npx create-nx-workspace@22.6.1 trpc-generator-test --pm=pnpm --preset=@aws/nx-plugin --ci=skip --analytics=false --aiAgents

Em seguida, vamos gerar uma API tRPC para adicionar o procedimento:

  1. Instale o Nx Console VSCode Plugin se ainda não o fez
  2. Abra o console Nx no VSCode
  3. Clique em Generate (UI) na seção "Common Nx Commands"
  4. Procure por @aws/nx-plugin - ts#trpc-api
  5. Preencha os parâmetros obrigatórios
    • apiName: test-api
  6. Clique em Generate

Em sua base de código, vamos vincular nosso @aws/nx-plugin local:

Terminal window
cd path/to/trpc-generator-test
pnpm link path/to/nx-plugin-for-aws/dist/packages/nx-plugin

Vamos testar o novo gerador:

  1. Instale o Nx Console VSCode Plugin se ainda não o fez
  2. Abra o console Nx no VSCode
  3. Clique em Generate (UI) na seção "Common Nx Commands"
  4. Procure por @aws/nx-plugin - ts#trpc-api#procedure
  5. Preencha os parâmetros obrigatórios
    • Clique em Generate

    Se bem-sucedido, devemos ter gerado um novo procedimento e adicionado o procedimento ao nosso router em router.ts.

    Se você chegou até aqui e ainda tem algum tempo para experimentar com geradores Nx, aqui estão algumas sugestões de recursos para adicionar ao gerador de procedimentos:

    Tente atualizar o gerador para suportar routers aninhados:

    • Aceitando notação com pontos para a entrada procedure (ex: games.query)
    • Gerando um procedimento com um nome baseado na notação invertida (ex: queryGames)
    • Adicionando o router aninhado apropriado (ou atualizando-o se já existir!)

    Nosso gerador deve se defender contra possíveis problemas, como um usuário selecionando um project que não é uma API tRPC. Dê uma olhada no gerador connection para um exemplo disso.

    Escreva alguns testes unitários para o gerador. Eles são bastante diretos de implementar, e a maioria segue o fluxo geral:

    1. Criar um workspace tree vazio usando createTreeUsingTsSolutionSetup()
    2. Adicionar quaisquer arquivos que já devem existir na tree (ex: project.json e src/router.ts para um backend tRPC)
    3. Executar o gerador em teste
    4. Validar que as alterações esperadas foram feitas na tree

    Atualmente, temos um único “smoke test” que executa todos os geradores e garante que a build seja bem-sucedida. Isso deve ser atualizado para incluir o novo gerador.

    Esta seção contém algumas orientações gerais que podem ajudar ao trabalhar no Nx Plugin for AWS.

    Trabalhe de trás para frente a partir de um projeto real

    Seção intitulada “Trabalhe de trás para frente a partir de um projeto real”

    Uma forma útil de construir novos geradores ou adicionar recursos/correções a um gerador existente é construí-lo de verdade primeiro. Dessa forma, você pode validar suas ideias e iterar rapidamente para alcançar a funcionalidade necessária. Depois de definir o resultado desejado, você pode então atualizar o gerador.

    Na prática, este processo pode ser assim:

    1. Crie um novo workspace

      Terminal window
      npx create-nx-workspace@22.6.1 my-project --pm=pnpm --preset=@aws/nx-plugin --ci=skip --analytics=false --aiAgents
    2. Execute quaisquer geradores que possam ser pré-requisitos para seu novo gerador/recurso/correção

    3. Faça commit das suas alterações (git commit)

    4. Faça as alterações desejadas e teste-as conforme necessário

    5. Use o git diff das suas alterações para informar quais mudanças devem ser feitas no Nx Plugin for AWS

    6. Execute um teste final end-to-end (vinculando seu @aws/nx-plugin) para garantir que seu gerador gera as alterações necessárias