Generatore di Generatori Nx
Aggiunge un Nx Generator a un progetto TypeScript, per aiutarti ad automatizzare task ripetitivi come la generazione di componenti o l’imposizione di strutture di progetto specifiche.
Utilizzo
Genera un Generatore
Puoi generare un generatore in due modi:
- 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
pnpm nx g @aws/nx-plugin:ts#nx-generator
yarn nx g @aws/nx-plugin:ts#nx-generator
npx nx g @aws/nx-plugin:ts#nx-generator
bunx nx g @aws/nx-plugin:ts#nx-generator
Puoi anche eseguire una prova per vedere quali file verrebbero modificati
pnpm nx g @aws/nx-plugin:ts#nx-generator --dry-run
yarn nx g @aws/nx-plugin:ts#nx-generator --dry-run
npx nx g @aws/nx-plugin:ts#nx-generator --dry-run
bunx nx g @aws/nx-plugin:ts#nx-generator --dry-run
Opzioni
Parametro | Tipo | Predefinito | Descrizione |
---|---|---|---|
pluginProject Obbligatorio | string | - | TypeScript project to add the generator to. We recommend creating a ts#project in a top-level 'tools' directory. |
name Obbligatorio | string | - | Generator name |
description | string | - | A description of your generator |
directory | string | - | The directory within the plugin project's source folder to add the generator to (default: <name>) |
Output del Generatore
Il generatore creerà i seguenti file all’interno del progetto pluginProject
specificato:
Directorysrc/<name>/
- schema.json Schema per l’input del generatore
- schema.d.ts Tipi TypeScript per lo schema
- generator.ts Implementazione stub del generatore
- generator.spec.ts Test per il generatore
- generators.json Configurazione Nx per definire i generatori
- package.json Creato o aggiornato con una voce “generators”
- tsconfig.json Aggiornato per utilizzare CommonJS
Questo generatore aggiornerà il progetto pluginProject
selezionato per utilizzare CommonJS, poiché gli Nx Generator supportano solo CommonJS al momento (fai riferimento a questa issue GitHub per il supporto ESM).
Generator Locali
Seleziona il tuo progetto locale nx-plugin
quando esegui il generatore ts#nx-generator
, specificando un nome e opzionalmente una directory e una descrizione.
Definizione dello Schema
Il file schema.json
definisce le opzioni accettate dal generatore. Segue il formato JSON Schema con estensioni specifiche per Nx.
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
Ecco un esempio semplice con alcune opzioni 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)
Puoi personalizzare i prompt mostrati durante l’esecuzione del generatore via CLI aggiungendo la proprietà x-prompt
:
"name": { "type": "string", "description": "Component name", "x-prompt": "Qual è il nome del componente?"}
Per opzioni booleane, puoi usare un prompt sì/no:
"withTests": { "type": "boolean", "description": "Whether to generate test files", "x-prompt": "Vuoi generare i file di test?"}
Selezione a Tendina
Per opzioni con un set fisso di scelte, usa enum
per permettere agli utenti di selezionare un’opzione.
"style": { "type": "string", "description": "The styling approach to use", "enum": ["css", "scss", "styled-components", "none"], "default": "css"}
Selezione Progetto a Tendina
Un pattern comune è permettere agli utenti di selezionare tra progetti esistenti nel workspace:
"project": { "type": "string", "description": "The project to add the component to", "x-prompt": "A quale progetto vuoi aggiungere il componente?", "x-dropdown": "projects"}
La proprietà x-dropdown: "projects"
indica a Nx di popolare la tendina con tutti i progetti nel workspace.
Argomenti Posizionali
Puoi configurare opzioni da passare come argomenti posizionali quando si esegue il generatore da riga di comando:
"name": { "type": "string", "description": "Component name", "x-priority": "important", "$default": { "$source": "argv", "index": 0 }}
Questo permette agli utenti di eseguire il generatore con nx g your-generator my-component
invece di nx g your-generator --name=my-component
.
Impostazione Priorità
Usa la proprietà x-priority
per indicare le opzioni più importanti:
"name": { "type": "string", "description": "Component name", "x-priority": "important"}
Le opzioni possono avere priorità "important"
o "internal"
. Questo aiuta Nx a ordinare le proprietà nell’estensione VSCode e nella CLI Nx.
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
Per maggiori dettagli sugli schemi, consulta la documentazione Nx Generator Options.
Tipi TypeScript con schema.d.ts
Oltre a schema.json
, il generatore crea un file schema.d.ts
che fornisce tipi TypeScript per le opzioni:
export interface YourGeneratorSchema { name: string; directory?: string; withTests?: boolean;}
Questa interfaccia viene utilizzata nell’implementazione del generatore per type safety e completamento del codice:
import { YourGeneratorSchema } from './schema';
export default async function (tree: Tree, options: YourGeneratorSchema) { // TypeScript conosce i tipi di tutte le opzioni const { name, directory = 'src/components', withTests = true } = options; // ...}
Implementazione di un Generatore
Dopo aver creato il nuovo generatore come sopra, puoi scrivere l’implementazione in generator.ts
.
Un generatore è una funzione che modifica un filesystem virtuale (Tree
), leggendo e scrivendo file per apportare le modifiche desiderate. Le modifiche al Tree
vengono scritte su disco solo al termine dell’esecuzione, a meno che non sia eseguito in modalità “dry-run”.
Ecco alcune operazioni comuni che potresti voler eseguire nel generatore:
Lettura e Scrittura di File
// Leggi un fileconst content = tree.read('path/to/file.ts', 'utf-8');
// Scrivi un filetree.write('path/to/new-file.ts', 'export const hello = "world";');
// Verifica se un file esisteif (tree.exists('path/to/file.ts')) { // Fai qualcosa}
Generazione File da Template
import { generateFiles, joinPathFragments } from '@nx/devkit';
// Genera file da templategenerateFiles( tree, joinPathFragments(__dirname, 'files'), // Directory template 'path/to/output', // Directory di output { // Variabili da sostituire nei template name: options.name, nameCamelCase: camelCase(options.name), nameKebabCase: kebabCase(options.name), // Aggiungi altre variabili se necessario },);
Manipolazione AST (Abstract Syntax Tree) TypeScript
Consigliamo di installare TSQuery per aiutare con la manipolazione AST.
import { tsquery } from '@phenomnomnominal/tsquery';import * as ts from 'typescript';
// Esempio: Incrementa numero di versione in un file
// Analizza il contenuto del file in un AST TypeScriptconst sourceFile = tsquery.ast(tree.read('path/to/version.ts', 'utf-8'));
// Trova nodi corrispondenti al selettoreconst nodes = tsquery.query( sourceFile, 'VariableDeclaration:has(Identifier[name="VERSION"]) NumericLiteral',);
if (nodes.length > 0) { // Ottieni il nodo del literal numerico const numericNode = nodes[0] as ts.NumericLiteral;
// Ottieni la versione corrente e incrementala const currentVersion = Number(numericNode.text); const newVersion = currentVersion + 1;
// Sostituisci il nodo nell'AST const result = tsquery.replace( sourceFile, 'VariableDeclaration:has(Identifier[name="VERSION"]) NumericLiteral', () => ts.factory.createNumericLiteral(newVersion), );
// Scrivi il contenuto aggiornato nel tree tree.write( 'path/to/version.ts', ts .createPrinter({ newLine: ts.NewLineKind.LineFeed, }) .printNode(ts.EmitHint.Unspecified, result, sourceFile), );}
Aggiunta Dipendenze
import { addDependenciesToPackageJson } from '@nx/devkit';
// Aggiungi dipendenze a package.jsonaddDependenciesToPackageJson( tree, { 'new-dependency': '^1.0.0', }, { 'new-dev-dependency': '^2.0.0', },);
Formattazione File Generati
import { formatFiles } from '@nx/devkit';
// Formatta tutti i file modificatiawait formatFiles(tree);
Lettura e Aggiornamento File JSON
import { readJson, updateJson } from '@nx/devkit';
// Leggi un file JSONconst packageJson = readJson(tree, 'package.json');
// Aggiorna un file JSONupdateJson(tree, 'tsconfig.json', (json) => { json.compilerOptions = { ...json.compilerOptions, strict: true, }; return json;});
Esecuzione del Generatore
Puoi eseguire il generatore in due modi:
- 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
pnpm nx g @my-project/nx-plugin:my-generator
yarn nx g @my-project/nx-plugin:my-generator
npx nx g @my-project/nx-plugin:my-generator
bunx nx g @my-project/nx-plugin:my-generator
Puoi anche eseguire una prova per vedere quali file verrebbero modificati
pnpm nx g @my-project/nx-plugin:my-generator --dry-run
yarn nx g @my-project/nx-plugin:my-generator --dry-run
npx nx g @my-project/nx-plugin:my-generator --dry-run
bunx nx g @my-project/nx-plugin:my-generator --dry-run
Test del Generatore
I test unitari per i generatori sono semplici da implementare. Ecco un pattern tipico:
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';import { yourGenerator } from './generator';
describe('your generator', () => { let tree;
beforeEach(() => { // Crea un workspace tree vuoto tree = createTreeWithEmptyWorkspace();
// Aggiungi eventuali file che devono esistere nel tree tree.write( 'project.json', JSON.stringify({ name: 'test-project', sourceRoot: 'src', }), );
tree.write('src/existing-file.ts', 'export const existing = true;'); });
it('dovrebbe generare i file attesi', async () => { // Esegui il generatore await yourGenerator(tree, { name: 'test', // Aggiungi altre opzioni richieste });
// Verifica che i file siano stati creati expect(tree.exists('src/test/file.ts')).toBeTruthy();
// Controlla il contenuto del file const content = tree.read('src/test/file.ts', 'utf-8'); expect(content).toContain('export const test');
// Puoi anche usare snapshot expect(tree.read('src/test/file.ts', 'utf-8')).toMatchSnapshot(); });
it('dovrebbe aggiornare file esistenti', async () => { // Esegui il generatore await yourGenerator(tree, { name: 'test', // Aggiungi altre opzioni richieste });
// Verifica aggiornamenti a file esistenti const content = tree.read('src/existing-file.ts', 'utf-8'); expect(content).toContain('import { test } from'); });
it('dovrebbe gestire errori', async () => { // Verifica che il generatore generi un errore in certe condizioni await expect( yourGenerator(tree, { name: 'invalid', // Aggiungi opzioni che causano errore }), ).rejects.toThrow('Messaggio di errore atteso'); });});
Punti chiave per testare i generatori:
- Usa
createTreeWithEmptyWorkspace()
per creare un filesystem virtuale - Prepara eventuali file prerequisiti prima di eseguire il generatore
- Testa sia la creazione di nuovi file che l’aggiornamento di esistenti
- Usa snapshot per contenuti complessi
- Testa condizioni di errore per garantire un fallimento controllato
Contribuire a Generator per @aws/nx-plugin
Puoi usare ts#nx-generator
anche per scaffoldare un generatore all’interno di @aws/nx-plugin
.
Quando eseguito nel nostro repository, questo generatore creerà i seguenti file:
Directorypackages/nx-plugin/src/<name>/
- schema.json Schema per l’input del generatore
- schema.d.ts Tipi TypeScript per lo schema
- generator.ts Implementazione del generatore
- generator.spec.ts Test per il generatore
Directorydocs/src/content/docs/guides/
- <name>.mdx Pagina di documentazione per il generatore
- packages/nx-plugin/generators.json Aggiornato per includere il generatore
Potrai quindi iniziare a implementare il generatore.