Experts in Angular

Angular CLISchematics Personalizados: O Poder da Criação
Schematics Personalizados O Poder da Criação

Schematics Personalizados: O Poder da Criação

No universo em constante expansão do desenvolvimento Angular, a capacidade de personalizar e automatizar tarefas é crucial para impulsionar a produtividade e garantir a consistência do seu código. Os Schematics do Angular CLI emergem como ferramentas poderosas, permitindo que você crie seus próprios “moldes” para gerar e modificar código, adaptando o Angular CLI às suas necessidades e padrões específicos.

Imagine os Schematics como um conjunto de plantas e instruções detalhadas para construir diferentes módulos da sua nave espacial Angular. Com eles, você pode automatizar a criação de componentes, serviços, módulos e outros elementos, garantindo que cada peça se encaixe perfeitamente na estrutura da sua nave.

Criação de Schematics

Você pode criar suas próprias schematics para operar em projetos Angular. Desenvolvedores de bibliotecas geralmente empacotam schematics com suas bibliotecas para integrá-las ao Angular CLI. Você também pode criar schematics independentes para manipular os arquivos e estruturas em aplicações Angular como uma forma de personalizá-las para seu ambiente de desenvolvimento e fazê-las conformar-se aos seus padrões e restrições. As schematics podem ser encadeadas, executando outras schematics para realizar operações complexas.

Manipular o código em uma aplicação tem o potencial de ser tanto muito poderoso quanto correspondentemente perigoso. Por exemplo, criar um arquivo que já existe seria um erro, e se fosse aplicado imediatamente, descartaria todas as outras alterações aplicadas até o momento. A ferramenta de Schematics do Angular protege contra efeitos colaterais e erros criando um sistema de arquivos virtual. Uma schematic descreve um pipeline de transformações que podem ser aplicadas ao sistema de arquivos virtual. Quando uma schematic é executada, as transformações são registradas na memória e só são aplicadas no sistema de arquivos real uma vez que são confirmadas como válidas.

O Sistema de Arquivos Virtual: A Planta Baixa da Nave

O sistema de arquivos virtual é a base da operação dos Schematics. Ele é representado pela classe Tree, uma estrutura de dados que contém duas partes principais:

  • Base: Um conjunto de arquivos que já existem no seu projeto.
  • Área de Staging: Uma lista de alterações a serem aplicadas à base.

Ao realizar modificações com os Schematics, você não altera diretamente a base, mas adiciona essas modificações à área de staging. Essa abordagem garante a segurança do seu projeto, permitindo que você experimente e teste diferentes transformações sem o risco de danificar seus arquivos originais.

Regras: As Instruções de Montagem

Uma Rule é um objeto que define uma função que recebe uma Tree, aplica transformações e retorna uma nova Tree. O arquivo principal de um Schematic, geralmente chamado de index.ts, define um conjunto de regras que implementam a lógica do Schematic.

Imagine as regras como as instruções de montagem da sua nave espacial. Cada regra descreve uma etapa específica do processo, como criar um novo componente, modificar um arquivo existente ou adicionar uma dependência ao seu projeto.

Ações: As Ferramentas da Construção

As transformações aplicadas às árvores são representadas por objetos Action. Existem quatro tipos de ações:

  • Create: Cria um novo arquivo ou diretório na árvore.
  • Rename: Renomeia um arquivo ou diretório existente na árvore.
  • Overwrite: Sobrescreve o conteúdo de um arquivo existente na árvore.
  • Delete: Exclui um arquivo ou diretório da árvore.

Cada ação é executada em um contexto específico, representado pela classe SchematicContext.

Contexto do Schematic: O Ambiente de Trabalho

O contexto do Schematic, representado pelo objeto SchematicContext, fornece acesso a funções utilitárias e metadados que o Schematic pode precisar para funcionar corretamente. Ele também define uma estratégia de mesclagem (merge strategy) que determina como as alterações da árvore de staging são mescladas na árvore base. Uma alteração pode ser aceita, ignorada ou gerar uma exceção, garantindo que o processo de transformação seja seguro e controlado.

Com esses conceitos em mente, você está pronto para mergulhar no mundo da criação de Schematics e personalizar o Angular CLI para atender às suas necessidades específicas.

Definindo Regras e Ações: Construindo a Lógica da sua Fábrica de Componentes

Na jornada de criação de Schematics, as regras e ações são os elementos fundamentais que moldam o comportamento da sua “fábrica de componentes”. As regras definem as transformações a serem aplicadas ao sistema de arquivos virtual, enquanto as ações representam cada etapa individual dessas transformações.

Fábricas de Regras: A Estrutura da Lógica

Ao criar um novo Schematic com o Schematics CLI, a função de entrada gerada é uma fábrica de regras (RuleFactory). Uma RuleFactory é uma função de ordem superior que cria uma Rule.

import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';

// Você não precisa exportar a função como padrão.
// Você também pode ter mais de uma fábrica de regras por arquivo.
export function helloWorld(_options: any): Rule {
  return (tree: Tree, _context: SchematicContext) => {
    return tree;
  };
}

Neste exemplo, a função helloWorld é uma fábrica de regras que recebe um objeto de opções e retorna uma Rule. A Rule em si é uma função que recebe uma Tree e um SchematicContext, aplica transformações à árvore e retorna uma nova Tree.

Transformando Projetos: O Poder das Regras

Suas regras podem realizar diversas ações para transformar seus projetos, como chamar ferramentas externas, implementar lógica personalizada e gerar ou modificar código. Por exemplo, você pode usar uma regra para definir como um template do Schematic deve ser mesclado no projeto de destino.

Regras podem usar utilitários fornecidos com o pacote @schematics/angular.

O pacote @schematics/angular oferece uma série de funções utilitárias que facilitam o trabalho com módulos, dependências, TypeScript, AST (Abstract Syntax Tree), JSON, workspaces e projetos do Angular CLI, entre outros.

import {
  JsonAstObject,
  JsonObject,
  JsonValue,
  Path,
  normalize,
  parseJsonAst,
  strings,
} from '@angular-devkit/core';

Essas funções utilitárias são como ferramentas especializadas que auxiliam na construção e modificação da sua nave espacial Angular, permitindo que você realize tarefas complexas de forma mais simples e eficiente.

UtilitárioPropósitoUso
JsonAstObjectRepresenta a estrutura AST (Abstract Syntax Tree) de um objeto JSON.Usado para analisar e navegar em objetos JSON programaticamente, permitindo modificações sem destruir a formatação original.
JsonObjectUm tipo TypeScript que representa qualquer objeto JSON genérico.Utilizado para acessar e modificar dados JSON de forma tipada dentro de schematics.
JsonValueRepresenta qualquer valor JSON possível, incluindo objetos, arrays, strings, números, etc.Serve como tipo base para trabalhar com dados JSON de qualquer tipo dentro dos schematics.
PathRepresenta um caminho de arquivo no sistema de arquivos virtual do Angular DevKit.Usado para manipular caminhos de arquivos de maneira independente da plataforma, garantindo a portabilidade dos scripts.
normalizeNormaliza um caminho de arquivo para um formato padronizado.Converte caminhos de arquivo em um formato consistente, independente da plataforma, para garantir a correta manipulação de caminhos.
parseJsonAstAnalisa um texto JSON e retorna sua representação AST.Permite a análise de texto JSON bruto em uma estrutura AST para navegação e modificação precisas, similar ao JsonAstObject.
stringsUm conjunto de utilitários para manipulação de strings.Oferece funções para formatar strings conforme convenções de nomenclatura Angular, como dasherize, camelize, classify, etc.
Esses utilitários são parte do @angular-devkit/core e fornecem funcionalidades essenciais para trabalhar com JSON, strings e caminhos de arquivo dentro dos schematics do Angular.
Vamos criar uma regra simples que adiciona um novo arquivo ao seu projeto:
import { Rule, Tree, SchematicContext } from '@angular-devkit/schematics';
import { apply, url, template, move, chain, mergeWith } from '@angular-devkit/schematics';
import { strings } from '@angular-devkit/core';

export function hello(_options: any): Rule {
  return (tree: Tree, _context: SchematicContext) => {
    const templateSource = apply(url('./files'), [
      template({
        ..._options,
        ...strings,
      }),
      move(normalize(_options.path as string)),
    ]);
    return chain([
      mergeWith(templateSource),
    ]);
  };
}

Neste exemplo, a regra hello utiliza o template ./files/hello.component.ts para gerar um novo arquivo hello.component.ts no caminho especificado nas opções.

Definindo Opções de Entrada com um Esquema e Interfaces

Um esquema (schema) JSON é utilizado para definir as opções que um schematic pode aceitar, juntamente com seus tipos de dados, valores permitidos e padrões. As interfaces TypeScript são usadas para representar esses dados dentro do código do schematic.

Esquema JSON

O esquema JSON serve como contrato de dados para o schematic. Ele define quais opções estão disponíveis, os tipos de dados que são aceitos e quaisquer valores padrão. Esse esquema é crucial para garantir que o usuário forneça dados corretos e que o schematic funcione conforme o esperado.

Exemplo de Esquema JSON

Vamos considerar um exemplo de um schematic hipotético chamado “Hello World”. Este schematic pode ter um nome e uma opção para usar cores. O arquivo schema.json pode ser algo assim:

{
  "$schema": "http://json-schema.org/schema",
  "id": "HelloWorldSchema",
  "title": "Hello World Options Schema",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "O nome a ser usado no greeting.",
      "minLength": 1,
      "default": "world"
    },
    "useColor": {
      "type": "boolean",
      "description": "Se deve usar cores no output.",
      "default": false
    }
  },
  "required": ["name"]
}
  • $schema: Especifica o esquema JSON que estamos utilizando, garantindo conformidade com o padrão.
  • id e title: Identificadores opcionais para descrever o esquema.
  • type: Define o tipo de dado principal do esquema, que geralmente é um objeto.
  • properties: Define as propriedades esperadas no input, como name e useColor, com seus tipos e descrições.
  • required: Especifica quais propriedades são obrigatórias.

Interfaces TypeScript

Para manipular os dados dentro do código do schematic, usamos interfaces TypeScript. Estas interfaces devem refletir a estrutura definida no esquema JSON.

Exemplo de Interface TypeScript
// src/hello-world/schema.d.ts

export interface HelloWorldSchema {
  name: string;
  useColor: boolean;
}

Esta interface deve estar em linha com o que foi definido no schema.json, garantindo que o TypeScript possa oferecer tipagem estática e detectar erros de tipo em tempo de desenvolvimento.

Prompts em Schematics: Interagindo com o Usuário para uma Experiência Personalizada

Os Schematics do Angular CLI podem interagir com o usuário durante a execução, solicitando informações e personalizando o processo de geração de código. Essa interação é possível através dos prompts, que permitem que o usuário forneça valores para as opções do Schematic de forma intuitiva e dinâmica.

O Poder dos Prompts: Diálogo com o Usuário

Os prompts são perguntas personalizadas que o Angular CLI exibe ao usuário antes de executar o Schematic. As respostas fornecidas pelo usuário são então utilizadas como valores para as opções do Schematic, permitindo que ele personalize o comportamento e o resultado da geração de código.

Imagine que você está criando um Schematic para gerar um novo planeta em sua galáxia Angular. Com os prompts, você pode perguntar ao usuário o nome do planeta, o tipo de atmosfera, a presença de vida e outros detalhes importantes, personalizando o planeta gerado de acordo com suas preferências.

Definindo Prompts no Esquema JSON: A Interface de Comunicação

Para adicionar um prompt a uma opção do Schematic, basta incluir a propriedade x-prompt no esquema JSON, com o texto da pergunta que será exibida ao usuário.

Exemplo: Schematic “Hello World” com Prompts

No nosso exemplo hipotético de schematic “Hello World”, podemos melhorar a interação com o usuário perguntando seu nome e se ele prefere que a resposta seja exibida em cores.

Veja como podemos definir esses prompts no schema.json:

{
  "$schema": "http://json-schema.org/schema",
  "id": "HelloWorldSchema",
  "title": "Hello World Options Schema",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1,
      "default": "world",
      "x-prompt": "Qual é o seu nome?" // Prompt para o nome do usuário
    },
    "useColor": {
      "type": "boolean",
      "x-prompt": "Você gostaria que a resposta fosse colorida?" // Prompt para a preferência de cor
    }
  }
}
Detalhamento do Esquema com Prompts
  • x-prompt para name:
    • Prompt: “Qual é o seu nome?”
    • Tipo: String
    • Padrão: “world”
    • Este prompt pede ao usuário que insira seu nome, substituindo o padrão “world” pela entrada do usuário.
  • x-prompt para useColor:
    • Prompt: “Você gostaria que a resposta fosse colorida?”
    • Tipo: Booleano
    • Este prompt é uma pergunta sim/não que determina se a saída deve ser exibida em cores.

Utilizando Prompts em um Schematic

Vamos ver como esses prompts são utilizados na lógica do schematic:

// src/hello-world/index.ts

import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
import { HelloWorldSchema } from './schema'; // Importa a interface TypeScript

export function helloWorld(options: HelloWorldSchema): Rule {
  return (tree: Tree, _context: SchematicContext) => {
    const message = `Hello, ${options.name}!`;

    // Aplica cor à saída se o usuário optar por isso
    if (options.useColor) {
      console.log(`\x1b[32m${message}\x1b[0m`); // Código ANSI para texto verde
    } else {
      console.log(message);
    }

    return tree;
  };
}

Como os Prompts Melhoram a Experiência do Usuário

  • Simplicidade: Os prompts abstraem a complexidade das opções de configuração, apresentando ao usuário perguntas simples em vez de uma longa lista de argumentos de linha de comando.
  • Orientação: Usuários novatos podem ser guiados através da configuração sem precisar ler uma documentação extensa.
  • Flexibilidade: Usuários avançados ainda podem sobrescrever padrões usando opções de linha de comando, se desejarem.

Vantagens de Usar Prompts

  1. Facilidade de Uso: Prompts criam uma interface amigável para configurar schematics, diminuindo a barreira de entrada para o uso de schematics mais complexos.
  2. Customização: Usuários podem rapidamente customizar o comportamento de um schematic através das respostas, permitindo uma geração de código mais adaptada e relevante.
  3. Redução de Erros: Ao guiar os usuários através das opções com prompts, há uma redução na chance de erros devido a entradas incorretas de linha de comando.

Sintaxe Abreviada dos Prompts: Simplificando a Comunicação com o Usuário

Na jornada de criação de Schematics, a interação com o usuário é essencial para personalizar a geração de código. Os prompts, como vimos anteriormente, permitem que o usuário forneça informações e guie o comportamento do Schematic. Para tornar essa interação ainda mais fluida e intuitiva, o Angular CLI oferece uma sintaxe abreviada para os prompts, simplificando a definição de perguntas e respostas.

A Essência da Sintaxe Abreviada

A sintaxe abreviada permite que você defina um prompt apenas com o texto da pergunta, sem precisar especificar o tipo de entrada explicitamente. O Angular CLI infere o tipo de entrada mais adequado com base no esquema JSON da propriedade.

Por exemplo, no nosso Schematic “Hello World”, poderíamos definir os prompts da seguinte forma:

{
  "properties": {
    "name": {
      // ... outras propriedades
      "x-prompt": "Qual é o seu nome?" 
    },
    "useColor": {
      // ... outras propriedades
      "x-prompt": "Deseja a resposta colorida?" 
    }
  }
}

Tipos de Entrada para Prompts

Existem três tipos de entrada suportados para prompts, que são escolhidos automaticamente com base no tipo de propriedade definido no esquema JSON:

  1. Confirmação (confirmation): Usado para perguntas de sim ou não, ideal para opções booleanas. “Sim” corresponde a true e “não” a false.
  2. Entrada de Texto (input): Usado para entrada textual, ideal para opções de string ou número.
  3. Lista (list): Usado quando há um conjunto predefinido de valores permitidos.

Inferência Automática de Tipo

Na forma abreviada, o tipo do prompt é inferido com base no tipo e nas restrições da propriedade no esquema. Aqui estão alguns exemplos de como a inferência funciona:

Tipo de PropriedadeTipo de Prompt Inferido
"type": "boolean"Confirmação (“sim”=true, “não”=false)
"type": "string"Entrada de Texto
"type": "number"Entrada de Texto (somente números válidos aceitos)
"type": "integer"Entrada de Texto (somente números inteiros válidos aceitos)
"enum": […]Lista (os membros do enum tornam-se seleções de lista)

Exemplo de Uso da Sintaxe Abreviada

Vamos ver um exemplo onde o esquema define uma propriedade que aceita um valor enumerado. O prompt automaticamente seleciona o tipo de lista e cria um menu com os valores possíveis.

"style": {
  "description": "A extensão do arquivo ou pré-processador a ser usado para arquivos de estilo.",
  "type": "string",
  "default": "css",
  "enum": ["css", "scss", "sass", "less", "styl"],
  "x-prompt": "Qual formato de folha de estilo você gostaria de usar?"
}

Neste exemplo, o Angular CLI usa a lista como tipo de entrada para o prompt, permitindo que o usuário escolha entre as opções definidas no enum.

Detalhes do Exemplo
  • Propriedade style:
    • Descrição: Define o formato de folha de estilo a ser usado.
    • Tipo: String
    • Valores Permitidos (Enum): "css", "scss", "sass", "less", "styl"
    • Prompt: “Qual formato de folha de estilo você gostaria de usar?”

Validação Automática: Garantindo a Qualidade dos Dados

O Angular CLI valida automaticamente a resposta fornecida pelo usuário em relação às restrições definidas no esquema JSON. Se o valor não for aceitável, o usuário será solicitado a fornecer um novo valor. Isso garante que os valores passados para o Schematic atendam às expectativas da sua implementação, eliminando a necessidade de verificações adicionais no código do Schematic.

Vantagens da Sintaxe Abreviada

Validação Automática: A validação automática de entradas assegura que apenas valores válidos sejam usados, reduzindo a chance de erros durante a execução do schematic.

Simplicidade: A sintaxe abreviada reduz a quantidade de código necessário para definir prompts, tornando o código mais limpo e fácil de manter.

Inferência Automática: A capacidade de inferir automaticamente o tipo de prompt com base no esquema JSON simplifica a configuração de prompts e garante que os tipos corretos sejam usados.

Sintaxe Completa para Prompts

A sintaxe completa para prompts no campo x-prompt permite uma personalização adicional e controle sobre o comportamento do prompt, além do que é oferecido pela forma abreviada. Nesta forma completa, o valor do campo x-prompt é um objeto JSON com subcampos que definem o comportamento do prompt.

Estrutura do Campo x-prompt

Na sintaxe completa, o campo x-prompt pode incluir os seguintes subcampos:

  • type: Define o tipo de entrada, que pode ser confirmation, input ou list. Na forma abreviada, este tipo é selecionado automaticamente.
  • message: String obrigatória que especifica a mensagem a ser exibida no prompt.
  • items: Array que contém strings ou pares de objetos label/valor. Este campo é válido apenas quando o tipo é list.

Exemplo de Uso da Sintaxe Completa

Abaixo está um exemplo de um esquema JSON que define um prompt usando a sintaxe completa. Este exemplo é parte do esquema que o Angular CLI usa para gerar aplicações, e define o prompt que permite aos usuários escolher qual pré-processador de estilo desejam usar para a aplicação que está sendo criada.

// package/schematics/angular/application/schema.json
"style": {
  "description": "A extensão de arquivo ou pré-processador a ser usado para arquivos de estilo.",
  "type": "string",
  "default": "css",
  "enum": [
    "css",
    "scss",
    "sass",
    "less"
  ],
  "x-prompt": {
    "message": "Qual formato de folha de estilo você gostaria de usar?",
    "type": "list",
    "items": [
      { "value": "css",  "label": "CSS" },
      { "value": "scss", "label": "SCSS   [ https://sass-lang.com/documentation/syntax#scss                ]" },
      { "value": "sass", "label": "Sass   [ https://sass-lang.com/documentation/syntax#the-indented-syntax ]" },
      { "value": "less", "label": "Less   [ https://lesscss.org/                                            ]" }
    ]
  }
}

Detalhes do Exemplo

  • Propriedade style:
    • Descrição: Define o formato de folha de estilo a ser usado.
    • Tipo: String
    • Valores Permitidos (Enum): "css", "scss", "sass", "less"
    • Prompt:
      • Mensagem: “Qual formato de folha de estilo você gostaria de usar?”
      • Tipo: list
      • Itens:
        • "css" com o rótulo “CSS”
        • "scss" com o rótulo “SCSS” e um link para a documentação
        • "sass" com o rótulo “Sass” e um link para a documentação
        • "less" com o rótulo “Less” e um link para a documentação

Neste exemplo, a escolha do usuário é guiada por uma lista de opções que são claramente rotuladas e incluem links para documentação, permitindo que o usuário tome uma decisão informada sobre qual pré-processador usar.

Terminal

No terminal, quando o ng generate é executado com um schematic que utiliza prompts, ele pode se parecer com o seguinte:

$ ng generate @my-library/my-schematic

? What is your name? (world) John Doe
? Would you like the response in color? (y/N) y
? Which stylesheet format would you like to use? 
  CSS
❯ SCSS   [ https://sass-lang.com/documentation/syntax#scss                ]
  Sass   [ https://sass-lang.com/documentation/syntax#the-indented-syntax ]
  Less   [ https://lesscss.org/                                            ]

✔ Creating component files...
✔ Updating app.module.ts...

Schema x-prompt

O x-prompt é um recurso poderoso do Angular Schematics que permite definir interações do usuário de forma declarativa durante a execução de um schematic. Através do uso de uma sintaxe em JSON, os desenvolvedores podem configurar prompts que interagem com o usuário, solicitando informações necessárias para personalizar a execução do schematic.

A seguir, apresentamos o JSON schema completo para a definição de prompts utilizando o x-prompt. Este schema cobre a sintaxe completa e permite um entendimento mais aprofundado de como configurar prompts de forma detalhada.

Estrutura do Schema x-prompt
{
    "oneOf": [
        { "type": "string" },
        {
            "type": "object",
            "properties": {
                "type": { "type": "string" },
                "message": { "type": "string" },
                "items": {
                    "type": "array",
                    "items": {
                        "oneOf": [
                            { "type": "string" },
                            {
                                "type": "object",
                                "properties": {
                                    "label": { "type": "string" },
                                    "value": { }
                                },
                                "required": [ "value" ]
                            }
                        ]
                    }
                }
            },
            "required": [ "message" ]
        }
    ]
}

Explicação dos Campos

A estrutura acima descreve como um prompt pode ser configurado usando o campo x-prompt no schema JSON de um schematic. Vamos detalhar cada parte:

  1. oneOf:
    • Permite que o x-prompt seja configurado de duas maneiras: uma string simples ou um objeto detalhado.
    • String: No caso mais simples, apenas o texto da pergunta é necessário, e o tipo de entrada é inferido do tipo da propriedade (ex.: confirmação para booleanos).
  2. Objeto:
    • type: (Opcional) Define o tipo de entrada esperada. Os valores possíveis incluem confirmation, input ou list.
    • message: (Obrigatório) A mensagem que será exibida ao usuário. Esta é a pergunta ou instrução principal.
    • items: (Apenas para o tipo list) Uma lista de opções que o usuário pode escolher. Cada item pode ser uma string ou um objeto com label e value.
  3. items:
    • Usado para definir uma lista de opções disponíveis para seleção quando o tipo de prompt é list.
    • Cada item na lista pode ser uma string simples ou um objeto com:
      • label: O texto que será exibido ao usuário.
      • value: O valor associado ao item selecionado.

Uso na Prática

Vamos considerar um exemplo prático para entender como esse schema é usado:

Exemplo de Schema JSON para Prompt

{
    "style": {
        "type": "string",
        "enum": ["css", "scss", "sass", "less"],
        "x-prompt": {
            "message": "Which stylesheet format would you like to use?",
            "type": "list",
            "items": [
                { "label": "CSS", "value": "css" },
                { "label": "SCSS", "value": "scss" },
                { "label": "Sass", "value": "sass" },
                { "label": "Less", "value": "less" }
            ]
        }
    }
}

Explicação do Exemplo

  • style: A propriedade do schema que estamos configurando.
  • type: “string”, pois estamos lidando com uma escolha de estilo.
  • enum: Define os valores permitidos.
  • x-prompt: Configura o prompt que será mostrado ao usuário.
    • message: “Which stylesheet format would you like to use?”
    • type: “list”, pois queremos apresentar uma lista de opções.

Schematics CLI: A Forja dos Seus Schematics Personalizados

O Angular Schematics fornece uma ferramenta de linha de comando própria, conhecida como schematics-cli, que facilita a criação, modificação e execução de coleções de schematics. Esta ferramenta é essencial para desenvolvedores que desejam criar schematics personalizados para automatizar tarefas ou integrar bibliotecas Angular com a CLI Angular.
O Schematics CLI é essa ferramenta, um companheiro essencial na sua jornada de automação e personalização do Angular CLI.

Instalando o Schematics CLI: A Bigorna da Criação

Para começar a trabalhar com schematics, você precisa instalar a ferramenta de linha de comando schematics-cli. Para isso, você deve ter o Node.js na versão 6.9 ou superior instalado em seu sistema. A instalação pode ser feita globalmente com o seguinte comando:

npm install -g @angular-devkit/schematics-cli

Com o Schematics CLI instalado, você terá acesso ao executável schematics, que permite criar novas coleções de Schematics, adicionar novos Schematics a coleções existentes e estender Schematics já existentes.

Funcionalidades do Schematics CLI

O schematics-cli oferece diversas funcionalidades que facilitam o trabalho com schematics, incluindo:

  • Criação de uma nova coleção de schematics: Inicializa um novo projeto de schematics com a estrutura de diretórios e arquivos padrão.
  • Adição de um novo schematic a uma coleção existente: Permite expandir uma coleção de schematics com novas funcionalidades.
  • Extensão de um schematic existente: Fornece a capacidade de modificar ou estender o comportamento de schematics já existentes.

Criando uma Coleção de Schematics: A Base de Lançamento da Sua Fábrica de Componentes

Com o Schematics CLI instalado, estamos prontos para dar o primeiro passo na criação de nossos próprios Schematics: a construção da coleção. Imagine a coleção como a base de lançamento da sua fábrica de componentes, onde todos os seus Schematics serão armazenados e organizados.

A criação de uma coleção de schematics é um passo fundamental para personalizar e automatizar tarefas dentro do ecossistema Angular. Usando a CLI de Schematics, você pode rapidamente iniciar uma nova coleção e definir schematics personalizados para suas necessidades específicas.

Criando uma Coleção Vazia: O Primeiro Passo

Para começar, você pode usar o seguinte comando para criar um novo schematic chamado hello-world dentro de um novo diretório de projeto com o mesmo nome:

schematics blank --name=hello-world

Este comando utiliza o Schematic blank fornecido pelo Schematics CLI para gerar um novo projeto Node.js com a estrutura básica de uma coleção de Schematics. O nome da coleção será hello-world, e um Schematic inicial com o mesmo nome será criado dentro da pasta src/hello-world.

Estrutura de Diretórios Criada

Após executar o comando, a CLI de Schematics gera a seguinte estrutura de diretórios e arquivos:

hello-world/
|-- src/
|   |-- hello-world/
|   |   |-- index.ts
|   |   |-- schema.json
|   |-- collection.json
|-- package.json
|-- README.md
|-- tsconfig.json

Criando uma Coleção de Schematics: A Base de Lançamento da Sua Fábrica de Componentes

Com o Schematics CLI instalado, estamos prontos para dar o primeiro passo na criação de nossos próprios Schematics: a construção da coleção. Imagine a coleção como a base de lançamento da sua fábrica de componentes, onde todos os seus Schematics serão armazenados e organizados.

Criando uma Coleção Vazia: O Primeiro Passo

Para criar uma nova coleção de Schematics, utilize o seguinte comando:

Bash

schematics blank --name=hello-world

Use o código com cuidado.

Este comando utiliza o Schematic blank fornecido pelo Schematics CLI para gerar um novo projeto Node.js com a estrutura básica de uma coleção de Schematics. O nome da coleção será hello-world, e um Schematic inicial com o mesmo nome será criado dentro da pasta src/hello-world.

Explorando a Estrutura da Coleção

Após criar a coleção, navegue até o diretório hello-world e instale as dependências do projeto:

Bash

cd hello-world
npm install
npm run build

Use o código com cuidado.

O comando npm install baixa e instala todas as dependências listadas no arquivo package.json, enquanto o comando npm run build compila o código TypeScript dos seus Schematics para JavaScript, tornando-os executáveis pelo Angular CLI.

Agora, você pode abrir o projeto em seu editor de código favorito para explorar os arquivos gerados.

Anatomia da Coleção

A estrutura básica de uma coleção de Schematics é a seguinte:

  • src/hello-world/index.ts: Contém o código-fonte do schematic, onde você implementa a lógica que o schematic irá executar.
  • src/hello-world/schema.json: Define o esquema de entrada do schematic, incluindo as opções disponíveis e seus tipos.
  • src/collection.json: Lista todos os schematics disponíveis na coleção e suas configurações.
  • package.json: Arquivo de manifesto npm, necessário para gerenciar dependências.
  • README.md: Documento que pode ser usado para explicar o propósito e uso do seu schematic.
  • tsconfig.json: Arquivo de configuração TypeScript.

Instalando Dependências e Executando o Build

Após a criação do projeto, é importante instalar as dependências necessárias e compilar o código do schematic. Execute os seguintes comandos dentro do diretório do projeto:

cd hello-world
npm install
npm run build

O comando npm install instala todas as dependências listadas no package.json, enquanto o comando npm run build compila o código TypeScript para JavaScript, gerando os arquivos necessários para a execução do schematic.

Abrindo o Projeto no Editor

Para inspecionar os arquivos gerados e começar a modificar o código do schematic, você pode abrir o projeto em seu editor de código favorito. Por exemplo, se você estiver usando o VS Code, execute:

code .

Isso abrirá o VS Code no diretório do projeto, permitindo que você veja e edite os arquivos gerados.

Desenvolvendo o Schematic

Dentro do arquivo src/hello-world/index.ts, você encontrará um esqueleto básico para começar a desenvolver seu schematic. É aqui que você adicionará a lógica para manipular o projeto Angular ou executar outras tarefas automatizadas.

Por exemplo, se você deseja que o schematic crie um novo componente Angular, você pode usar funções auxiliares fornecidas pelo Angular Schematics para adicionar arquivos, modificar conteúdo existente ou executar comandos adicionais.

Modificando o Código Gerado: Dando Vida aos Schematics

O código gerado pelo Schematics CLI é apenas um esqueleto básico. Você precisará modificá-lo para implementar a lógica específica do seu Schematic, utilizando as funções e utilitários fornecidos pelo Angular DevKit.

Com a base de lançamento da sua fábrica de componentes pronta, você está preparado para criar seus próprios Schematics e automatizar tarefas, gerar código de alta qualidade e personalizar o Angular CLI de acordo com suas necessidades.

Executando um Schematic: Dando Vida à sua Criação

Após criar sua coleção de Schematics e implementar a lógica de transformação no arquivo index.ts, chegou o momento de colocar sua “fábrica de componentes” em ação. O comando schematics do Schematics CLI é a chave para executar seus Schematics e aplicar as transformações desejadas ao seu projeto Angular.

O Comando schematics: A Linha de Produção

Para executar um schematic, você usará o comando schematics. Este comando requer que você forneça o caminho para a coleção de schematics, o nome do schematic que deseja executar e quaisquer opções obrigatórias necessárias para o funcionamento do schematic.

A sintaxe geral do comando é a seguinte:

schematics <caminho-para-o-projeto-de-schematics>:<nome-do-schematic> --<opção-obrigatória>=<valor>
  • <caminho-para-o-projeto-de-schematics>: O caminho absoluto ou relativo para a pasta do projeto que contém sua coleção de Schematics.
  • <nome-do-schematic>: O nome do Schematic que você deseja executar.
  • --<opção-obrigatória>=<valor>: Quaisquer opções obrigatórias definidas no esquema JSON do Schematic.

Exemplos de Uso

Executar um Schematic Localmente

Se você está no diretório raiz do projeto de schematics e deseja executar o schematic recém-criado, você pode usar o caminho relativo . (ponto) para se referir ao diretório atual. Se o schematic não requer opções obrigatórias, o comando será simples:

schematics .:hello-world

Neste exemplo, . indica o diretório atual, e hello-world é o nome do schematic que você deseja executar.

Executar um Schematic com Opções

Se o schematic requer opções obrigatórias, você precisará especificá-las usando a sintaxe --<nome-da-opção>=<valor>. Suponha que seu schematic tenha uma opção obrigatória chamada name, o comando seria:

schematics .:hello-world --name=MyComponent

Neste caso, a opção name é passada com o valor MyComponent.

Executar um Schematic em um Caminho Específico

Se a coleção de schematics estiver localizada em um caminho específico e não no diretório atual, você deve fornecer o caminho completo ou relativo para a coleção:

schematics /caminho/para/hello-world:hello-world

Aqui, /caminho/para/hello-world é o caminho completo para a coleção de schematics.

O que Acontece Quando Você Executa um Schematic

Ao executar um schematic, a CLI de Schematics processa as transformações definidas no arquivo index.ts do schematic. Isso pode incluir a criação de novos arquivos, modificação de arquivos existentes ou execução de qualquer lógica de negócios que você tenha implementado.

Por exemplo, se o schematic hello-world estiver programado para criar um novo componente Angular, ao executar o schematic, você verá os novos arquivos de componente gerados no local especificado.

Adicionando um Schematic a uma Coleção: Expandindo a Fábrica de Componentes

À medida que sua nave espacial Angular cresce e evolui, você pode precisar adicionar novos módulos e funcionalidades. Da mesma forma, à medida que seu projeto Angular se expande, você pode precisar criar novos Schematics para automatizar tarefas específicas e manter a consistência do seu código.

O Angular CLI permite que você adicione novos Schematics a uma coleção existente de forma simples e intuitiva, expandindo sua “fábrica de componentes” e tornando-a ainda mais versátil.

Como Adicionar um Schematic a uma Coleção

Para adicionar um novo schematic a uma coleção existente, você deve navegar até a pasta do projeto da coleção e usar o comando schematics com o subcomando blank. Isso criará um novo schematic dentro da coleção.

Passos para Adicionar um Novo Schematic

1 – Navegue para a Pasta do Projeto

Antes de adicionar um novo schematic, certifique-se de estar no diretório raiz do projeto de schematics. Use o comando cd para navegar até a pasta, se necessário.

cd hello-world

Neste exemplo, hello-world é o diretório do projeto onde sua coleção de schematics está localizada.

2 – Execute o Comando para Criar um Novo Schematic

Com o terminal no diretório do projeto, use o comando schematics para adicionar um novo schematic à coleção existente. O comando blank cria um template básico para o novo schematic.

schematics blank --name=goodbye-world
  • blank: É o nome do schematic fornecido pelo CLI que gera um novo esqueleto de schematic.
  • --name=goodbye-world: Especifica o nome do novo schematic que você está criando. Neste exemplo, o nome é goodbye-world.
3 – Arquivos e Estrutura Criados

O comando acima gera os seguintes arquivos e estrutura para o novo schematic:

  • src/goodbye-world: O diretório que contém o novo schematic.
  • src/goodbye-world/index.ts: O arquivo principal onde você define a lógica do schematic.
  • src/goodbye-world/index.spec.ts: Um arquivo de teste associado para o schematic.
  • Atualizações em collection.json: O arquivo collection.json da coleção é atualizado para incluir o novo schematic.

Atualizações no collection.json

Quando você adiciona um novo schematic a uma coleção, o arquivo collection.json é automaticamente atualizado para registrar o novo schematic. Ele inclui o nome, a descrição e a função de fábrica do novo schematic. Aqui está um exemplo de como isso pode parecer após adicionar goodbye-world:

{
  "schematics": {
    "hello-world": {
      "description": "A blank schematic.",
      "factory": "./src/hello-world/index#helloWorld"
    },
    "goodbye-world": {
      "description": "A blank schematic.",
      "factory": "./src/goodbye-world/index#goodbyeWorld"
    }
  }
}

Conteúdo da Coleção de Schematics

Ao criar uma coleção de schematics, a estrutura do projeto e os arquivos de configuração desempenham um papel crucial em como a coleção é organizada e utilizada. Vamos explorar como a pasta raiz do projeto de uma coleção é estruturada e o propósito de cada arquivo dentro dessa estrutura.

Estrutura da Coleção

No nível superior da pasta raiz do projeto para uma coleção, encontramos vários arquivos e pastas que configuram e implementam os schematics. A estrutura básica inclui:

  • Arquivos de Configuração: Arquivos como package.json, tsconfig.json, etc., que configuram o ambiente e as dependências do projeto.
  • Pasta node_modules: Contém pacotes e dependências instalados via npm.
  • Pasta src/: Onde os schematics reais e suas lógicas são implementados.

Pasta src/

Dentro da pasta src/, você encontrará subpastas para cada schematic nomeado na coleção. Além disso, há um arquivo chamado collection.json que descreve os schematics coletados.

collection.json

O arquivo collection.json é fundamental para definir a estrutura e as propriedades dos schematics na coleção. Aqui está um exemplo de como ele pode ser estruturado:

{
  "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
  "schematics": {
    "hello-world": {
      "description": "A blank schematic.",
      "factory": "./hello-world/index#helloWorld"
    }
  }
}

Detalhamento dos Campos

  • $schema:
    • Especifica o esquema JSON que o CLI usa para validação. Isso garante que o collection.json siga o formato esperado pelo Angular CLI.
  • schematics:
    • Lista os schematics nomeados que pertencem a esta coleção. Cada schematic é definido por várias propriedades.
  • description:
    • Fornece uma descrição em texto simples do schematic. Isso ajuda a identificar rapidamente o propósito do schematic.
  • factory:
    • Aponta para a função de fábrica gerada que será chamada para executar o schematic. No exemplo acima, o schematic hello-world é invocado chamando a função de fábrica helloWorld() localizada no arquivo ./hello-world/index.ts.
  • schema (opcional):
    • Aponta para um arquivo de esquema JSON que define as opções de linha de comando disponíveis para o schematic. Isso permite a validação e o preenchimento automático de opções no CLI.
  • aliases (opcional):
    • Especifica uma ou mais strings que podem ser usadas como atalhos para invocar o schematic. Por exemplo, o schematic para o comando “generate” do Angular CLI possui um alias “g”, permitindo que você use o comando ng g.

Exemplo de Invocação

Com a estrutura definida no collection.json, você pode invocar o schematic hello-world usando o Angular CLI com a seguinte sintaxe:

schematics <caminho-da-coleção>:hello-world

Ou, se hello-world tivesse um alias definido como “hw”, você poderia invocar com:

schematics <caminho-da-coleção>:hw

Ao manter sua coleção de Schematics bem organizada, com descrições claras e nomes intuitivos, você facilita a navegação e o uso dos seus Schematics por outros desenvolvedores.

Schematics Nomeados: As Ferramentas Especializadas da sua Fábrica

Em nossa jornada pela criação de Schematics, exploramos a estrutura da coleção e o papel do arquivo collection.json. Agora, vamos mergulhar nos Schematics nomeados, que são as ferramentas especializadas da sua fábrica de componentes, cada uma com sua função e propósito específicos.

O Primeiro Schematic: A Fundação da Fábrica

Ao criar um novo projeto de Schematics com o Schematics CLI, o primeiro Schematic gerado tem o mesmo nome da coleção e é automaticamente adicionado ao arquivo collection.json. Esse Schematic inicial serve como base para você começar a construir sua fábrica de componentes.

Anatomia de um Schematic Nomeado: As Peças da Ferramenta

Cada Schematic nomeado na sua coleção possui as seguintes partes principais:

  • index.ts: O arquivo principal do Schematic, onde você define a lógica de transformação do seu projeto Angular. É aqui que você utiliza as funções e utilitários do Angular DevKit para criar, modificar ou excluir arquivos, atualizar dependências, aplicar regras de estilo e realizar outras tarefas.
  • schema.json: O esquema JSON do Schematic, que define as opções de entrada que o usuário pode fornecer na linha de comando, seus tipos de dados, valores padrão e outras informações relevantes.
  • schema.d.ts: Um arquivo de definição de tipos para o esquema JSON, que facilita a utilização das opções em seu código TypeScript, oferecendo recursos como autocompletar e verificação de tipos.
  • files/ (opcional): Uma pasta que contém arquivos de componente e template que podem ser replicados no seu projeto Angular. Essa pasta é útil para criar Schematics que geram estruturas de código mais complexas, como componentes, serviços ou módulos completos.
coleção de schematics do Angular CLI

Lógica no index.ts: A Alma do Schematic

É possível que um Schematic forneça toda a sua lógica no arquivo index.ts, sem a necessidade de templates adicionais. No entanto, para criar Schematics mais dinâmicos e flexíveis, você pode utilizar templates na pasta files/, como aqueles encontrados em projetos Angular standalone. A lógica no arquivo index.ts configura esses templates, injetando dados e modificando variáveis de acordo com as opções fornecidas pelo usuário.

Exemplo: O Schematic “hello-world”

Vamos relembrar o exemplo do Schematic hello-world que criamos anteriormente.

// src/hello-world/index.ts
import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';

export function helloWorld(_options: any): Rule {
  return (tree: Tree, _context: SchematicContext) => {
    tree.create("/hello.txt", "Hello, World!"); 
    return tree;
  };
}

Neste exemplo, o Schematic hello-world cria um arquivo chamado hello.txt na raiz do projeto com o conteúdo “Hello, World!”. Essa lógica é definida diretamente no arquivo index.ts, sem a necessidade de templates adicionais.

Schematics Dinâmicos com Templates

Para criar Schematics mais complexos e personalizados, você pode utilizar templates na pasta files/. Esses templates podem conter código Angular, HTML, CSS ou qualquer outro tipo de arquivo que você precise gerar.

A lógica no arquivo index.ts irá configurar esses templates, substituindo variáveis e aplicando transformações de acordo com as opções fornecidas pelo usuário.

Com os Schematics nomeados e o uso de templates, você tem o poder de criar ferramentas especializadas que automatizam tarefas complexas e geram código de alta qualidade, adaptado às necessidades específicas do seu projeto Angular.

Analisando um Exemplo Completo: O Schematic “address-form” do Angular Material

Para solidificar nosso entendimento sobre a criação de Schematics, vamos mergulhar em um exemplo real e completo: o Schematic address-form do Angular Material. Este Schematic gera um formulário de endereço utilizando os componentes do Angular Material e o Reactive Forms.

Esse exemplo cria um formulário de endereço usando o Angular Material, ilustrando a estrutura e o funcionamento de um schematic completo. Veremos o uso de templates EJS, integração com o Angular CLI e a configuração necessária para que o schematic funcione corretamente.

Componentes Principais do Exemplo

1. Arquivo <a href="https://github.com/angular/components/blob/main/src/material/schematics/ng-generate/address-form/index.ts">index.ts</a>

O arquivo <a href="https://github.com/angular/components/blob/main/src/material/schematics/ng-generate/address-form/index.ts">index.ts</a> é a entrada principal do schematic e define a lógica que será aplicada.

import {chain, noop, Rule, Tree} from '@angular-devkit/schematics';
import {
  addModuleImportToModule,
  buildComponent,
  findModuleFromOptions,
  isStandaloneSchematic,
} from '@angular/cdk/schematics';
import {Schema} from './schema';

/**
 * Scaffolds a new table component.
 * Internally it bootstraps the base component schematic
 */
export default function (options: Schema): Rule {
  return chain([
    buildComponent(
      {...options},
      {
        template:
          './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html.template',
        stylesheet:
          './__path__/__name@dasherize@if-flat__/__name@dasherize__.component.__style__.template',
      },
    ),
    options.skipImport ? noop() : addFormModulesToModule(options),
  ]);
}

/**
 * Adds the required modules to the relative module.
 */
function addFormModulesToModule(options: Schema) {
  return async (host: Tree) => {
    const isStandalone = await isStandaloneSchematic(host, options);

    if (!isStandalone) {
      const modulePath = (await findModuleFromOptions(host, options))!;
      addModuleImportToModule(host, modulePath, 'MatInputModule', '@angular/material/input');
      addModuleImportToModule(host, modulePath, 'MatButtonModule', '@angular/material/button');
      addModuleImportToModule(host, modulePath, 'MatSelectModule', '@angular/material/select');
      addModuleImportToModule(host, modulePath, 'MatRadioModule', '@angular/material/radio');
      addModuleImportToModule(host, modulePath, 'MatCardModule', '@angular/material/card');
      addModuleImportToModule(host, modulePath, 'ReactiveFormsModule', '@angular/forms');
    }
  };
}
Explicação
  • chain: Utilizado para executar múltiplas regras sequencialmente.
  • buildComponent: Função que cria o componente a partir de templates.
  • addFormModulesToModule: Função que adiciona os módulos necessários ao módulo do Angular.
  • noop: Função “no-operation”, usada quando nenhuma ação é necessária (como em skipImport).

2. Arquivo de Template

Este exemplo faz uso de templates EJS para gerar código dinâmico.

Template EJS
import { Component, inject<% if(!!viewEncapsulation) { %>, ViewEncapsulation<% }%><% if(changeDetection !== 'Default') { %>, ChangeDetectionStrategy<% }%> } from '@angular/core';
<% if(standalone) { %>
import { ReactiveFormsModule, FormBuilder, Validators } from '@angular/forms';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { MatSelectModule } from '@angular/material/select';
import { MatRadioModule } from '@angular/material/radio';
import { MatCardModule } from '@angular/material/card';
<% } else { %>
import { FormBuilder, Validators } from '@angular/forms';
<% } %>

@Component({
  selector: '<%= selector %>',<% if(inlineTemplate) { %>
  template: `
    <%= indentTextContent(resolvedFiles.template, 4) %>
  `,<% } else { %>
  templateUrl: './<%= dasherize(name) %>.component.html',<% } if(inlineStyle) { %>
  styles: `
    <%= indentTextContent(resolvedFiles.stylesheet, 4) %>
  `<% } else { %>
  styleUrl: './<%= dasherize(name) %>.component.<%= style %>'<% } %><% if(!!viewEncapsulation) { %>,
  encapsulation: ViewEncapsulation.<%= viewEncapsulation %><% } if (changeDetection !== 'Default') { %>,
  changeDetection: ChangeDetectionStrategy.<%= changeDetection %><% } %><% if(standalone) { %>,
  standalone: true,
  imports: [
    MatInputModule,
    MatButtonModule,
    MatSelectModule,
    MatRadioModule,
    MatCardModule,
    ReactiveFormsModule
  ]<% } %>
})
export class <%= classify(name) %>Component {
  private fb = inject(FormBuilder);
  addressForm = this.fb.group({
    company: null,
    firstName: [null, Validators.required],
    lastName: [null, Validators.required],
    address: [null, Validators.required],
    address2: null,
    city: [null, Validators.required],
    state: [null, Validators.required],
    postalCode: [null, Validators.compose([
      Validators.required, Validators.minLength(5), Validators.maxLength(5)])
    ],
    shipping: ['free', Validators.required]
  });

  hasUnitNumber = false;

  states = [
    {name: 'Alabama', abbreviation: 'AL'},
    {name: 'Alaska', abbreviation: 'AK'},
    // ...
  ];

  onSubmit(): void {
    alert('Thanks!');
  }
}
Explicação do EJS
  • O código utiliza a sintaxe EJS <% ... %> para incluir importações condicionais, com base nas opções escolhidas pelo usuário.
  • Se o usuário selecionou um tipo de viewEncapsulation, ele é importado e utilizado na configuração do componente.
  • Se a estratégia de changeDetection for diferente da padrão, ela também é importada e utilizada.
  • Se o componente for standalone, os módulos do Angular Material e o ReactiveFormsModule são importados diretamente no componente. Caso contrário, apenas o FormBuilder e Validators são importados.
  • A configuração do componente utiliza EJS para definir o seletor, o template (interno ou externo), os estilos (internos ou externos), o encapsulamento de visualização, a estratégia de detecção de mudanças e, se o componente for standalone, as importações de módulos.
  • A função dasherize converte o nome do componente para kebab-case, garantindo um seletor válido.
  • As funções indentTextContent e resolvedFiles são utilitários do Angular CLI para lidar com templates e estilos externos.
  • A classe do componente contém a lógica do formulário, incluindo a criação do formulário reativo com o FormBuilder, a definição dos campos e seus validadores, e a função onSubmit para lidar com o envio do formulário.
  • A variável hasUnitNumber controla a exibição condicional do campo de número da unidade no template.
  • O array states fornece os dados para o componente de seleção de estados.

3. Arquivo schema.json

O schema.json define as opções que o schematic aceita, como tipos, valores padrão, e prompts interativos.

{
  "$schema": "http://json-schema.org/draft-07/schema",
  "$id": "SchematicsMaterialAddressForm",
  "title": "Material Address Form Options Schema",
  "type": "object",
  "properties": {
    "path": {
      "type": "string",
      "format": "path",
      "$default": {
        "$source": "workingDirectory"
      },
      "description": "The path to create the component.",
      "visible": false
    },
    "project": {
      "type": "string",
      "description": "The name of the project.",
      "$default": {
        "$source": "projectName"
      }
    },
    "name": {
      "type": "string",
      "description": "The name of the component.",
      "$default": {
        "$source": "argv",
        "index": 0
      },
      "x-prompt": "What should be the name of the component?"
    },
    // ...
  },
  "required": ["name"]
}

Componentes Principais

  • Propriedades: Define os parâmetros que o schematic aceita, como name, project, inlineStyle, etc.
  • x-prompt: Proporciona prompts interativos para coletar dados do usuário.
  • Tipos e Enumerações: Define o tipo de dados e valores permitidos, como enum para style.

Considerações Finais

O exemplo cobre um caso real de criação de componentes usando Angular Material e mostra como um schematic pode ser configurado para gerar código dinâmico com base nas entradas do usuário. Este conhecimento é fundamental para criar schematics personalizados que podem padronizar e automatizar a criação de componentes ou modificar a estrutura de projetos Angular, promovendo consistência e reduzindo erros.