CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-nx--devkit

The Nx Devkit provides utilities for creating custom generators, executors, and plugins to extend the Nx build system for different technologies and use cases.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

generators.mddocs/

Code Generation

Powerful code generation utilities for creating files from templates, formatting code, and managing project scaffolding with EJS templating support.

Capabilities

File Generation from Templates

Generate files and directories from template folders with variable substitution and conditional logic.

/**
 * Generates a folder of files based on provided templates
 * Performs template substitutions using EJS and filename replacements
 * @param tree - File system tree
 * @param srcFolder - Source template folder (absolute path)
 * @param target - Target directory relative to workspace root
 * @param substitutions - Variables for template substitution
 * @param options - Generation options including overwrite strategy
 */
function generateFiles(
  tree: Tree,
  srcFolder: string,
  target: string,
  substitutions: { [k: string]: any },
  options?: GenerateFilesOptions
): void;

interface GenerateFilesOptions {
  /** Strategy for handling existing files */
  overwriteStrategy?: OverwriteStrategy;
}

enum OverwriteStrategy {
  /** Replace existing files */
  Overwrite = "overwrite",
  /** Keep existing files unchanged */
  KeepExisting = "keepExisting", 
  /** Throw error if file exists */
  ThrowIfExisting = "throwIfExisting"
}

Usage Examples:

import { Tree, generateFiles, OverwriteStrategy } from "@nx/devkit";
import * as path from "path";

export default function myGenerator(tree: Tree, options: { name: string; description?: string }) {
  // Generate files from templates with substitutions
  generateFiles(
    tree,
    path.join(__dirname, "files"), // Template source folder
    `libs/${options.name}`,        // Target directory
    {
      ...options,
      tmpl: "", // Remove __tmpl__ suffix from filenames
      className: options.name.charAt(0).toUpperCase() + options.name.slice(1),
    },
    {
      overwriteStrategy: OverwriteStrategy.ThrowIfExisting
    }
  );
}

// Template structure example:
// files/
//   src/
//     index.ts__tmpl__
//     lib/
//       __name__.ts__tmpl__
//   README.md__tmpl__
//   package.json__tmpl__

// Template file content example (index.ts__tmpl__):
/*
export * from './lib/<%= name %>';

// Generated with className: <%= className %>
// Description: <%= description || 'No description provided' %>
*/

Code Formatting

Format generated code using Prettier and other formatting tools.

/**
 * Formats all created or updated files using Prettier
 * Only formats if Prettier is detected in the workspace
 * @param tree - File system tree
 * @param options - Formatting options
 */
function formatFiles(
  tree: Tree,
  options?: {
    sortRootTsconfigPaths?: boolean;
  }
): Promise<void>;

Usage Examples:

import { Tree, generateFiles, formatFiles } from "@nx/devkit";

export default async function myGenerator(tree: Tree, options: any) {
  // Generate files
  generateFiles(tree, templatePath, targetPath, substitutions);
  
  // Format all generated files
  await formatFiles(tree, {
    sortRootTsconfigPaths: true // Sort paths in tsconfig.json
  });
}

TypeScript to JavaScript Conversion

Convert TypeScript files to JavaScript and update configurations accordingly.

/**
 * Rename and transpile TypeScript files to JavaScript
 * @param tree - File system tree
 * @param options - Conversion options
 */
function toJS(tree: Tree, options?: ToJSOptions): void;

/**
 * Update TypeScript configurations to allow JavaScript files
 * @param tree - File system tree
 * @param options - Configuration options
 */
function updateTsConfigsToJs(
  tree: Tree, 
  options: { projectRoot: string }
): void;

interface ToJSOptions {
  /** Convert all files in the tree */
  all?: boolean;
  /** Specific files to convert */
  files?: string[];
}

Usage Examples:

import { Tree, toJS, updateTsConfigsToJs } from "@nx/devkit";

export default function convertToJs(tree: Tree, options: { projectRoot: string }) {
  // Convert TypeScript files to JavaScript
  toJS(tree);
  
  // Update tsconfig files to allow JS
  updateTsConfigsToJs(tree, {
    projectRoot: options.projectRoot
  });
}

Task Management

Manage and sequence generator callbacks for post-generation tasks.

/**
 * Run multiple generator callbacks in sequence
 * @param tasks - Array of callback functions to execute
 * @returns Combined callback that runs all tasks in order
 */
function runTasksInSerial(...tasks: GeneratorCallback[]): GeneratorCallback;

/**
 * Callback function type returned by generators
 * Used for post-generation tasks like installing packages
 */
type GeneratorCallback = () => void | Promise<void>;

Usage Examples:

import { 
  Tree, 
  GeneratorCallback,
  runTasksInSerial,
  addDependenciesToPackageJson,
  installPackagesTask
} from "@nx/devkit";

export default function myGenerator(tree: Tree, options: any): GeneratorCallback {
  // Generate files...
  
  // Create multiple tasks
  const addDepsTask = addDependenciesToPackageJson(
    tree,
    { react: "^18.0.0" },
    { "@types/react": "^18.0.0" }
  );
  
  const installTask = () => installPackagesTask(tree);
  
  const customTask = () => {
    console.log("Running custom post-generation task");
  };
  
  // Return combined task that runs in sequence
  return runTasksInSerial(addDepsTask, installTask, customTask);
}

File Processing Utilities

Utilities for processing files and handling ignored files.

/**
 * Visit all files that are not ignored by git
 * @param tree - File system tree
 * @param dirPath - Directory to visit (defaults to root)
 * @param visitor - Function called for each non-ignored file
 */
function visitNotIgnoredFiles(
  tree: Tree,
  dirPath?: string,
  visitor: (path: string) => void
): void;

Usage Examples:

import { Tree, visitNotIgnoredFiles } from "@nx/devkit";

export default function processFiles(tree: Tree) {
  // Process all non-ignored TypeScript files
  visitNotIgnoredFiles(tree, "src", (filePath) => {
    if (filePath.endsWith(".ts") && !filePath.endsWith(".spec.ts")) {
      const content = tree.read(filePath, "utf-8");
      // Process the file content
      const processedContent = content.replace(/old-pattern/g, "new-pattern");
      tree.write(filePath, processedContent);
    }
  });
}

Generator Types

Core Generator Interface

/**
 * Generator function signature
 * Can return void, a callback, or a promise of either
 */
type Generator<T = any> = (
  tree: Tree,
  schema: T
) => void | GeneratorCallback | Promise<void | GeneratorCallback>;

/**
 * Migration function signature for updating existing code
 */
type Migration<T = any> = (
  tree: Tree,
  schema: T
) => void | GeneratorCallback | Promise<void | GeneratorCallback>;

/**
 * Schema definition for generators.json
 */
interface GeneratorsJson {
  generators?: Record<string, GeneratorDescription>;
  schematics?: Record<string, GeneratorDescription>; // Legacy support
}

interface GeneratorDescription {
  /** Path to the generator implementation */
  implementation?: string;
  /** Path to the schema JSON file */
  schema?: string;
  /** Aliases for the generator */
  aliases?: string[];
  /** Whether generator is hidden from help */
  hidden?: boolean;
  /** Description of the generator */
  description?: string;
}

Template Substitution

The generateFiles function supports EJS templating with these features:

Filename Substitution:

  • __name__ → replaced with substitutions.name
  • __className__ → replaced with substitutions.className
  • __tmpl__ → removed (use tmpl: "" in substitutions)

Content Substitution:

  • <%= variable %> → outputs variable value
  • <%- variable %> → outputs unescaped variable value
  • <% if (condition) { %>...content...<% } %> → conditional content
  • <% for (item of items) { %>...content...<% } %> → loops

Advanced Usage Examples:

// Template file: __name__.service.ts__tmpl__
/*
<% if (type === 'api') { %>
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class <%= className %>Service {
  constructor(private http: HttpClient) {}
  
  <% for (method of methods) { %>
  <%= method.name %>(<%- method.params %>): <%= method.returnType %> {
    return this.http.<%= method.httpMethod %>('/<%= name %>/<%= method.endpoint %>');
  }
  
  <% } %>
}
<% } else { %>
export class <%= className %>Service {
  // Simple service implementation
}
<% } %>
*/

// Generator usage:
generateFiles(tree, templatePath, targetPath, {
  name: 'user',
  className: 'User',
  type: 'api',
  methods: [
    { 
      name: 'getUsers', 
      params: '', 
      returnType: 'Observable<User[]>',
      httpMethod: 'get',
      endpoint: 'list'
    },
    {
      name: 'createUser',
      params: 'user: User',
      returnType: 'Observable<User>',
      httpMethod: 'post', 
      endpoint: 'create'
    }
  ],
  tmpl: ''
});

Framework Integration

Converting Nx generators for use with other frameworks:

/**
 * Convert an Nx Generator to Angular Devkit Schematic
 * @param generator - Nx generator function
 * @param skipWritingConfigInOldFormat - Skip legacy format
 * @returns Angular DevKit schematic
 */
function convertNxGenerator<T = any>(
  generator: Generator<T>,
  skipWritingConfigInOldFormat?: boolean
): any;

Usage Examples:

import { convertNxGenerator } from "@nx/devkit";

// Convert Nx generator to Angular schematic
const schematic = convertNxGenerator(myNxGenerator);

// Use in Angular CLI collection
export default schematic;

Install with Tessl CLI

npx tessl i tessl/npm-nx--devkit

docs

executors.md

generators.md

index.md

package-management.md

plugin-development.md

project-graph.md

tree-operations.md

utilities.md

workspace-configuration.md

tile.json