---
title: Composing Generators
description: Learn how to combine and reuse Nx generators to build complex workflows from simpler building blocks, including using Nx Devkit generators and jscodeshift codemods.
filter: 'type:Guides'
---

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.

```typescript
import { libraryGenerator } from '@nx/js';

export default async function (tree: Tree, schema: any) {
  await libraryGenerator(
    tree, // virtual file system tree
    { name: schema.name } // options for the generator
  );
}
```

## Using jscodeshift codemods

Codemods created for use with [`jscodeshift`](https://github.com/facebook/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.

```typescript
import { Tree, visitNotIgnoredFiles } from '@nx/devkit';
import { applyTransform } from 'jscodeshift/src/testUtils';
import arrowFunctionsTransform from './arrow-functions';

// The schema path can be an individual file or a directory
export default async function (tree: Tree, schema: { path: string }): any {
  visitNotIgnoredFiles(tree, schema.path, (filePath) => {
    const input = tree.read(filePath).toString();
    const transformOptions = {};
    const output = applyTransform(
      { default: arrowFunctionsTransform, parser: 'ts' },
      transformOptions,
      { source: input, path: filePath }
    );
    tree.write(filePath, output);
  });
}
```
