Generatore di Generatori Nx
Aggiunge un Nx Generator a un progetto TypeScript, per aiutarti ad automatizzare task ripetitivi come la creazione di componenti o l’imposizione di strutture di progetto specifiche.
Utilizzo
Sezione intitolata “Utilizzo”Generare un Generatore
Sezione intitolata “Generare 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
Sezione intitolata “Opzioni”Parametro | Tipo | Predefinito | Descrizione |
---|---|---|---|
project Obbligatorio | string | - | TypeScript project to add the generator to. We recommend using the ts#nx-plugin generator to create this. |
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
Sezione intitolata “Output del Generatore”Il generatore creerà i seguenti file all’interno del project
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
- README.md Documentazione del 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 project
selezionato per utilizzare CommonJS, poiché attualmente i generatori Nx supportano solo CommonJS (fai riferimento a questa issue GitHub per il supporto ESM).
Generatori Locali
Sezione intitolata “Generatori Locali”Seleziona il tuo progetto locale nx-plugin
quando esegui il generatore ts#nx-generator
, e specifica un nome, una directory opzionale e una descrizione.
Definizione dello Schema
Sezione intitolata “Definizione dello Schema”Il file schema.json
definisce le opzioni accettate dal generatore. 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 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 durante l’esecuzione del generatore via CLI aggiungendo la proprietà x-prompt
:
"name": { "type": "string", "description": "Component name", "x-prompt": "What is the name of your component?"}
Per opzioni booleane, puoi usare un prompt sì/no:
"withTests": { "type": "boolean", "description": "Whether to generate test files", "x-prompt": "Would you like to generate test files?"}
Selezione a Tendina
Sezione intitolata “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
Sezione intitolata “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": "Which project would you like to add the component to?", "x-dropdown": "projects"}
La proprietà x-dropdown: "projects"
indica a Nx di popolare la tendina con tutti i progetti nel workspace.
Argomenti Posizionali
Sezione intitolata “Argomenti Posizionali”Puoi configurare opzioni da passare come argomenti posizionali quando si esegue il generatore dalla CLI:
"name": { "type": "string", "description": "Component name", "x-priority": "important", "$default": { "$source": "argv", "index": 0 }}
Questo permette agli utenti di eseguire il generatore come nx g your-generator my-component
invece di nx g your-generator --name=my-component
.
Impostazione Priorità
Sezione intitolata “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 di Nx e nella CLI 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"}
Maggiori Informazioni
Sezione intitolata “Maggiori Informazioni”Per maggiori dettagli sugli schemi, consulta la documentazione Nx Generator Options.
Tipi TypeScript con schema.d.ts
Sezione intitolata “Tipi TypeScript con schema.d.ts”Insieme a schema.json
, il generatore crea un file schema.d.ts
che fornisce tipi TypeScript per le opzioni del generatore:
export interface YourGeneratorSchema { name: string; directory?: string; withTests?: boolean;}
Questa interfaccia viene utilizzata nell’implementazione del generatore per garantire 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
Sezione intitolata “Implementazione di un Generatore”Dopo aver creato il nuovo generatore come sopra, puoi scrivere la tua 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 dal Tree
vengono scritte su disco solo al termine dell’esecuzione del generatore, a meno che non sia eseguito in modalità “dry-run”. Un generatore vuoto appare così:
export const myGenerator = async (tree: Tree, options: MyGeneratorSchema) => { // Usa il tree per applicare modifiche};
export default myGenerator;
Ecco alcune operazioni comuni che potresti voler eseguire nel tuo generatore:
Lettura e Scrittura di File
Sezione intitolata “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
Sezione intitolata “Generazione File da Template”Puoi generare file con l’utility generateFiles
da @nx/devkit
. Questo permette di definire template in sintassi EJS e sostituire variabili.
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
Sezione intitolata “Manipolazione AST (Abstract Syntax Tree) TypeScript”Puoi usare il metodo tsAstReplace
esposto dal Nx Plugin for AWS per sostituire parti di un abstract syntax tree TypeScript.
import { tsAstReplace } from '@aws/nx-plugin/sdk/utils/ast';import * as ts from 'typescript';
// Esempio: Incrementa numero versione in un filetsAstReplace( tree, 'path/to/version.ts', 'VariableDeclaration:has(Identifier[name="VERSION"]) NumericLiteral', (node: ts.NumericLiteral) => ts.factory.createNumericLiteral(Number(node.text) + 1));
Aggiunta Dipendenze
Sezione intitolata “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
Sezione intitolata “Formattazione File Generati”import { formatFilesInSubtree } from '@aws/nx-plugin/sdk/utils/format';
// Formatta tutti i file modificatiawait formatFilesInSubtree(tree, 'optional/path/to/format');
Lettura e Aggiornamento File JSON
Sezione intitolata “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;});
Estensione di un Generatore dal Nx Plugin for AWS
Sezione intitolata “Estensione di un Generatore dal Nx Plugin for AWS”Puoi importare generatori dal Nx Plugin for AWS ed estenderli o combinarli come desideri. Ad esempio, potresti creare un generatore 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, { ... });
// Estendi qui il generatore di progetti TypeScript
// Restituisci il callback per assicurare l'installazione delle dipendenze. // Puoi wrappare il callback se desideri eseguire operazioni aggiuntive nel callback del generatore. return callback;};
Generatori OpenAPI
Sezione intitolata “Generatori OpenAPI”Puoi utilizzare ed estendere i generatori che usiamo per client e 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, { ... });
// Aggiungi file aggiuntivi qui};
Esponiamo anche un metodo che ti permette di costruire una struttura dati utilizzabile per iterare sulle operazioni in una specifica OpenAPI e quindi strumentare la tua generazione di codice, ad 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(__dirname, 'files'), // Directory template 'path/to/output', // Directory di output data, );};
Questo ti permette di scrivere template come:
export const myOperationNames = [<%_ allOperations.forEach((op) => { _%> '<%- op.name %>',<%_ }); _%>];
Fai riferimento al repository su GitHub per esempi di template più complessi.
Esecuzione del Tuo Generatore
Sezione intitolata “Esecuzione del Tuo Generatore”Puoi eseguire il tuo 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 Tuo Generatore
Sezione intitolata “Test del Tuo 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 file che devono già 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('should generate expected files', 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 usare anche snapshot expect(tree.read('src/test/file.ts', 'utf-8')).toMatchSnapshot(); });
it('should update existing files', async () => { // Esegui il generatore await yourGenerator(tree, { name: 'test', // Aggiungi altre opzioni richieste });
// Verifica che i file esistenti siano stati aggiornati const content = tree.read('src/existing-file.ts', 'utf-8'); expect(content).toContain('import { test } from'); });
it('should handle errors', async () => { // Aspettati che il generatore sollevi un errore in certe condizioni await expect( yourGenerator(tree, { name: 'invalid', // Aggiungi opzioni che dovrebbero causare un errore }), ).rejects.toThrow('Expected error message'); });});
Punti chiave per testare i generatori:
- Usa
createTreeWithEmptyWorkspace()
per creare un filesystem virtuale - Configura file prerequisiti prima di eseguire il generatore
- Testa sia la creazione di nuovi file che l’aggiornamento di file esistenti
- Usa snapshot per contenuti di file complessi
- Testa condizioni di errore per garantire un fallimento controllato
Contribuire a Generatori in @aws/nx-plugin
Sezione intitolata “Contribuire a Generatori in @aws/nx-plugin”Puoi anche usare ts#nx-generator
per scaffoldare un generatore all’interno di @aws/nx-plugin
.
Quando questo generatore viene eseguito nel nostro repository, genererà 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 tuo generatore.