Composing Generators

Generators are useful individually, but reusing and composing generators allows you to build whole workflows out of simpler building blocks.

Using Nx Devkit Generators

Nx Devkit generators can be imported and invoked like any javascript function. They often return a Promise, so they can be used with the await keyword to mimic synchronous code. Because this is standard javascript, control flow logic can be adjusted with if blocks and for loops as usual.

1import { libraryGenerator } from '@nrwl/workspace/generators';
2
3export default async function (tree: Tree, schema: any) {
4  await libraryGenerator(
5    tree, // virtual file system tree
6    { name: schema.name } // options for the generator
7  );
8}

Using jscodeshift Codemods

Codemods created for use with jscodeshift can be used within Nx Devkit generators using the visitNotIgnoredFiles helper function. This way you can compose codemods with other generators while retaining --dry-run and Nx Console compatibilities.

1import { Tree, visitNotIgnoredFiles } from '@nrwl/devkit';
2import { applyTransform } from 'jscodeshift/src/testUtils';
3import arrowFunctionsTransform from './arrow-functions';
4
5// The schema path can be an individual file or a directory
6export default async function (tree: Tree, schema: { path: string }): any {
7  visitNotIgnoredFiles(tree, schema.path, (filePath) => {
8    const input = tree.read(filePath).toString();
9    const transformOptions = {};
10    const output = applyTransform(
11      { default: arrowFunctionsTransform, parser: 'ts' },
12      transformOptions,
13      { source: input, path: filePath }
14    );
15    tree.write(filePath, output);
16  });
17}