Set up your own Angular schematics in no time with ngx-cli-toolkit
Tags: angular, schematics
Published: 2021-06-05 23:13:01

If you are familiar with Angular, you might already know how to use `ng update`, `ng add` or `ng generate`. Every time you execute those commands, a so-called schematic gets executed.

Schematics are a great way to save developers hours of work on reading migration guides or copying boilerplate code from one place to another. On top of that, they are a great way to ship best practices.

So, how do we write our schematics now? Unfortunately, it is not yet as easy as you might think. You can create a blank schematics project like this:

```shell
npm install -g @angular-devkit/schematics-cli
schematics blank hello-world
```

The `schematics-cli` creates a pre-configured project for you with a ready-to-use `ng generate` schematic. Everything from that point on needs to be done manually and leaves a lot of open questions. 

- How do I integrate my schematic into my Angular library project?
- How can I generate additional schematics?
- What about `ng add`, `ng update`? 

A lot of those questions get answered here:
- https://angular.io/guide/schematics-for-libraries
- https://angular.io/guide/cli-builder
- https://tomastrajan.medium.com/total-guide-to-custom-angular-schematics-5c50cf90cdb4

While this is a good thing, I still wondered why I had to do so many things manually. Shouldn't it be as easy as `ng generate component`? This question has motivated me to work on `ngx-cli-toolkit`.

## ngx-cli-toolkit

`ngx-cli-toolkit` is a collection of schematics that configure and create schematics for your project. 

{% github kroeder/ngx-cli-toolkit no-readme %}

## Example

Let's dive into some examples.

### Create a new project

For the following examples, I will jump into the role of a library author who usually not only needs `ng generate` schematics but `ng add` and `ng update` schematics as well.

We start by creating a new Angular library project.

```shell
ng new test-application --create-application false
cd test-application
ng generate library ui
```

### Add `ngx-cli-toolkit`

`ngx-cli-toolkit` provides an `ng add` schematic.

```shell
ng add ngx-cli-toolkit
```

At this point, we only installed the necessary dependencies.

### Initialize schematics project

To initialize schematics for a project, you need to run the following `generate` schematic in the library directory. The schematic searches for a package.json and will pick the next available one relative to your current path.

This means we have to first navigate to our library project and execute the schematic there.

```shell
cd projects/ui
ng generate ngx-cli-toolkit:init
```

> You can also perform this at any place that provides a `package.json` file and is an Angular project. Support for other environments is planned. 

The `init` schematic adds a `schematics` and an `ng-update` field to your `package.json`.

```json 
{
  "name": "ui",
  ...
  "schematics": "./schematics/collection.json",
  "ng-update": {
    "migrations": "./schematics/migrations.json",
    "packageGroup": []
  }
}
```

The `schematics` field locates the `collection.json` that manages `ng generate` and `ng add` schematics.

The second field, `ng-update`, locates the `migrations.json` file that manages `ng update` schematics.

Both are important for the Angular CLI to perform `ng generate ${name-of-your-lib}:${name-of-your-schematic}` or `ng update ${name-of-your-lib}`.

Additionally to the added `package.json` fields, the schematic generates a `migrations.json` and `collection.json` for you as well.

### Generating schematics

All `ng generate` schematics search for a `package.json` file to locate the `collection.json` or `migrations.json` file. It is essential to perform these schematics in the right spot.

All following examples assume you perform the example commands in `projects/ui/schematics`.

```shell
cd projects/ui/schematics
```

#### Create `ng add` schematic

Let's generate an `ng add` schematic.

```shell
ng generate ngx-cli-toolkit:add-schematic

CREATE projects/ui/schematics/ng-add/index.spec.ts (579 bytes)
CREATE projects/ui/schematics/ng-add/index.ts (162 bytes)
UPDATE projects/ui/schematics/collection.json (245 bytes)
```

All generators create a schematic and a test file. 

> I highly recommend writing your schematics using Test-Driven-Development (TDD) because it is the fastest way to make sure your schematic works as soon as you get used to the testing process of schematics. You can browse through the ngx-cli-toolkit repository to get a few examples of how to test them.

Your `collection.json` now should look like this:

```json
{
  "$schema": "../../../node_modules/@angular-devkit/schematics/collection-schema.json",
  "schematics": {
    "ng-add": {
      "save": "dependencies",
      "description": "Bootstrap package",
      "factory": "ng-add/index#ngAdd"
    }
  }
}
```

> You can read more about this here: https://angular.io/guide/schematics-for-libraries#providing-installation-support

#### Create `ng generate` schematic

Similar to the `ng add` generator, you can create an `ng generate` schematic by executing the command:

```shell
ng generate ngx-cli-toolkit:generate-schematic name-of-your-schematic

CREATE projects/ui/schematics/name-of-your-schematic/index.spec.ts (612 bytes)
CREATE projects/ui/schematics/name-of-your-schematic/index.ts (268 bytes)
CREATE projects/ui/schematics/name-of-your-schematic/schema.json (308 bytes)
UPDATE projects/ui/schematics/collection.json (450 bytes)
```

The `schema.json` file manages the input arguments of your schematic. 

> Read more about this here: https://angular.io/guide/schematics-authoring#defining-input-options-with-a-schema-and-interfaces

#### Create `ng update` schematic

Last but not least, you can create `ng update` schematics by executing:

```shell
$ ng generate ngx-cli-toolkit:update-schematic name-of-your-schematic
CREATE projects/ui/schematics/update-schematic/index.spec.ts (600 bytes)
CREATE projects/ui/schematics/update-schematic/index.ts (301 bytes)
UPDATE projects/ui/schematics/migrations.json (305 bytes)
```

The schematic asks for a version and stores it in your `migration.json`.

```json
{
  "$schema": "../../../node_modules/@angular-devkit/schematics/collection-schema.json",
  "schematics": {
    "name-of-your-schematic": {
      "description": "New update schematic",
      "factory": "name-of-your-schematic/index#updateSchematic",
      "schema": "name-of-your-schematic/schema.json",
      "version": "1.2.3"
    }
  }
}
```

As soon as someone runs `ng update` on your package and installs `>= v1.2.3`, this update schematic gets executed. You can also use versions like `1.2.3-alpha`, `1.2.3-rc`, .etc.

## Conclusion

You can do great things with schematics, but learning how to write schematics is not easy. It can take many hours until you finally get to the point where you can actually start solving your problem and stop configuring things beforehand. 

`ngx-cli-toolkit` tries to reduce exactly that so you can jump right into the fun part of schematics.