Gerador de Gerador do Nx
Adiciona um Nx Generator a um projeto TypeScript para ajudar a automatizar tarefas repetitivas como scaffolding de componentes ou imposição de estruturas de projeto específicas.
Utilização
Seção intitulada “Utilização”Gerar um Generator
Seção intitulada “Gerar um Generator”Você pode gerar um generator 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#nx-generator
- Preencha os parâmetros obrigatórios
- Clique em
Generate
pnpm nx g @aws/nx-plugin:ts#nx-generator
yarn nx g @aws/nx-plugin:ts#nx-generator
npx nx g @aws/nx-plugin:ts#nx-generator
bunx nx g @aws/nx-plugin:ts#nx-generator
Você também pode realizar uma execução simulada para ver quais arquivos seriam alterados
pnpm nx g @aws/nx-plugin:ts#nx-generator --dry-run
yarn nx g @aws/nx-plugin:ts#nx-generator --dry-run
npx nx g @aws/nx-plugin:ts#nx-generator --dry-run
bunx nx g @aws/nx-plugin:ts#nx-generator --dry-run
Parâmetro | Tipo | Padrão | Descrição |
---|---|---|---|
pluginProject Obrigatório | string | - | TypeScript project to add the generator to. We recommend creating a ts#project in a top-level 'tools' directory. |
name Obrigatório | string | - | Generator name |
description | string | - | A description of your generator |
directory | string | - | The directory within the plugin project's source folder to add the generator to (default: <name>) |
Saída do Generator
Seção intitulada “Saída do Generator”O generator criará os seguintes arquivos no projeto pluginProject
especificado:
Directorysrc/<name>/
- schema.json Esquema para entrada do generator
- schema.d.ts Tipos TypeScript para o esquema
- generator.ts Implementação inicial do generator
- generator.spec.ts Testes para o generator
- generators.json Configuração Nx para definir seus generators
- package.json Criado ou atualizado com entrada “generators”
- tsconfig.json Atualizado para usar CommonJS
Este generator atualizará o pluginProject
selecionado para usar CommonJS, pois os Nx Generators atualmente só suportam CommonJS (consulte esta issue do GitHub sobre suporte a ESM).
Generators Locais
Seção intitulada “Generators Locais”Selecione seu projeto local nx-plugin
ao executar o generator ts#nx-generator
, e especifique um nome, diretório opcional e descrição.
Definindo o Esquema
Seção intitulada “Definindo o Esquema”O arquivo schema.json
define as opções aceitas pelo seu generator. Ele segue o formato JSON Schema com extensões específicas do Nx.
Estrutura Básica
Seção intitulada “Estrutura Básica”Um arquivo schema.json possui a seguinte estrutura básica:
{ "$schema": "https://json-schema.org/schema", "$id": "YourGeneratorName", "title": "Your Generator Title", "description": "Description of what your generator does", "type": "object", "properties": { // Your generator options go here }, "required": ["requiredOption1", "requiredOption2"]}
Exemplo Simples
Seção intitulada “Exemplo Simples”Aqui está um exemplo simples com algumas opções básicas:
{ "$schema": "https://json-schema.org/schema", "$id": "ComponentGenerator", "title": "Create a Component", "description": "Creates a new React component", "type": "object", "properties": { "name": { "type": "string", "description": "Component name", "x-priority": "important" }, "directory": { "type": "string", "description": "Directory where the component will be created", "default": "src/components" }, "withTests": { "type": "boolean", "description": "Whether to generate test files", "default": true } }, "required": ["name"]}
Prompts Interativos (CLI)
Seção intitulada “Prompts Interativos (CLI)”Você pode personalizar os prompts exibidos ao executar seu generator via CLI adicionando a propriedade x-prompt
:
"name": { "type": "string", "description": "Component name", "x-prompt": "What is the name of your component?"}
Para opções booleanas, use um prompt sim/não:
"withTests": { "type": "boolean", "description": "Whether to generate test files", "x-prompt": "Would you like to generate test files?"}
Seleções Dropdown
Seção intitulada “Seleções Dropdown”Para opções com um conjunto fixo de escolhas, use enum
para permitir seleção entre as opções:
"style": { "type": "string", "description": "The styling approach to use", "enum": ["css", "scss", "styled-components", "none"], "default": "css"}
Dropdown de Seleção de Projeto
Seção intitulada “Dropdown de Seleção de Projeto”Um padrão comum é permitir seleção entre projetos existentes no workspace:
"project": { "type": "string", "description": "The project to add the component to", "x-prompt": "Which project would you like to add the component to?", "x-dropdown": "projects"}
A propriedade x-dropdown: "projects"
instrui o Nx a preencher o dropdown com todos os projetos do workspace.
Argumentos Posicionais
Seção intitulada “Argumentos Posicionais”Você pode configurar opções para serem passadas como argumentos posicionais ao executar o generator via linha de comando:
"name": { "type": "string", "description": "Component name", "x-priority": "important", "$default": { "$source": "argv", "index": 0 }}
Isso permite executar o generator como nx g your-generator my-component
ao invés de nx g your-generator --name=my-component
.
Definindo Prioridades
Seção intitulada “Definindo Prioridades”Use a propriedade x-priority
para indicar opções mais importantes:
"name": { "type": "string", "description": "Component name", "x-priority": "important"}
Opções podem ter prioridades "important"
ou "internal"
. Isso ajuda o Nx a ordenar propriedades na extensão VSCode e CLI do Nx.
Valores Padrão
Seção intitulada “Valores Padrão”Você pode fornecer valores padrão para opções:
"directory": { "type": "string", "description": "Directory where the component will be created", "default": "src/components"}
Mais Informações
Seção intitulada “Mais Informações”Para mais detalhes sobre esquemas, consulte a documentação de Opções do Nx Generator.
Tipos TypeScript com schema.d.ts
Seção intitulada “Tipos TypeScript com schema.d.ts”Junto com schema.json
, o generator cria um arquivo schema.d.ts
que fornece tipos TypeScript para as opções:
export interface YourGeneratorSchema { name: string; directory?: string; withTests?: boolean;}
Esta interface é usada na implementação do generator para fornecer segurança de tipos e autocompletar:
import { YourGeneratorSchema } from './schema';
export default async function (tree: Tree, options: YourGeneratorSchema) { // TypeScript conhece os tipos de todas as opções const { name, directory = 'src/components', withTests = true } = options; // ...}
Implementando um Generator
Seção intitulada “Implementando um Generator”Após criar o generator como acima, você pode escrever sua implementação em generator.ts
.
Um generator é uma função que modula um sistema de arquivos virtual (Tree
), lendo e escrevendo arquivos para fazer as alterações desejadas. As mudanças no Tree
só são escritas em disco quando o generator termina, exceto em modo “dry-run”.
Aqui estão operações comuns que você pode realizar no generator:
Lendo e Escrevendo Arquivos
Seção intitulada “Lendo e Escrevendo Arquivos”// Ler um arquivoconst content = tree.read('path/to/file.ts', 'utf-8');
// Escrever um arquivotree.write('path/to/new-file.ts', 'export const hello = "world";');
// Verificar se um arquivo existeif (tree.exists('path/to/file.ts')) { // Fazer algo}
Gerando Arquivos de Templates
Seção intitulada “Gerando Arquivos de Templates”Você pode gerar arquivos com o utilitário generateFiles
do @nx/devkit
. Isso permite definir templates em sintaxe EJS e substituir variáveis.
import { generateFiles, joinPathFragments } from '@nx/devkit';
// Gerar arquivos de templatesgenerateFiles( tree, joinPathFragments(__dirname, 'files'), // Diretório do template 'path/to/output', // Diretório de saída { // Variáveis para substituir nos templates name: options.name, nameCamelCase: camelCase(options.name), nameKebabCase: kebabCase(options.name), // Adicione mais variáveis conforme necessário },);
Manipulação de AST (Abstract Syntax Tree) TypeScript
Seção intitulada “Manipulação de AST (Abstract Syntax Tree) TypeScript”Você pode usar o método tsAstReplace
exposto pelo Nx Plugin for AWS para substituir partes de uma AST TypeScript.
import { tsAstReplace } from '@aws/nx-plugin/sdk/utils/ast';import * as ts from 'typescript';
// Exemplo: Incrementar número de versão em um arquivotsAstReplace( tree, 'path/to/version.ts', 'VariableDeclaration:has(Identifier[name="VERSION"]) NumericLiteral', (node: ts.NumericLiteral) => ts.factory.createNumericLiteral(Number(node.text) + 1));
Adicionando Dependências
Seção intitulada “Adicionando Dependências”import { addDependenciesToPackageJson } from '@nx/devkit';
// Adicionar dependências ao package.jsonaddDependenciesToPackageJson( tree, { 'new-dependency': '^1.0.0', }, { 'new-dev-dependency': '^2.0.0', },);
Formatando Arquivos Gerados
Seção intitulada “Formatando Arquivos Gerados”import { formatFilesInSubtree } from '@aws/nx-plugin/sdk/utils/format';
// Formatar todos os arquivos modificadosawait formatFilesInSubtree(tree, 'optional/path/to/format');
Lendo e Atualizando Arquivos JSON
Seção intitulada “Lendo e Atualizando Arquivos JSON”import { readJson, updateJson } from '@nx/devkit';
// Ler um arquivo JSONconst packageJson = readJson(tree, 'package.json');
// Atualizar um arquivo JSONupdateJson(tree, 'tsconfig.json', (json) => { json.compilerOptions = { ...json.compilerOptions, strict: true, }; return json;});
Estendendo um Generator do Nx Plugin for AWS
Seção intitulada “Estendendo um Generator do Nx Plugin for AWS”Você pode importar generators do Nx Plugin for AWS e estendê-los ou compô-los conforme desejar. Por exemplo, criar um generator que estende um projeto TypeScript:
import { tsProjectGenerator } from '@aws/nx-plugin/sdk/ts';
export const myGenerator = async (tree: Tree, schema: MyGeneratorSchema) => { const callback = await tsProjectGenerator(tree, { ... });
// Estenda o generator de projeto TypeScript aqui
// Retorne o callback para garantir instalação de dependências // Você pode encapsular o callback para operações adicionais return callback;};
Generators OpenAPI
Seção intitulada “Generators OpenAPI”Você pode usar e estender os generators que usamos para clients e hooks TypeScript de forma similar:
import { openApiTsClientGenerator } from '@aws/nx-plugin/sdk/open-api';
export const myGenerator = async (tree: Tree, schema: MyGeneratorSchema) => { await openApiTsClientGenerator(tree, { ... });
// Adicione arquivos adicionais aqui};
Também expomos um método para construir estruturas de dados que permitem iterar sobre operações em especificações OpenAPI e instrumentar sua própria geração de código:
import { buildOpenApiCodeGenerationData } from '@aws/nx-plugin/sdk/open-api.js';
export const myGenerator = async (tree: Tree, schema: MyGeneratorSchema) => { const data = await buildOpenApiCodeGenerationData(tree, 'path/to/spec.json');
generateFiles( tree, joinPathFragments(__dirname, 'files'), // Diretório de templates 'path/to/output', // Diretório de saída data, );};
Isso permite escrever templates como:
export const myOperationNames = [<%_ allOperations.forEach((op) => { _%> '<%- op.name %>',<%_ }); _%>];
Consulte o repositório no GitHub para exemplos mais complexos.
Executando Seu Generator
Seção intitulada “Executando Seu Generator”Você pode executar seu generator 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
@my-project/nx-plugin - my-generator
- Preencha os parâmetros obrigatórios
- Clique em
Generate
pnpm nx g @my-project/nx-plugin:my-generator
yarn nx g @my-project/nx-plugin:my-generator
npx nx g @my-project/nx-plugin:my-generator
bunx nx g @my-project/nx-plugin:my-generator
Você também pode realizar uma execução simulada para ver quais arquivos seriam alterados
pnpm nx g @my-project/nx-plugin:my-generator --dry-run
yarn nx g @my-project/nx-plugin:my-generator --dry-run
npx nx g @my-project/nx-plugin:my-generator --dry-run
bunx nx g @my-project/nx-plugin:my-generator --dry-run
Testando Seu Generator
Seção intitulada “Testando Seu Generator”Testes unitários para generators são simples de implementar. Aqui está um padrão típico:
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';import { yourGenerator } from './generator';
describe('your generator', () => { let tree;
beforeEach(() => { // Criar workspace vazio tree = createTreeWithEmptyWorkspace();
// Adicionar arquivos pré-existentes tree.write( 'project.json', JSON.stringify({ name: 'test-project', sourceRoot: 'src', }), );
tree.write('src/existing-file.ts', 'export const existing = true;'); });
it('should generate expected files', async () => { // Executar o generator await yourGenerator(tree, { name: 'test', // Adicionar outras opções necessárias });
// Verificar criação de arquivos expect(tree.exists('src/test/file.ts')).toBeTruthy();
// Verificar conteúdo const content = tree.read('src/test/file.ts', 'utf-8'); expect(content).toContain('export const test');
// Snapshots também podem ser usados expect(tree.read('src/test/file.ts', 'utf-8')).toMatchSnapshot(); });
it('should update existing files', async () => { await yourGenerator(tree, { name: 'test', // Adicionar outras opções necessárias });
const content = tree.read('src/existing-file.ts', 'utf-8'); expect(content).toContain('import { test } from'); });
it('should handle errors', async () => { await expect( yourGenerator(tree, { name: 'invalid', // Opções que devem causar erro }), ).rejects.toThrow('Mensagem de erro esperada'); });});
Pontos-chave para testar generators:
- Use
createTreeWithEmptyWorkspace()
para criar sistema de arquivos virtual - Configure arquivos pré-requisitos antes de executar o generator
- Teste criação de novos arquivos e atualizações de existentes
- Use snapshots para conteúdo complexo
- Teste condições de erro para garantir falha controlada
Contribuindo com Generators para @aws/nx-plugin
Seção intitulada “Contribuindo com Generators para @aws/nx-plugin”Você também pode usar ts#nx-generator
para estruturar um generator dentro de @aws/nx-plugin
.
Quando executado em nosso repositório, este generator criará os seguintes arquivos:
Directorypackages/nx-plugin/src/<name>/
- schema.json Esquema para entrada do generator
- schema.d.ts Tipos TypeScript para o esquema
- generator.ts Implementação do generator
- generator.spec.ts Testes para o generator
Directorydocs/src/content/docs/guides/
- <name>.mdx Página de documentação do generator
- packages/nx-plugin/generators.json Atualizado para incluir seu generator
Você pode então começar a implementar seu generator.