Contribuir con un Generador
Creemos un nuevo generador para contribuir a @aws/nx-plugin
. Nuestro objetivo será generar un nuevo procedimiento para una API tRPC.
Explora el Plugin
Sección titulada «Explora el Plugin»Primero, clonemos el plugin:
git clone git@github.com:awslabs/nx-plugin-for-aws.git
Luego instala y construye:
cd nx-plugin-for-awspnpm ipnpm nx run-many --target build --all
Crea un Generador Vacío
Sección titulada «Crea un Generador Vacío»Creemos el nuevo generador en packages/nx-plugin/src/trpc/procedure
.
¡Proveemos un generador para crear nuevos generadores para que puedas estructurar rápidamente tu nuevo generador! Puedes ejecutar este generador así:
- 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
- pluginProject: @aws/nx-plugin
- name: ts#trpc-api#procedure
- directory: trpc/procedure
- description: Adds a procedure to a tRPC API
- Haga clic en
Generate
pnpm nx g @aws/nx-plugin:ts#nx-generator --pluginProject=@aws/nx-plugin --name=ts#trpc-api#procedure --directory=trpc/procedure --description=Adds a procedure to a tRPC API
yarn nx g @aws/nx-plugin:ts#nx-generator --pluginProject=@aws/nx-plugin --name=ts#trpc-api#procedure --directory=trpc/procedure --description=Adds a procedure to a tRPC API
npx nx g @aws/nx-plugin:ts#nx-generator --pluginProject=@aws/nx-plugin --name=ts#trpc-api#procedure --directory=trpc/procedure --description=Adds a procedure to a tRPC API
bunx nx g @aws/nx-plugin:ts#nx-generator --pluginProject=@aws/nx-plugin --name=ts#trpc-api#procedure --directory=trpc/procedure --description=Adds a procedure to a tRPC API
También puede realizar una ejecución en seco para ver qué archivos se cambiarían
pnpm nx g @aws/nx-plugin:ts#nx-generator --pluginProject=@aws/nx-plugin --name=ts#trpc-api#procedure --directory=trpc/procedure --description=Adds a procedure to a tRPC API --dry-run
yarn nx g @aws/nx-plugin:ts#nx-generator --pluginProject=@aws/nx-plugin --name=ts#trpc-api#procedure --directory=trpc/procedure --description=Adds a procedure to a tRPC API --dry-run
npx nx g @aws/nx-plugin:ts#nx-generator --pluginProject=@aws/nx-plugin --name=ts#trpc-api#procedure --directory=trpc/procedure --description=Adds a procedure to a tRPC API --dry-run
bunx nx g @aws/nx-plugin:ts#nx-generator --pluginProject=@aws/nx-plugin --name=ts#trpc-api#procedure --directory=trpc/procedure --description=Adds a procedure to a tRPC API --dry-run
Notarás que se han generado los siguientes archivos:
Directorypackages/nx-plugin/src/trpc/procedure
- schema.json Define las entradas del generador
- schema.d.ts Interfaz TypeScript que coincide con el schema
- generator.ts Función que ejecuta Nx como generador
- generator.spec.ts Pruebas para el generador
Directorydocs/src/content/docs/guides/
- trpc-procedure.mdx Documentación del generador
- packages/nx-plugin/generators.json Actualizado para incluir el generador
Actualicemos el schema para agregar las propiedades necesarias:
{ "$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"]}
export interface TrpcProcedureSchema { project: string; procedure: string; type: 'query' | 'mutation';}
Notarás que el generador ya está configurado en 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" } },...
Implementa el Generador
Sección titulada «Implementa el Generador»Para agregar un procedimiento a una API tRPC, necesitamos hacer dos cosas:
- Crear un archivo TypeScript para el nuevo procedimiento
- Agregar el procedimiento al router
Crea el Nuevo Procedimiento
Sección titulada «Crea el Nuevo Procedimiento»Para crear el archivo TypeScript, usaremos una utilidad llamada generateFiles
. Con esto, definimos una plantilla EJS que podemos renderizar en nuestro generador con variables basadas en las opciones seleccionadas.
Primero, definimos la plantilla en packages/nx-plugin/src/trpc/procedure/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 {}; });
En la plantilla usamos tres variables:
procedureNameCamelCase
procedureNameKebabCase
procedureType
Debemos asegurarnos de pasarlas a generateFiles
, junto con el directorio destino (el sourceRoot
del proyecto seleccionado). Actualicemos el generador:
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;
Agrega el Procedimiento al Router
Sección titulada «Agrega el Procedimiento al Router»Ahora debemos actualizar el router para incluir el nuevo procedimiento. Usamos manipulación del AST de TypeScript para modificar el código fuente.
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 { destructuredImport, replace } from '../../utils/ast';import { factory, ObjectLiteralExpression } from 'typescript';
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');
destructuredImport( tree, routerPath, [procedureNameCamelCase], `./procedures/${procedureNameKebabCase}.js`, );
replace( tree, routerPath, 'CallExpression[expression.name="router"] > ObjectLiteralExpression', (node) => factory.createObjectLiteralExpression([ ...(node as ObjectLiteralExpression).properties, factory.createShorthandPropertyAssignment(procedureNameCamelCase), ]), );
await formatFilesInSubtree(tree);};
export default trpcProcedureGenerator;
Compilemos el generador para probarlo:
pnpm nx run @aws/nx-plugin:compile
Probando el Generador
Sección titulada «Probando el Generador»Para probar, vincularemos nuestro plugin local a un proyecto existente.
Crea un Proyecto de Prueba con API tRPC
Sección titulada «Crea un Proyecto de Prueba con API tRPC»En otro directorio, crea un workspace:
npx create-nx-workspace@~21.0.3 trpc-generator-test --pm=pnpm --preset=@aws/nx-plugin --ci=skip
npx create-nx-workspace@~21.0.3 trpc-generator-test --pm=yarn --preset=@aws/nx-plugin --ci=skip
npx create-nx-workspace@~21.0.3 trpc-generator-test --pm=npm --preset=@aws/nx-plugin --ci=skip
npx create-nx-workspace@~21.0.3 trpc-generator-test --pm=bun --preset=@aws/nx-plugin --ci=skip
Genera una API tRPC:
- 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#trpc-api
- Complete los parámetros requeridos
- apiName: test-api
- Haga clic en
Generate
pnpm nx g @aws/nx-plugin:ts#trpc-api --apiName=test-api --no-interactive
yarn nx g @aws/nx-plugin:ts#trpc-api --apiName=test-api --no-interactive
npx nx g @aws/nx-plugin:ts#trpc-api --apiName=test-api --no-interactive
bunx nx g @aws/nx-plugin:ts#trpc-api --apiName=test-api --no-interactive
También puede realizar una ejecución en seco para ver qué archivos se cambiarían
pnpm nx g @aws/nx-plugin:ts#trpc-api --apiName=test-api --no-interactive --dry-run
yarn nx g @aws/nx-plugin:ts#trpc-api --apiName=test-api --no-interactive --dry-run
npx nx g @aws/nx-plugin:ts#trpc-api --apiName=test-api --no-interactive --dry-run
bunx nx g @aws/nx-plugin:ts#trpc-api --apiName=test-api --no-interactive --dry-run
Vincula el Plugin Local
Sección titulada «Vincula el Plugin Local»En tu proyecto, vincula @aws/nx-plugin
:
cd path/to/trpc-generator-testpnpm link path/to/nx-plugin-for-aws/dist/packages/nx-plugin
cd path/to/trpc-generator-testyarn link path/to/nx-plugin-for-aws/dist/packages/nx-plugin
cd path/to/trpc-generator-testnpm link path/to/nx-plugin-for-aws/dist/packages/nx-plugin
cd path/to/nx-plugin-for-aws/dist/packages/nx-pluginbun linkcd path/to/trpc-generator-testbun link @aws/nx-plugin
Ejecuta el Nuevo Generador
Sección titulada «Ejecuta el Nuevo Generador»Prueba el generador:
- 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#trpc-api#procedure
- Complete los parámetros requeridos
- Haga clic en
Generate
pnpm nx g @aws/nx-plugin:ts#trpc-api#procedure
yarn nx g @aws/nx-plugin:ts#trpc-api#procedure
npx nx g @aws/nx-plugin:ts#trpc-api#procedure
bunx nx g @aws/nx-plugin:ts#trpc-api#procedure
También puede realizar una ejecución en seco para ver qué archivos se cambiarían
pnpm nx g @aws/nx-plugin:ts#trpc-api#procedure --dry-run
yarn nx g @aws/nx-plugin:ts#trpc-api#procedure --dry-run
npx nx g @aws/nx-plugin:ts#trpc-api#procedure --dry-run
bunx nx g @aws/nx-plugin:ts#trpc-api#procedure --dry-run
Si tiene éxito, se habrá generado un nuevo procedimiento y agregado al router en router.ts
.
Ejercicios
Sección titulada «Ejercicios»Si llegaste hasta aquí y quieres experimentar más, aquí algunas sugerencias:
1. Operaciones Anidadas
Sección titulada «1. Operaciones Anidadas»Actualiza el generador para soportar routers anidados:
- Aceptar notación de puntos en
procedure
(ej:games.query
) - Generar procedimientos con nombres basados en la notación invertida (ej:
queryGames
) - Agregar el router anidado correspondiente
2. Validación
Sección titulada «2. Validación»El generador debe prevenir problemas, como seleccionar un project
que no sea una API tRPC. Revisa el generador api-connection
como ejemplo.
3. Pruebas Unitarias
Sección titulada «3. Pruebas Unitarias»Escribe pruebas unitarias para el generador. El flujo general es:
- Crear un workspace vacío con
createTreeUsingTsSolutionSetup()
- Agregar archivos existentes necesarios (ej:
project.json
,src/router.ts
) - Ejecutar el generador
- Validar los cambios en el árbol
4. Pruebas End-to-End
Sección titulada «4. Pruebas End-to-End»Actualmente tenemos una prueba “smoke test” que verifica que los generadores se construyen. Debes actualizarla para incluir este nuevo generador.