Then we can create our new custom collection with schematics @schematics/schematics:schematic --name collection-name .

I agree, this looks like a pretty funky command 🤷😂

Let’s shed a bit of light onto what’s going on there… The command schematics accepts parameter @schematics/schematics:schematics which consists of two parts, the name of the collection (npm package) @schematics/schematics and the name of the executed schematics which is funnily called schematics in our case. Second parameter --name is used to provide name of our new collection.

Running this command will create a new folder with a project skeleton for developing of our new collection with some dummy schematics examples and useful build and test scripts.

Simplest way to create a new custom schematics

Schematics are pretty powerful and can do many advanced things besides generating new files. In official terms schematics apply rules to the tree representing all existing project files and staging area which is a list of changes that will be applied to these files.

This might sound like a lot of things to learn before being able to leverage schematics in our project. Luckily there is a simpler way…

We can just copy and adjust default Angular schematics to get useful results right now and learn more advanced APIs later when needed

In previous step we have generated skeleton of a new collection project which contains couple of example schematics to help us get started. The first thing we have to do is to have a look in collection.json file which contains definition of all implemented schematics and make some adjustments…

Remove all schematics generated by default and replace them with our new custom service schematics

Then we can copy content of the original Angular service schematics located in node_modules/@schematics/angular/service into our src/my-custom-service .

Relative imports in index.ts will become broken so we have to replace them with absolute ones by replacing ../ with @schematics/angular/ . Typescript compiler should stop complaining and it should be possible to successfully run tests using npm t .

Lets look into the content of files directory. It contains some funny looking directories and files with names like __name@dasherize__.service.ts which are used to enable schematics templating capabilities.

In our example __name__ represents a token which will be replaced by the service name provided in ng generate my-custom-service service-name command and dasherize is one of the provided helper functions which outputs standardized file names converting camelCase into dash-separated file names.

Similarly, the file itself contains template of a service file which will be generated by Angular CLI…

Basic Angular service template ( note that it contains templating part delimited by <%= and %> )

Let’s say that in our project we have a convention that our business services never contain data fetching logic, which is in turn handled by dedicated resource services. In that case we end up with a lot of services which look like this…

Example of service we want to generate using our custom service schematics

Such service can be generated using template like this…

Adjusted content of __name@dasherize__.service.ts file

Note how we used two different helper function classify and dasherize to transform passed service name to appropriate forms for the usage (class name vs file import path).

There, we just created our first useful custom schematic!

Copying default Angular service schematic has another advantage because it supports all original parameters and flags out of the box. As with template, we can just simply extend list of supported flags to implement new desired functionality.

Let’s say we want to introduce flag --interface to indicate if we want our service to contain interface stub for a corresponding entity. When the flag is passed (variable is set to true ) we want our service to look like this…

“Some” will be replaced by passed service name, more realistic example could be UserService with user property which is of type User…

To achieve that we have to add new interface property in schema.json and schema.d.ts files…

schema.json

schema.d.ts

More scaleable approach is to generate schema.d.ts file with help of an utility library but in our case hand editing seems to be straight forward and simple enough

Good, we are now able to use --interface flag without any complaints from Angular CLI but generated service ends up the same in both cases. In the last step we have to adjust service template to make use of our new flag…

Note use of three different helper functions — classify, dasherize and a new one called camelize — to transform name into contextually appropriate form. Also note conditional blocks containing if and the name of evaluated flag…

As we can see, templating supports evaluation of conditional statements with <%= if(variableName) %> content <%= } %> and nested statements. These capabilities are pretty powerful and enable us to create arbitrary complex templates.

Cool! Our schematic is generating an useful service. Now is the time to use it in a real project…

How to test schematics with real Angular CLI projects

Once we created our custom collection we should write corresponding unit tests to make sure everything works as expected.

The next logical step is to try our collection in practice. This can be performed on any local Angular CLI project. First, we have to run npm build to compile Typescript sources of our collection and then run npm link to make it available for linking by other local projects.

Then we can navigate to our target project and run npm link our-collection-name . After successful linking we can execute ng g schematics-name -c our-collection-name to see if it generates files with expected content in expected path.

Follow me on Twitter to get notified about the newest blog posts and interesting frontend stuff

How to publish custom schematics collection to npm

Custom collection project generated by provided schematics isn’t publishing friendly per se.

It contains build npm script which just compiles Typescript sources in place. Combine that with default .gitignore file which excludes compiled Javascript files and we get nice “module not found” error when we install and try to use collection which was published just with npm publish without any tweaking.

The simplest way to make this work is to remove the rule that ignores generated .js file from .gitignore so that they are published together with Typescript sources.

Be aware that there are more elegant solutions with compiling Typescript sources into a dist folder and publishing just that but hey, this is just a development tool and it works great so that’s good enough!

How to use new custom schematics collection in other projects

This one is straight forward, we just install newly published collection as we would do for any other npm package with npm i -D our-collection-name .

Then we can run ng generate schematics-name --collection our-collection-name . This can be shortened to ng g schematics-name -c our-collection-name which is much easier to type.

Remember that one collection can and probably will contain more than one useful schematic…

Example of a custom schematics collection

One of the reasons I got very interested in Angular Schematics is that I wrote a small state management library for Angular called ngx-model.

Creating new model services involves a bit of repetitive boilerplate because we always have to inject ModelFactory and instantiate Model instance. Additionally, it’s also very helpful to provide a type for our Model in multiple places to get nice code completion and type checking support.

All this can be handled by editor (IDE) templates but not everyone uses the same editor and it would be a nontrivial task to distribute all these templates for every popular editor.

Schematics fit into this scenario much better because they leverage package manager which is used by every frontend developer who we are interested in. A simple npm i -D @angular-extensions/schematics and ng g model my-model -c @angular-extensions/schematics are enough to get the ball rolling.

Ideas on what to generate with our schematics

The ngx-model schematics generate both service and corresponding test files. They contain necessary boilerplate and an extra example method with a corresponding test.

Only thing the developers need to do is to add their own methods following the provided example.

Schematics which generate boilerplate and examples of use have a huge potential to shorten learning curve for new developers joining any existing project

Generating examples of use can also be a great way to spread know-how about the project specific conventions and best practices. Always up to date in a controlled semantically versioned way. This sounds like a pretty awesome solution if you ask me 😉

That’s all for now!

As you might have noticed I am a huge fan of developer productivity and therefore schematics. I see a huge potential in their use and hope that you can use these tips to enhance developer experience in your projects too!

Please, help spread these tips to a wider audience with your 👏 👏 👏 and promote @angular-extensions/schematics with GitHub ⭐⭐⭐ if you’re a ngx-model user, don’t forget to build your own schematics & have fun!

Also, feel free to check some other interesting Angular posts…