Generador de Generadores de Nx
Agrega un Generador de Nx a un proyecto TypeScript para ayudarte a automatizar tareas repetitivas como la creación de componentes o la aplicación de estructuras de proyecto específicas.
Generar un generador
Sección titulada «Generar un generador»Puedes generar un generador de dos formas:
- Instale el Nx Console VSCode Plugin si aún no lo ha hecho
- Abra la consola Nx en VSCode
- Haga clic en
Generate (UI)en la sección "Common Nx Commands" - Busque
@aws/nx-plugin - ts#nx-generator - Complete los parámetros requeridos
- Haga clic en
Generate
pnpm nx g @aws/nx-plugin:ts#nx-generatoryarn nx g @aws/nx-plugin:ts#nx-generatornpx nx g @aws/nx-plugin:ts#nx-generatorbunx nx g @aws/nx-plugin:ts#nx-generatorTambién puede realizar una ejecución en seco para ver qué archivos se cambiarían
pnpm nx g @aws/nx-plugin:ts#nx-generator --dry-runyarn nx g @aws/nx-plugin:ts#nx-generator --dry-runnpx nx g @aws/nx-plugin:ts#nx-generator --dry-runbunx nx g @aws/nx-plugin:ts#nx-generator --dry-runOpciones
Sección titulada «Opciones»| Parámetro | Tipo | Predeterminado | Descripción |
|---|---|---|---|
| project Requerido | string | - | Proyecto TypeScript al que agregar el generador. Recomendamos usar el generador ts#nx-plugin para crearlo. |
| name Requerido | string | - | Nombre del generador |
| description | string | - | Una descripción de tu generador |
| directory | string | - | El directorio dentro de la carpeta de código fuente del proyecto del plugin donde agregar el generador (predeterminado: <name>) |
Salida del generador
Sección titulada «Salida del generador»El generador creará los siguientes archivos en el project seleccionado:
Directoriosrc/<nombre>/
- schema.json Esquema para la entrada del generador
- schema.d.ts Tipos TypeScript para tu esquema
- generator.ts Implementación base del generador
- generator.spec.ts Pruebas para tu generador
- README.md Documentación del generador
- generators.json Configuración de Nx para definir tus generadores
- package.json Creado o actualizado para agregar entrada “generators”
- tsconfig.json Actualizado para usar CommonJS
Modificación del proyecto
Este generador actualizará el project seleccionado para usar CommonJS, ya que los generadores de Nx actualmente solo soportan CommonJS (consulta este issue de GitHub para soporte ESM).
Generadores locales
Sección titulada «Generadores locales»Selecciona tu proyecto local nx-plugin al ejecutar el generador ts#nx-generator, y especifica un nombre junto con directorio y descripción opcionales.
Definir el esquema
Sección titulada «Definir el esquema»El archivo schema.json define las opciones que acepta tu generador. Sigue el formato JSON Schema con extensiones específicas de Nx.
Estructura básica
Sección titulada «Estructura básica»Un archivo schema.json tiene la siguiente estructura básica:
{ "$schema": "https://json-schema.org/schema", "$id": "YourGeneratorName", "title": "Your Generator Title", "description": "Description of what your generator does", "type": "object", "properties": { // Tus opciones del generador van aquí }, "required": ["requiredOption1", "requiredOption2"]}Ejemplo simple
Sección titulada «Ejemplo simple»Aquí un ejemplo simple con algunas opciones básicas:
{ "$schema": "https://json-schema.org/schema", "$id": "ComponentGenerator", "title": "Create a Component", "description": "Crea un nuevo componente React", "type": "object", "properties": { "name": { "type": "string", "description": "Nombre del componente", "x-priority": "important" }, "directory": { "type": "string", "description": "Directorio donde se creará el componente", "default": "src/components" }, "withTests": { "type": "boolean", "description": "Generar archivos de prueba", "default": true } }, "required": ["name"]}Prompts interactivos (CLI)
Sección titulada «Prompts interactivos (CLI)»Puedes personalizar los prompts mostrados al ejecutar tu generador vía CLI agregando la propiedad x-prompt:
"name": { "type": "string", "description": "Nombre del componente", "x-prompt": "¿Cuál es el nombre de tu componente?"}Para opciones booleanas, puedes usar un prompt sí/no:
"withTests": { "type": "boolean", "description": "Generar archivos de prueba", "x-prompt": "¿Deseas generar archivos de prueba?"}Selecciones en dropdown
Sección titulada «Selecciones en dropdown»Para opciones con un conjunto fijo de opciones, usa enum para que los usuarios puedan seleccionar:
"style": { "type": "string", "description": "Enfoque de estilos a usar", "enum": ["css", "scss", "styled-components", "none"], "default": "css"}Dropdown de selección de proyectos
Sección titulada «Dropdown de selección de proyectos»Un patrón común es permitir seleccionar entre proyectos existentes:
"project": { "type": "string", "description": "Proyecto donde agregar el componente", "x-prompt": "¿A qué proyecto deseas agregar el componente?", "x-dropdown": "projects"}La propiedad x-dropdown: "projects" indica a Nx poblar el dropdown con todos los proyectos del workspace.
Argumentos posicionales
Sección titulada «Argumentos posicionales»Puedes configurar opciones para recibirse como argumentos posicionales:
"name": { "type": "string", "description": "Nombre del componente", "x-priority": "important", "$default": { "$source": "argv", "index": 0 }}Esto permite ejecutar el generador como nx g your-generator mi-componente en lugar de nx g your-generator --name=mi-componente.
Establecer prioridades
Sección titulada «Establecer prioridades»Usa la propiedad x-priority para indicar opciones importantes:
"name": { "type": "string", "description": "Nombre del componente", "x-priority": "important"}Las prioridades pueden ser "important" o "internal". Esto ayuda a Nx a ordenar propiedades en la extensión VSCode y CLI.
Valores predeterminados
Sección titulada «Valores predeterminados»Puedes proveer valores por defecto:
"directory": { "type": "string", "description": "Directorio para el componente", "default": "src/components"}Más información
Sección titulada «Más información»Para más detalles sobre esquemas, consulta la documentación de Opciones de Generadores Nx.
Tipos TypeScript con schema.d.ts
Sección titulada «Tipos TypeScript con schema.d.ts»Junto con schema.json, el generador crea un archivo schema.d.ts con tipos TypeScript:
export interface YourGeneratorSchema { name: string; directory?: string; withTests?: boolean;}Esta interfaz se usa en la implementación para seguridad de tipos:
import { YourGeneratorSchema } from './schema';
export default async function (tree: Tree, options: YourGeneratorSchema) { // TypeScript conoce los tipos de las opciones const { name, directory = 'src/components', withTests = true } = options; // ...}Implementar un generador
Sección titulada «Implementar un generador»Tras crear el generador, puedes escribir su implementación en generator.ts.
Un generador es una función que muta un sistema de archivos virtual (Tree). Los cambios se escriben al disco al finalizar, a menos que se ejecute en modo “dry-run”. Un generador vacío:
export const myGenerator = async (tree: Tree, options: MyGeneratorSchema) => { // Usa el tree para aplicar cambios};
export default myGenerator;Operaciones comunes en generadores:
Leer y escribir archivos
Sección titulada «Leer y escribir archivos»// Leer archivoconst content = tree.read('ruta/al/archivo.ts', 'utf-8');
// Escribir archivotree.write('ruta/nuevo-archivo.ts', 'export const hola = "mundo";');
// Verificar existenciaif (tree.exists('ruta/al/archivo.ts')) { // Hacer algo}Generar archivos desde plantillas
Sección titulada «Generar archivos desde plantillas»Usa generateFiles de @nx/devkit con plantillas EJS:
import { generateFiles, joinPathFragments } from '@nx/devkit';
generateFiles( tree, joinPathFragments(__dirname, 'files'), // Directorio de plantillas 'ruta/de/salida', // Directorio de salida { name: options.name, nameCamelCase: camelCase(options.name), nameKebabCase: kebabCase(options.name), },);Transformaciones de código con GritQL
Sección titulada «Transformaciones de código con GritQL»Puedes usar GritQL para buscar y transformar código fuente de forma declarativa en tus generadores. GritQL soporta múltiples lenguajes incluyendo TypeScript, JavaScript, Python, HCL (Terraform) y más, permitiéndote usar la misma sintaxis de patrones en toda tu stack.
El Plugin Nx para AWS expone dos helpers:
applyGritQL(tree, filePath, pattern)— aplica un patrón de reescritura GritQL a un archivo y retornaPromise<boolean>indicando si se realizaron cambiosmatchGritQL(tree, filePath, pattern)— verifica si un patrón GritQL coincide en algún lugar del archivo y retornaPromise<boolean>
import { applyGritQL, matchGritQL } from '@aws/nx-plugin/sdk/utils/ast';
// Reemplazar una llamada de funciónawait applyGritQL( tree, 'src/app.ts', '`console.log($msg)` => `logger.info($msg)`',);
// Agregar un elemento a un array solo si no está presenteawait applyGritQL( tree, 'src/plugins.ts', '`plugins: [$items]` => `plugins: [$items, myPlugin()]` where { $items <: not contains `myPlugin` }',);
// Verificar si existe un patrón antes de hacer cambiosif (!(await matchGritQL(tree, filePath, '`import { Auth } from "./auth"`'))) { // Agregar el import}Los patrones GritQL también funcionan en archivos no-TypeScript. Prefija tu patrón con language <name> para apuntar a otros lenguajes:
// Python: reemplazar sentencias print con llamadas de loggingawait applyGritQL( tree, 'src/handler.py', 'language python\n`print($msg)` => `logger.info($msg)`',);Los patrones GritQL usan fragmentos de código delimitados por backticks con $metavariables como comodines. Usa => para reescrituras y cláusulas where para condiciones.
Agregar dependencias
Sección titulada «Agregar dependencias»import { addDependenciesToPackageJson } from '@nx/devkit';
addDependenciesToPackageJson( tree, { 'nueva-dependencia': '^1.0.0' }, { 'nueva-dev-dependencia': '^2.0.0' },);Formatear archivos
Sección titulada «Formatear archivos»import { formatFilesInSubtree } from '@aws/nx-plugin/sdk/utils/format';
await formatFilesInSubtree(tree, 'ruta/opcional');Leer y actualizar JSON
Sección titulada «Leer y actualizar JSON»import { readJson, updateJson } from '@nx/devkit';
// Leer JSONconst packageJson = readJson(tree, 'package.json');
// Actualizar JSONupdateJson(tree, 'tsconfig.json', (json) => { json.compilerOptions.strict = true; return json;});Extender generadores del Plugin Nx para AWS
Sección titulada «Extender generadores del Plugin Nx para AWS»Importa y extiende generadores existentes:
import { tsProjectGenerator } from '@aws/nx-plugin/sdk/ts';
export const myGenerator = async (tree: Tree, schema: MyGeneratorSchema) => { const callback = await tsProjectGenerator(tree, { ... }); // Extiende aquí return callback;};Generadores OpenAPI
Sección titulada «Generadores OpenAPI»Puedes usar generadores para clientes TypeScript:
import { openApiTsClientGenerator } from '@aws/nx-plugin/sdk/open-api';
export const myGenerator = async (tree: Tree, schema: MyGeneratorSchema) => { await openApiTsClientGenerator(tree, { ... }); // Agregar archivos};También puedes generar datos desde especificaciones OpenAPI:
import { buildOpenApiCodeGenerationData } from '@aws/nx-plugin/sdk/open-api.js';
export const myGenerator = async (tree: Tree, schema: MyGeneratorSchema) => { const data = await buildOpenApiCodeGenerationData(tree, 'ruta/espec.json'); generateFiles(tree, __dirname + '/files', 'ruta/salida', data);};Ejemplo de plantilla EJS:
export const myOperationNames = [<%_ allOperations.forEach((op) => { _%> '<%- op.name %>',<%_ }); _%>];Consulta el repositorio en GitHub para ejemplos complejos.
Ejecutar tu generador
Sección titulada «Ejecutar tu generador»Ejecuta tu generador de dos formas:
- Instale el Nx Console VSCode Plugin si aún no lo ha hecho
- Abra la consola Nx en VSCode
- Haga clic en
Generate (UI)en la sección "Common Nx Commands" - Busque
@my-project/nx-plugin - my-generator - Complete los parámetros requeridos
- Haga clic en
Generate
pnpm nx g @my-project/nx-plugin:my-generatoryarn nx g @my-project/nx-plugin:my-generatornpx nx g @my-project/nx-plugin:my-generatorbunx nx g @my-project/nx-plugin:my-generatorTambién puede realizar una ejecución en seco para ver qué archivos se cambiarían
pnpm nx g @my-project/nx-plugin:my-generator --dry-runyarn nx g @my-project/nx-plugin:my-generator --dry-runnpx nx g @my-project/nx-plugin:my-generator --dry-runbunx nx g @my-project/nx-plugin:my-generator --dry-runProbar tu generador
Sección titulada «Probar tu generador»Pruebas unitarias típicas:
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';import { yourGenerator } from './generator';
describe('tu generador', () => { let tree;
beforeEach(() => { tree = createTreeWithEmptyWorkspace(); tree.write('project.json', JSON.stringify({ name: 'test-project' })); });
it('debe generar archivos esperados', async () => { await yourGenerator(tree, { name: 'test' }); expect(tree.exists('src/test/file.ts')).toBeTruthy(); expect(tree.read('src/test/file.ts', 'utf-8')).toMatchSnapshot(); });
it('debe manejar errores', async () => { await expect(yourGenerator(tree, { name: 'invalido' })) .rejects.toThrow('Mensaje de error esperado'); });});Puntos clave:
- Usa
createTreeWithEmptyWorkspace() - Prueba creación y actualización de archivos
- Usa snapshots para contenido complejo
- Prueba condiciones de error
Contribuir generadores a @aws/nx-plugin
Sección titulada «Contribuir generadores a @aws/nx-plugin»Usa ts#nx-generator para crear generadores dentro de @aws/nx-plugin.
Al ejecutarlo en nuestro repositorio, genera:
Directoriopackages/nx-plugin/src/<nombre>/
- schema.json
- schema.d.ts
- generator.ts
- generator.spec.ts
Directoriodocs/src/content/docs/guides/
- <nombre>.mdx
- packages/nx-plugin/generators.json Actualizado