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
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
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
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
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
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
Para probar, vincularemos nuestro plugin local a un proyecto existente.
Crea un Proyecto de Prueba con API tRPC
En otro directorio, crea un workspace:
npx create-nx-workspace@~20.6.3 trpc-generator-test --pm=pnpm --preset=ts --ci=skip --formatter=prettier
npx create-nx-workspace@~20.6.3 trpc-generator-test --pm=yarn --preset=ts --ci=skip --formatter=prettier
npx create-nx-workspace@~20.6.3 trpc-generator-test --pm=npm --preset=ts --ci=skip --formatter=prettier
npx create-nx-workspace@~20.6.3 trpc-generator-test --pm=bun --preset=ts --ci=skip --formatter=prettier
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
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
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
Si llegaste hasta aquí y quieres experimentar más, aquí algunas sugerencias:
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
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
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
Actualmente tenemos una prueba “smoke test” que verifica que los generadores se construyen. Debes actualizarla para incluir este nuevo generador.