Angular Schematics from 0 to publishing your own library (II)

Post Editor

In this second post, we will explore some of the most useful methods of the Schematics API. It definitely offers a lot of functions and utilities, to transform our Angular workspace.

4 min read
post

Angular Schematics from 0 to publishing your own library (II)

In this second post, we will explore some of the most useful methods of the Schematics API. It definitely offers a lot of functions and utilities, to transform our Angular workspace.

post
post
4 min read

In this second post, we will explore some of the most useful methods of the Schematics API. It definitely offers a lot of functions and utilities, to transform our Angular workspace.

Methods to read the file system
Link to this section

These methods are executed on the base, and allows you to traverse it and get useful meta data and other information about the current state.

getDir()
Link to this section

This method allows you to get information about the contents of a specific folder in your base.

<>Copy
// ...node_modules/@angular-devkit/schematics/src/tree/interface.d.ts const hasEntries = tree.getDir(normalize(`${staticPath}${_options.path}`))

get()
Link to this section

This method allows you to get a single file in the source.

visit()
Link to this section

This method is useful to traverse the workspace from a path and below. We can then get concrete information about each file visited.

<>Copy
tree.getDir('/').visit(filePath => { if (filePath.includes('node_modules')) { return; } )}

read()
Link to this section

Read is meant to be used to read and extract information of a single file resource. It returns a Buffer.

<>Copy
const tsConfigBuffer = tree.read(filePath); if (!tsConfigBuffer) { return; }

apply()
Link to this section

This method allows you to apply multiple rules to a source, and it returns the transformed tree.

url()
Link to this section

This method allows you accessing the base existing in the file system, that wants to be replicated, relative to the root of the schematic that implements it

applyTemplate() | template()
Link to this section

These methods take a rule or several, as arguments, and the path to the files to replicate (also accessed via another method, the url())

If you want to implement string utilities to your templates, you'll do it via these methods.

move()
Link to this section

This method allows you to move a file or tree to a new location

noop()
Link to this section

This method allows you to explicitly describe no operations for certain conditions met.

<>Copy
const source = apply(url('./files'), [ template({ ...strings, ..._options, }), move(path) ]);

String Utilities
Link to this section

String utilities are helpful to normalize definitions and to enforce conventions. For example, when we work in large teams, (or even when we work on our own! ) we want standards to be followed and patterns to be enforced to

  • name artifacts
  • name variables
  • follow styleguide best practices, etc

These utility methods are available in the templates directly, without having to export anything else, additionally. Although we do have to import them to Schematics entry point or rule factory

When describing structures, we can even chain unlimited methods an unlimited amount of times. We only need to follow this syntax

__name@dasherize__

Where __ (two underscores) act as delimiter by default and @ indicates the concatenation of methods.

dasherize()
Link to this section

This method takes a string value and returns the same value with dashes and lowercase. (kebab-case)

For example, should we pass `InDepthDev`, it would return `in-depth-dev`

classify()
Link to this section

This method takes a string value and returns the same value with the first character in uppercase, and the rest in lowercase. (PascalCase)

For example, should we pass `in depth dev`, it would return `InDepthDev`

camelize()
Link to this section

This method takes a string value and returns the same value with the first character in lowercase, the first successive characters in uppercase, and the rest in lowercase. (camelCase)

For example, should we pass `in depth dev`, it would return `inDepthDev`

decamelize()
Link to this section

This method takes a string value and returns the same value replacing all spaces or caps as delimiters, with dashes

For example, should we pass `inDepthDev`, it would return `in-depth-dev`

undescore()
Link to this section

This method takes a string value and returns the same value replacing all spaces or caps as delimiters, with underscores

For example, should we pass `in Depth Dev`, it would return `in_depth_dev`

Chaining or combining schematics
Link to this section

The following methods exists in order to allow the combination and extension of independent schematics.

schematic()
Link to this section

This method allows you to pass a schematic collection, a schematic alias or entry rule name, as it appears in the collection, and the options, that are part of the same collection, to be chained with the current schematic

externalSchematic()
Link to this section

This method allows you to pass a schematic collection, a schematic alias or entry rule name, as it appears in the collection, and the options, that are part of an external collection, to be chained with the current schematic

chain()
Link to this section

This method allows you to combine multiple schematics rules, to obtain a single concatenated rule, and be able to synchronously execute several operations with different concerns

Merging strategies
Link to this section

This methods are meant to decouple the source into branches in the staging area, where transformations can be applied.

branchAndMerge()
Link to this section

This method allows you to branch out from the source, apply transformations and then merge back to it.

mergeWith()
Link to this section

This method allows you to merge trees, after transformations are applied, and usually back to the physical source

Template syntax
Link to this section

Schematics allows us to implement template syntax in a very flexible way, for example:

<>Copy
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Injectable({ providedIn: 'root' }) export class <%= classify(name) %>Service { constructor(private http: HttpClient) { } }

This code is part of the implementation of the service schematic, externalSchematic of the CLI. In this way, the service gets the name passed to the schematic as option

Another very interesting use of the template syntax is directly in templates, which allows you to access string utilities but also to any other custom function defined in the schematic, as seen in the example

<>Copy
const source = apply(url('./files'), [ forEach((file: FileEntry) => { let dir = dirname(file.path); let pathName = basename(dir); _options.folderName = pathName; _context.logger.info(`Estamos leyendo en árbol virtual -> ${pathName}`); return file; }), template({ ...strings, ..._options, addProjectInfo }), move(path) ]); function addProjectInfo(): string { return `This is the readme file for project: ${projectName}. You can find more info about Angular on [this link](https://www.angular.io)` }

Logging
Link to this section

A very important aspect at the time of developing developer oriented tools, and at the time of executing CLI commands as a user, is the ability of obtaining real time information about the executing process.

The schematics context allows us to access the LoggerApi, an implementation you can see here `/node_modules/@angular-devkit/core/src/logger/logger.d.ts`

Exceptions
Link to this section

A very best practice is to have a good errors and exceptions catching strategy. Schematics offers use the SchematicsExceptionsutility that implements BaseExceptionfrom Angular core. You can explore it here /node_modules/@angular-devkit/core/src/exception/exception.d.ts

Up to now we explored the API only in theory! Meet me in the next post to explore the schematics the Angular CLI comes equipped with, to generate artifacts, add and install libraries, and update dependencies.

We will also write our first schematics together!

Share

About the author

author_image

Natalia works in the role of Frontend Architect/Principal Software Engineer for enterprise-scale web software platforms. She is also a Google Developer Expert for web technologies and Angular.

author_image

About the author

Natalia Venditto

Natalia works in the role of Frontend Architect/Principal Software Engineer for enterprise-scale web software platforms. She is also a Google Developer Expert for web technologies and Angular.

About the author

author_image

Natalia works in the role of Frontend Architect/Principal Software Engineer for enterprise-scale web software platforms. She is also a Google Developer Expert for web technologies and Angular.

Looking for a JS job?
Default logo
Looking for Angular Developer

Great Software Laboratory Private Limited

India
Remote
Job logo
AngularJS Developer

VariQ Corporation

United States
Remote
Job logo
Senior Full Stack Angular Developer

Plus One Health Management

Remote
More jobs
NxAngularCli
NxAngularCli
NxAngularCli

Featured articles

Angularpost
8 June 202118 min read
Techniques to style component host element in Angular

Styling the host element is a crucial ability. Understanding that can completely change the way you develop reusable components, making their code clear and easier to maintain. This article will concentrate on techniques that use CSS styles and reduce Typescript logic.