Aller au contenu

Générateur de Générateur Nx

Ajoute un Nx Generator à un projet TypeScript, pour vous aider à automatiser des tâches répétitives comme la création de composants ou l’application de structures de projet spécifiques.

Vous pouvez générer un générateur de deux manières :

  1. Installez le Nx Console VSCode Plugin si ce n'est pas déjà fait
  2. Ouvrez la console Nx dans VSCode
  3. Cliquez sur Generate (UI) dans la section "Common Nx Commands"
  4. Recherchez @aws/nx-plugin - ts#nx-generator
  5. Remplissez les paramètres requis
    • Cliquez sur Generate
    Paramètre Type Par défaut Description
    project Requis string - TypeScript project to add the generator to. We recommend using the ts#nx-plugin generator to create this.
    name Requis 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>)

    Le générateur créera les fichiers suivants dans le project spécifié :

    • Répertoiresrc/<name>/
      • schema.json Schéma des entrées de votre générateur
      • schema.d.ts Types TypeScript pour votre schéma
      • generator.ts Implémentation de base du générateur
      • generator.spec.ts Tests pour votre générateur
      • README.md Documentation pour votre générateur
    • generators.json Configuration Nx pour définir vos générateurs
    • package.json Créé ou mis à jour pour ajouter une entrée “generators”
    • tsconfig.json Mis à jour pour utiliser CommonJS

    Ce générateur mettra à jour le project sélectionné pour utiliser CommonJS, car les Nx Generators ne prennent actuellement en charge que CommonJS (voir cette issue GitHub pour le support ESM).

    Sélectionnez votre projet local nx-plugin lors de l’exécution du générateur ts#nx-generator, et spécifiez un nom ainsi qu’un répertoire et une description optionnels.

    Le fichier schema.json définit les options acceptées par votre générateur. Il suit le format JSON Schema avec des extensions spécifiques à Nx.

    Un fichier schema.json a la structure de base suivante :

    {
    "$schema": "https://json-schema.org/schema",
    "$id": "YourGeneratorName",
    "title": "Your Generator Title",
    "description": "Description of what your generator does",
    "type": "object",
    "properties": {
    // Vos options de générateur ici
    },
    "required": ["requiredOption1", "requiredOption2"]
    }

    Voici un exemple simple avec quelques options basiques :

    {
    "$schema": "https://json-schema.org/schema",
    "$id": "ComponentGenerator",
    "title": "Create a Component",
    "description": "Crée un nouveau composant React",
    "type": "object",
    "properties": {
    "name": {
    "type": "string",
    "description": "Nom du composant",
    "x-priority": "important"
    },
    "directory": {
    "type": "string",
    "description": "Répertoire de création du composant",
    "default": "src/components"
    },
    "withTests": {
    "type": "boolean",
    "description": "Générer des fichiers de test",
    "default": true
    }
    },
    "required": ["name"]
    }

    Personnalisez les invites affichées lors de l’exécution CLI avec la propriété x-prompt :

    "name": {
    "type": "string",
    "description": "Nom du composant",
    "x-prompt": "Quel est le nom de votre composant ?"
    }

    Pour les options booléennes :

    "withTests": {
    "type": "boolean",
    "description": "Générer des fichiers de test",
    "x-prompt": "Souhaitez-vous générer des fichiers de test ?"
    }

    Pour des choix prédéfinis, utilisez enum :

    "style": {
    "type": "string",
    "description": "Méthode de style à utiliser",
    "enum": ["css", "scss", "styled-components", "none"],
    "default": "css"
    }

    Permettez la sélection parmi les projets existants :

    "project": {
    "type": "string",
    "description": "Projet cible",
    "x-prompt": "Dans quel projet souhaitez-vous ajouter le composant ?",
    "x-dropdown": "projects"
    }

    x-dropdown: "projects" indique à Nx de peupler la liste avec tous les projets.

    Configurez des options comme arguments positionnels :

    "name": {
    "type": "string",
    "description": "Nom du composant",
    "x-priority": "important",
    "$default": {
    "$source": "argv",
    "index": 0
    }
    }

    Permet d’exécuter nx g your-generator mon-composant au lieu de --name=mon-composant.

    Utilisez x-priority pour indiquer l’importance :

    "name": {
    "type": "string",
    "description": "Nom du composant",
    "x-priority": "important"
    }

    Les priorités peuvent être "important" ou "internal".

    Définissez des valeurs par défaut :

    "directory": {
    "type": "string",
    "description": "Répertoire de création",
    "default": "src/components"
    }

    Consultez la documentation Nx sur les options de générateur.

    Le fichier schema.d.ts fournit des types pour vos options :

    export interface YourGeneratorSchema {
    name: string;
    directory?: string;
    withTests?: boolean;
    }

    Cette interface est utilisée pour la sécurité des types :

    import { YourGeneratorSchema } from './schema';
    export default async function (tree: Tree, options: YourGeneratorSchema) {
    const { name, directory = 'src/components', withTests = true } = options;
    // ...
    }

    Implémentez votre logique dans generator.ts.

    Un générateur est une fonction modifiant un système de fichiers virtuel (Tree). Les changements sont écrits sur le disque à la fin de l’exécution. Un générateur vide :

    export const myGenerator = async (tree: Tree, options: MyGeneratorSchema) => {
    // Appliquez des modifications avec le tree
    };
    export default myGenerator;

    Lecture/écriture de fichiers

    // Lire un fichier
    const content = tree.read('chemin/vers/fichier.ts', 'utf-8');
    // Écrire un fichier
    tree.write('chemin/vers/nouveau-fichier.ts', 'export const hello = "world";');
    // Vérifier l'existence
    if (tree.exists('chemin/vers/fichier.ts')) {
    // ...
    }

    Génération de fichiers depuis des templates

    Utilisez generateFiles avec des templates EJS :

    import { generateFiles, joinPathFragments } from '@nx/devkit';
    generateFiles(
    tree,
    joinPathFragments(__dirname, 'files'), // Dossier template
    'chemin/vers/sortie', // Dossier de sortie
    {
    name: options.name,
    nameCamelCase: camelCase(options.name),
    // ...
    }
    );

    Manipulation d’AST TypeScript

    Utilisez tsAstReplace pour modifier l’AST :

    import { tsAstReplace } from '@aws/nx-plugin/sdk/utils/ast';
    import * as ts from 'typescript';
    tsAstReplace(
    tree,
    'chemin/vers/version.ts',
    'VariableDeclaration:has(Identifier[name="VERSION"]) NumericLiteral',
    (node: ts.NumericLiteral) =>
    ts.factory.createNumericLiteral(Number(node.text) + 1));

    Ajout de dépendances

    import { addDependenciesToPackageJson } from '@nx/devkit';
    addDependenciesToPackageJson(
    tree,
    { 'nouvelle-dependance': '^1.0.0' },
    { 'nouvelle-dev-dependance': '^2.0.0' }
    );

    Installation des dépendances

    import { installPackagesTask } from '@nx/devkit';
    return () => {
    installPackagesTask(tree);
    };

    Formatage des fichiers

    import { formatFilesInSubtree } from '@aws/nx-plugin/sdk/utils/format';
    await formatFilesInSubtree(tree, 'chemin/optionnel');

    Manipulation de JSON

    import { readJson, updateJson } from '@nx/devkit';
    const packageJson = readJson(tree, 'package.json');
    updateJson(tree, 'tsconfig.json', (json) => {
    json.compilerOptions.strict = true;
    return json;
    });

    Extension de générateurs existants

    import { tsProjectGenerator } from '@aws/nx-plugin/sdk/ts';
    export const myGenerator = async (tree: Tree, schema: MyGeneratorSchema) => {
    const callback = await tsProjectGenerator(tree, { ... });
    // Logique supplémentaire
    return callback;
    };

    Générateurs OpenAPI

    import { openApiTsClientGenerator } from '@aws/nx-plugin/sdk/open-api';
    export const myGenerator = async (tree: Tree, schema: MyGeneratorSchema) => {
    await openApiTsClientGenerator(tree, { ... });
    // Fichiers supplémentaires
    };

    Génération basée sur les opérations OpenAPI :

    import { buildOpenApiCodeGenerationData } from '@aws/nx-plugin/sdk/open-api.js';
    const data = await buildOpenApiCodeGenerationData(tree, 'chemin/vers/spec.json');
    generateFiles(
    tree,
    joinPathFragments(__dirname, 'files'),
    'chemin/vers/sortie',
    data
    );

    Exécutez votre générateur via :

    1. Installez le Nx Console VSCode Plugin si ce n'est pas déjà fait
    2. Ouvrez la console Nx dans VSCode
    3. Cliquez sur Generate (UI) dans la section "Common Nx Commands"
    4. Recherchez @my-project/nx-plugin - my-generator
    5. Remplissez les paramètres requis
      • Cliquez sur Generate

      Exemple de tests unitaires :

      import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
      import { yourGenerator } from './generator';
      describe('votre générateur', () => {
      let tree;
      beforeEach(() => {
      tree = createTreeWithEmptyWorkspace();
      // Initialisation...
      });
      it('devrait générer les fichiers attendus', async () => {
      await yourGenerator(tree, { name: 'test' });
      expect(tree.exists('src/test/fichier.ts')).toBeTruthy();
      expect(tree.read('src/test/fichier.ts', 'utf-8')).toMatchSnapshot();
      });
      it('devrait gérer les erreurs', async () => {
      await expect(yourGenerator(tree, { name: 'invalide' }))
      .rejects.toThrow('Message d\'erreur attendu');
      });
      });

      Points clés :

      • Utilisez createTreeWithEmptyWorkspace()
      • Testez création/modification de fichiers
      • Utilisez des snapshots pour le contenu complexe
      • Testez les cas d’erreur

      Le générateur ts#nx-generator peut aussi scaffold un générateur dans @aws/nx-plugin :

      • Répertoirepackages/nx-plugin/src/<name>/
        • schema.json
        • schema.d.ts
        • generator.ts
        • generator.spec.ts
      • Répertoiredocs/src/content/docs/guides/
        • <name>.mdx
      • packages/nx-plugin/generators.json Mis à jour