Nx Generator Generator
Aggiunge un Nx Generator a un progetto TypeScript, per aiutarti ad automatizzare attività ripetitive come lo scaffolding di componenti o l’applicazione di particolari strutture di progetto.
Utilizzo
Sezione intitolata “Utilizzo”Generare un Generator
Sezione intitolata “Generare un Generator”Puoi generare un generator in due modi:
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-generatorPuoi anche eseguire una prova per vedere quali file verrebbero modificati
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-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
- Clicca su
Generate
Opzioni
Sezione intitolata “Opzioni”| Parametro | Tipo | Predefinito | Descrizione |
|---|---|---|---|
| project Obbligatorio | string | - | Progetto TypeScript a cui aggiungere il generatore. Si consiglia di utilizzare il generatore ts#nx-plugin per crearlo. |
| name Obbligatorio | string | - | Nome del generatore |
| description | string | - | Una descrizione del tuo generatore |
| directory | string | - | La directory all'interno della cartella sorgente del progetto plugin in cui aggiungere il generatore (predefinito: <name>) |
| preferInstallDependencies | boolean | true | Se preferire l'installazione delle dipendenze dopo l'esecuzione del generatore. Impostare su false per rimandare l'installazione quando si eseguono più generatori in batch (l'installazione viene comunque eseguita se necessaria affinché i generatori successivi possano calcolare il grafo dei progetti Nx); installare una volta alla fine. |
Output del Generator
Sezione intitolata “Output del Generator”Il generator creerà i seguenti file di progetto all’interno del project specificato:
Directorysrc/<name>/
- schema.json Schema per l’input del tuo generator
- schema.d.ts Tipi TypeScript per il tuo schema
- generator.ts Implementazione stub del generator
- generator.spec.ts Test per il tuo generator
- README.md Documentazione per il tuo generator
- generators.json Configurazione Nx per definire i tuoi generator
- package.json Creato o aggiornato per aggiungere una voce “generators”
- tsconfig.json Aggiornato per utilizzare CommonJS
Modifica del Progetto
Questo generator aggiornerà il project selezionato per utilizzare CommonJS, poiché gli Nx Generator supportano solo CommonJS al momento (fare riferimento a questa issue su GitHub per il supporto ESM).
Generator Locali
Sezione intitolata “Generator Locali”Seleziona il tuo progetto nx-plugin locale quando esegui il generator ts#nx-generator, e specifica un nome e una directory e descrizione opzionali.
Definire lo Schema
Sezione intitolata “Definire lo Schema”Il file schema.json definisce le opzioni che il tuo generator accetta. Segue il formato JSON Schema con estensioni specifiche di Nx.
Struttura Base
Sezione intitolata “Struttura Base”Un file schema.json ha la seguente struttura base:
{ "$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"]}Esempio Semplice
Sezione intitolata “Esempio Semplice”Ecco un esempio semplice con alcune opzioni di base:
{ "$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"]}Prompt Interattivi (CLI)
Sezione intitolata “Prompt Interattivi (CLI)”Puoi personalizzare i prompt visualizzati quando esegui il tuo generator tramite CLI aggiungendo la proprietà x-prompt:
"name": { "type": "string", "description": "Component name", "x-prompt": "What is the name of your component?"}Per le opzioni booleane, puoi utilizzare un prompt sì/no:
"withTests": { "type": "boolean", "description": "Whether to generate test files", "x-prompt": "Would you like to generate test files?"}Selezioni a Tendina
Sezione intitolata “Selezioni a Tendina”Per le opzioni con un insieme fisso di scelte, usa enum in modo che gli utenti possano selezionare una delle opzioni.
"style": { "type": "string", "description": "The styling approach to use", "enum": ["css", "scss", "styled-components", "none"], "default": "css"}Menu a Tendina per la Selezione del Progetto
Sezione intitolata “Menu a Tendina per la Selezione del Progetto”Un pattern comune è permettere agli utenti di selezionare tra i progetti esistenti nel 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"}La proprietà x-dropdown: "projects" indica a Nx di popolare il menu a tendina con tutti i progetti nel workspace.
Argomenti Posizionali
Sezione intitolata “Argomenti Posizionali”Puoi configurare le opzioni per essere passate come argomenti posizionali quando esegui il generator dalla riga di comando:
"name": { "type": "string", "description": "Component name", "x-priority": "important", "$default": { "$source": "argv", "index": 0 }}Questo permette agli utenti di eseguire il tuo generator come nx g your-generator my-component invece di nx g your-generator --name=my-component.
Impostare le Priorità
Sezione intitolata “Impostare le Priorità”Usa la proprietà x-priority per indicare quali opzioni sono più importanti:
"name": { "type": "string", "description": "Component name", "x-priority": "important"}Le opzioni possono avere priorità di "important" o "internal". Questo aiuta Nx a ordinare le proprietà nell’estensione VSCode di Nx e nella CLI di Nx.
Valori Predefiniti
Sezione intitolata “Valori Predefiniti”Puoi fornire valori predefiniti per le opzioni:
"directory": { "type": "string", "description": "Directory where the component will be created", "default": "src/components"}Ulteriori Informazioni
Sezione intitolata “Ulteriori Informazioni”Per maggiori dettagli sugli schemi, fare riferimento alla documentazione delle Opzioni dei Generator di Nx.
Tipi TypeScript con schema.d.ts
Sezione intitolata “Tipi TypeScript con schema.d.ts”Insieme a schema.json, il generator crea un file schema.d.ts che fornisce i tipi TypeScript per le opzioni del tuo generator:
export interface YourGeneratorSchema { name: string; directory?: string; withTests?: boolean;}Questa interfaccia viene utilizzata nell’implementazione del tuo generator per fornire type safety e completamento del codice:
import { YourGeneratorSchema } from './schema';
export default async function (tree: Tree, options: YourGeneratorSchema) { // TypeScript knows the types of all your options const { name, directory = 'src/components', withTests = true } = options; // ...}Implementare un Generator
Sezione intitolata “Implementare un Generator”Dopo aver creato il nuovo generator come sopra, puoi scrivere la tua implementazione in generator.ts.
Un generator è una funzione che muta un filesystem virtuale (il Tree), leggendo e scrivendo file per apportare le modifiche desiderate. Le modifiche dal Tree vengono scritte su disco solo una volta che il generator termina l’esecuzione, a meno che non venga eseguito in modalità “dry-run”. Un generator vuoto appare come segue:
export const myGenerator = async (tree: Tree, options: MyGeneratorSchema) => { // Use the tree to apply changes};
export default myGenerator;Ecco alcune operazioni comuni che potresti voler eseguire nel tuo generator:
Leggere e Scrivere File
Sezione intitolata “Leggere e Scrivere File”// Read a fileconst content = tree.read('path/to/file.ts', 'utf-8');
// Write a filetree.write('path/to/new-file.ts', 'export const hello = "world";');
// Check if a file existsif (tree.exists('path/to/file.ts')) { // Do something}Generare File da Template
Sezione intitolata “Generare File da Template”Puoi generare file con l’utility generateFiles da @nx/devkit. Questo ti permette di definire template nella sintassi EJS e sostituire variabili.
import { generateFiles, joinPathFragments } from '@nx/devkit';
// Generate files from templatesgenerateFiles( tree, joinPathFragments(import.meta.dirname, 'files'), // Template directory 'path/to/output', // Output directory { // Variables to replace in templates name: options.name, nameCamelCase: camelCase(options.name), nameKebabCase: kebabCase(options.name), // Add more variables as needed },);Trasformazioni di Codice con GritQL
Sezione intitolata “Trasformazioni di Codice con GritQL”Puoi utilizzare GritQL per cercare e trasformare in modo dichiarativo il codice sorgente nei tuoi generator. GritQL supporta più linguaggi tra cui TypeScript, JavaScript, Python, HCL (Terraform) e altri — quindi puoi utilizzare la stessa sintassi di pattern in tutto il tuo stack.
Il Nx Plugin for AWS espone due helper:
applyGritQL(tree, filePath, pattern)— applica un pattern di riscrittura GritQL a un file e restituiscePromise<boolean>indicando se sono state apportate modifichematchGritQL(tree, filePath, pattern)— verifica se un pattern GritQL corrisponde in qualsiasi punto di un file e restituiscePromise<boolean>
import { applyGritQL, matchGritQL } from '@aws/nx-plugin/sdk/utils/ast';
// Replace a function callawait applyGritQL( tree, 'src/app.ts', '`console.log($msg)` => `logger.info($msg)`',);
// Add an element to an array only if not already presentawait applyGritQL( tree, 'src/plugins.ts', '`plugins: [$items]` => `plugins: [$items, myPlugin()]` where { $items <: not contains `myPlugin` }',);
// Check if a pattern exists before making changesif (!(await matchGritQL(tree, filePath, '`import { Auth } from "./auth"`'))) { // Add the import}I pattern GritQL funzionano anche su file non TypeScript. Prefissa il tuo pattern con language <name> per targetizzare altri linguaggi:
// Python: replace print statements with logging callsawait applyGritQL( tree, 'src/handler.py', 'language python\n`print($msg)` => `logger.info($msg)`',);I pattern GritQL utilizzano snippet di codice delimitati da backtick con $metavariables come wildcard. Usa => per le riscritture e clausole where per le condizioni.
Aggiungere Dipendenze
Sezione intitolata “Aggiungere Dipendenze”import { addDependenciesToPackageJson } from '@nx/devkit';
// Add dependencies to package.jsonaddDependenciesToPackageJson( tree, { 'new-dependency': '^1.0.0', }, { 'new-dev-dependency': '^2.0.0', },);Formattare i File Generati
Sezione intitolata “Formattare i File Generati”import { formatFilesInSubtree } from '@aws/nx-plugin/sdk/utils/format';
// Format all files that were modifiedawait formatFilesInSubtree(tree, 'optional/path/to/format');Leggere e Aggiornare File JSON
Sezione intitolata “Leggere e Aggiornare File JSON”import { readJson, updateJson } from '@nx/devkit';
// Read a JSON fileconst packageJson = readJson(tree, 'package.json');
// Update a JSON fileupdateJson(tree, 'tsconfig.json', (json) => { json.compilerOptions = { ...json.compilerOptions, strict: true, }; return json;});Estendere un Generator dal Nx Plugin for AWS
Sezione intitolata “Estendere un Generator dal Nx Plugin for AWS”Puoi importare generator dal Nx Plugin for AWS ed estenderli o comporli come desideri, ad esempio potresti voler creare un generator che si basa su un progetto TypeScript:
import { tsProjectGenerator } from '@aws/nx-plugin/sdk/ts';
export const myGenerator = async (tree: Tree, schema: MyGeneratorSchema) => { const callback = await tsProjectGenerator(tree, { ... });
// Extend the TypeScript project generator here
// Return the callback to ensure dependencies are installed. // You can wrap the callback if you wish to perform additional operations in the generator callback. return callback;};Generator OpenAPI
Sezione intitolata “Generator OpenAPI”Puoi utilizzare ed estendere i generator che usiamo per i client e gli hook TypeScript in modo simile a quanto sopra:
import { openApiTsClientGenerator } from '@aws/nx-plugin/sdk/open-api';
export const myGenerator = async (tree: Tree, schema: MyGeneratorSchema) => { await openApiTsClientGenerator(tree, { ... });
// Add additional files here};Esponiamo anche un metodo che ti permette di costruire una struttura dati che può essere utilizzata per iterare sulle operazioni in una specifica OpenAPI e quindi strumentare la tua generazione di codice, per esempio:
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(import.meta.dirname, 'files'), // Template directory 'path/to/output', // Output directory data, );};Che poi ti permette di scrivere template come:
export const myOperationNames = [<%_ allOperations.forEach((op) => { _%> '<%- op.name %>',<%_ }); _%>];Fare riferimento al codebase su GitHub per template di esempio più complessi.
Eseguire il Tuo Generator
Sezione intitolata “Eseguire il Tuo Generator”Puoi eseguire il tuo generator in due modi:
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-generatorPuoi anche eseguire una prova per vedere quali file verrebbero modificati
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-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
@my-project/nx-plugin - my-generator - Compila i parametri richiesti
- Clicca su
Generate
Testare il Tuo Generator
Sezione intitolata “Testare il Tuo Generator”Gli unit test per i generator sono semplici da implementare. Ecco un pattern tipico:
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';import { yourGenerator } from './generator.js';
describe('your generator', () => { let tree;
beforeEach(() => { // Create an empty workspace tree tree = createTreeWithEmptyWorkspace();
// Add any files that should already exist in the tree 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 () => { // Run the generator await yourGenerator(tree, { name: 'test', // Add other required options });
// Check that files were created expect(tree.exists('src/test/file.ts')).toBeTruthy();
// Check file content const content = tree.read('src/test/file.ts', 'utf-8'); expect(content).toContain('export const test');
// You can also use snapshots expect(tree.read('src/test/file.ts', 'utf-8')).toMatchSnapshot(); });
it('should update existing files', async () => { // Run the generator await yourGenerator(tree, { name: 'test', // Add other required options });
// Check that existing files were updated const content = tree.read('src/existing-file.ts', 'utf-8'); expect(content).toContain('import { test } from'); });
it('should handle errors', async () => { // Expect the generator to throw an error in certain conditions await expect( yourGenerator(tree, { name: 'invalid', // Add options that should cause an error }), ).rejects.toThrow('Expected error message'); });});Punti chiave per testare i generator:
- Usa
createTreeWithEmptyWorkspace()per creare un filesystem virtuale - Configura tutti i file prerequisiti prima di eseguire il generator
- Testa sia la creazione di nuovi file che gli aggiornamenti ai file esistenti
- Usa gli snapshot per contenuti di file complessi
- Testa le condizioni di errore per assicurarti che il tuo generator fallisca in modo elegante
Contribuire Generator a @aws/nx-plugin
Sezione intitolata “Contribuire Generator a @aws/nx-plugin”Puoi anche utilizzare ts#nx-generator per creare lo scaffolding di un generator all’interno di @aws/nx-plugin.
Quando questo generator viene eseguito nel nostro repository, genererà i seguenti file per te:
Directorypackages/nx-plugin/src/<name>/
- schema.json Schema per l’input del tuo generator
- schema.d.ts Tipi TypeScript per il tuo schema
- generator.ts Implementazione del generator
- generator.spec.ts Test per il tuo generator
Directorydocs/src/content/docs/guides/
- <name>.mdx Pagina di documentazione per il tuo generator
- packages/nx-plugin/generators.json Aggiornato per includere il tuo generator
- packages/nx-plugin/sdk/<prefix>.ts Aggiornato per esporre il tuo generator dall’SDK (per i generator
ts#epy#)
Puoi quindi iniziare a implementare il tuo generator.