Contribuire con un Generator
Creiamo un nuovo generator da contribuire a @aws/nx-plugin. Il nostro obiettivo sarà generare una nuova procedura per un’API tRPC.
Clonare il Plugin
Sezione intitolata “Clonare il Plugin”Prima di tutto, cloniamo il plugin:
git clone git@github.com:awslabs/nx-plugin-for-aws.gitSuccessivamente, installiamo e compiliamo:
cd nx-plugin-for-awspnpm ipnpm nx run-many --target build --allCreare un Generator Vuoto
Sezione intitolata “Creare un Generator Vuoto”Creiamo il nuovo generator in packages/nx-plugin/src/trpc/procedure.
Forniamo un generator per creare nuovi generator in modo da poter scaffoldare rapidamente il tuo nuovo generator! Puoi eseguire questo generator come segue:
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 APIyarn 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 APInpx 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 APIbunx 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 APIPuoi anche eseguire una prova per vedere quali file verrebbero modificati
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-runyarn 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-runnpx 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-runbunx 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- Installa il Nx Console VSCode Plugin se non l'hai già fatto
- Apri la console Nx in VSCode
- Clicca su
Generate (UI)nella sezione "Common Nx Commands" - Cerca
@aws/nx-plugin - ts#nx-generator - Compila i parametri richiesti
- pluginProject: @aws/nx-plugin
- name: ts#trpc-api#procedure
- directory: trpc/procedure
- description: Adds a procedure to a tRPC API
- Clicca su
Generate
Noterai che i seguenti file sono stati generati per te:
Directorypackages/nx-plugin/src/trpc/procedure
- schema.json Definisce l’input per il generator
- schema.d.ts Un’interfaccia typescript che corrisponde allo schema
- generator.ts Funzione che Nx esegue come generator
- generator.spec.ts Test per il generator
Directorydocs/src/content/docs/guides/
- trpc-procedure.mdx Documentazione per il generator
- packages/nx-plugin/generators.json Aggiornato per includere il generator
Aggiorniamo lo schema per aggiungere le proprietà di cui avremo bisogno per il generator:
{ "$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';}Noterai che il generator è già stato collegato in 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" } },...Implementare il Generator
Sezione intitolata “Implementare il Generator”Per aggiungere una procedura a un’API tRPC, dobbiamo fare due cose:
- Creare un file TypeScript per la nuova procedura
- Aggiungere la procedura al router
Creare la nuova Procedura
Sezione intitolata “Creare la nuova Procedura”Per creare il file TypeScript per la nuova procedura, useremo un’utility chiamata generateFiles. Utilizzandola, possiamo definire un template EJS che possiamo renderizzare nel nostro generator con variabili basate sulle opzioni selezionate dall’utente.
Prima di tutto, definiremo il template in 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 {}; });Nel template, abbiamo referenziato tre variabili:
procedureNameCamelCaseprocedureNameKebabCaseprocedureType
Quindi dovremo assicurarci di passarle a generateFiles, insieme alla directory in cui generare i file, ovvero la posizione dei file sorgente (cioè sourceRoot) per il progetto tRPC che l’utente ha selezionato come input per il generator, che possiamo estrarre dalla configurazione del progetto.
Aggiorniamo il generator per farlo:
import { generateFiles, joinPathFragments, readProjectConfiguration, type Tree,} from '@nx/devkit';import type { TrpcProcedureSchema } from './schema.js';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(import.meta.dirname, 'files'), projectConfig.sourceRoot, { procedureNameCamelCase, procedureNameKebabCase, procedureType: options.type, }, );
await formatFilesInSubtree(tree);};
export default trpcProcedureGenerator;Aggiungere la Procedura al Router
Sezione intitolata “Aggiungere la Procedura al Router”Successivamente, vogliamo che il generator colleghi la nuova procedura al router. Questo significa leggere e aggiornare il codice sorgente dell’utente!
Usiamo GritQL per cercare e trasformare il codice sorgente in modo dichiarativo. L’helper addDestructuredImport aggiunge import nominati, e applyGritQL applica un pattern GritQL per aggiungere la procedura all’oggetto letterale del router.
import { generateFiles, joinPathFragments, readProjectConfiguration, type Tree,} from '@nx/devkit';import type { TrpcProcedureSchema } from './schema.js';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(import.meta.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;Ora che abbiamo implementato il generator, compiliamolo per assicurarci che sia disponibile per testarlo nel nostro progetto dungeon adventure.
pnpm nx compile @aws/nx-pluginTestare il Generator
Sezione intitolata “Testare il Generator”Per testare il generator, collegheremo il nostro Nx Plugin for AWS locale a una codebase esistente.
Creare un Progetto di Test con un’API tRPC
Sezione intitolata “Creare un Progetto di Test con un’API tRPC”In una directory separata, crea un nuovo workspace di test:
pnpm create @aws/nx-workspace trpc-generator-testyarn create @aws/nx-workspace trpc-generator-testnpm create @aws/nx-workspace -- trpc-generator-testbun create @aws/nx-workspace trpc-generator-testSuccessivamente, generiamo un’API tRPC a cui aggiungere la procedura:
pnpm nx g @aws/nx-plugin:ts#api --name=test-api --framework=trpc --no-interactiveyarn nx g @aws/nx-plugin:ts#api --name=test-api --framework=trpc --no-interactivenpx nx g @aws/nx-plugin:ts#api --name=test-api --framework=trpc --no-interactivebunx nx g @aws/nx-plugin:ts#api --name=test-api --framework=trpc --no-interactivePuoi anche eseguire una prova per vedere quali file verrebbero modificati
pnpm nx g @aws/nx-plugin:ts#api --name=test-api --framework=trpc --no-interactive --dry-runyarn nx g @aws/nx-plugin:ts#api --name=test-api --framework=trpc --no-interactive --dry-runnpx nx g @aws/nx-plugin:ts#api --name=test-api --framework=trpc --no-interactive --dry-runbunx nx g @aws/nx-plugin:ts#api --name=test-api --framework=trpc --no-interactive --dry-run- Installa il Nx Console VSCode Plugin se non l'hai già fatto
- Apri la console Nx in VSCode
- Clicca su
Generate (UI)nella sezione "Common Nx Commands" - Cerca
@aws/nx-plugin - ts#api - Compila i parametri richiesti
- name: test-api
- framework: trpc
- Clicca su
Generate
Collegare il nostro Nx Plugin for AWS locale
Sezione intitolata “Collegare il nostro Nx Plugin for AWS locale”Nella tua codebase, colleghiamo il nostro @aws/nx-plugin locale:
cd path/to/trpc-generator-testpnpm link path/to/nx-plugin-for-aws/dist/packages/nx-plugincd path/to/trpc-generator-testyarn link path/to/nx-plugin-for-aws/dist/packages/nx-plugincd path/to/trpc-generator-testnpm link path/to/nx-plugin-for-aws/dist/packages/nx-plugincd path/to/nx-plugin-for-aws/dist/packages/nx-pluginbun linkcd path/to/trpc-generator-testbun link @aws/nx-pluginEseguire il nuovo Generator
Sezione intitolata “Eseguire il nuovo Generator”Proviamo il nuovo generator:
pnpm nx g @aws/nx-plugin:ts#trpc-api#procedureyarn nx g @aws/nx-plugin:ts#trpc-api#procedurenpx nx g @aws/nx-plugin:ts#trpc-api#procedurebunx nx g @aws/nx-plugin:ts#trpc-api#procedurePuoi anche eseguire una prova per vedere quali file verrebbero modificati
pnpm nx g @aws/nx-plugin:ts#trpc-api#procedure --dry-runyarn nx g @aws/nx-plugin:ts#trpc-api#procedure --dry-runnpx nx g @aws/nx-plugin:ts#trpc-api#procedure --dry-runbunx nx g @aws/nx-plugin:ts#trpc-api#procedure --dry-run- Installa il Nx Console VSCode Plugin se non l'hai già fatto
- Apri la console Nx in VSCode
- Clicca su
Generate (UI)nella sezione "Common Nx Commands" - Cerca
@aws/nx-plugin - ts#trpc-api#procedure - Compila i parametri richiesti
- Clicca su
Generate
Se ha successo, dovremmo aver generato una nuova procedura e aggiunto la procedura al nostro router in router.ts.
Esercizi
Sezione intitolata “Esercizi”Se sei arrivato fin qui e hai ancora del tempo per sperimentare con i generator Nx, ecco alcuni suggerimenti di funzionalità da aggiungere al generator di procedure:
1. Operazioni Annidate
Sezione intitolata “1. Operazioni Annidate”Prova ad aggiornare il generator per supportare router annidati:
- Accettando la notazione a punti per l’input
procedure(ad es.games.query) - Generando una procedura con un nome basato sulla notazione a punti invertita (ad es.
queryGames) - Aggiungendo il router annidato appropriato (o aggiornandolo se esiste già!)
2. Validazione
Sezione intitolata “2. Validazione”Il nostro generator dovrebbe difendersi da potenziali problemi, come un utente che seleziona un project che non è un’API tRPC. Dai un’occhiata al generator connection per un esempio di questo.
3. Test Unitari
Sezione intitolata “3. Test Unitari”Scrivi alcuni test unitari per il generator. Questi sono abbastanza semplici da implementare e la maggior parte segue il flusso generale:
- Creare un albero di workspace vuoto usando
createTreeUsingTsSolutionSetup() - Aggiungere eventuali file che dovrebbero già esistere nell’albero (ad es.
project.jsonesrc/router.tsper un backend tRPC) - Eseguire il generator in fase di test
- Validare che le modifiche previste siano apportate all’albero
4. Test End to End
Sezione intitolata “4. Test End to End”Abbiamo una suite di “smoke test” che eseguono i generator in un workspace nuovo e si assicurano che tutto venga compilato. Come minimo, il tuo nuovo generator dovrebbe essere aggiunto a entrambe le matrici di generator in modo che venga esercitato dagli smoke test:
e2e/src/smoke-tests/generator-matrix.ts— esegue ogni generator tramite la CLI, un’invocazione alla volta, esattamente come farebbe un utente.packages/nx-plugin/src/internal/test-matrix/generator.ts— un generator nascosto che compone tutti gli altri per testare le migrazioni tra versioni.
Nota che la matrice di generator esegue solo i generator e compila il workspace — non istanzia alcuna infrastruttura. Per i generator che distribuiscono infrastruttura, considera di estendere i test e2e di deployment (e2e/src/smoke-tests/cdk-deploy.spec.ts e terraform-deploy.spec.ts) per distribuire effettivamente le tue risorse (tramite cdk deploy / terraform apply), quindi aggiungi un’asserzione a deploy-invocations.ts che invoca la risorsa distribuita e verifica che si comporti come previsto.
Se il tuo generator fornisce un server di sviluppo locale, considera di aggiungerlo al test e2e di sviluppo locale (e2e/src/smoke-tests/local-dev.spec.ts), che avvia il target dev ed esercita il server in esecuzione.
Linee Guida Generali per Accelerare il Contributo
Sezione intitolata “Linee Guida Generali per Accelerare il Contributo”Questa sezione contiene alcune linee guida generali che possono aiutare quando si lavora sul Nx Plugin for AWS.
Lavorare a ritroso da un progetto reale
Sezione intitolata “Lavorare a ritroso da un progetto reale”Un modo utile per costruire nuovi generator o aggiungere funzionalità/correzioni a un generator esistente è costruirlo prima per davvero. In questo modo puoi validare le tue idee e iterare rapidamente per ottenere la funzionalità di cui hai bisogno. Dopo aver stabilito il risultato desiderato, puoi quindi aggiornare il generator.
In pratica, questo processo potrebbe apparire così:
-
Creare un nuovo workspace
Terminal window pnpm create @aws/nx-workspace my-projectTerminal window yarn create @aws/nx-workspace my-projectTerminal window npm create @aws/nx-workspace -- my-projectTerminal window bun create @aws/nx-workspace my-project -
Eseguire eventuali generator che potrebbero essere prerequisiti per il tuo nuovo generator/funzionalità/correzione
-
Committare le tue modifiche (
git commit) -
Apportare le modifiche desiderate e testarle secondo necessità
-
Usare il
git diffdelle tue modifiche per informare quali modifiche dovrebbero essere apportate al Nx Plugin for AWS -
Eseguire un test end to end finale (collegando il tuo
@aws/nx-plugin) per assicurarti che il tuo generator fornisca le modifiche di cui hai bisogno