CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-nrwl--devkit

Legacy wrapper providing comprehensive Nx devkit utilities for creating plugins, generators, and executors

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

plugins.mddocs/

Plugin Development

Comprehensive plugin system for extending Nx with custom node creation, dependency analysis, and metadata generation. Plugins allow you to integrate new tools and technologies into Nx workspaces by defining how they should be discovered, configured, and executed.

Capabilities

Plugin Interfaces

Core interfaces for creating Nx plugins.

/**
 * Modern Nx plugin interface (recommended)
 */
interface NxPluginV2 {
  /** Plugin name */
  name: string;
  /** Function to create project nodes from configuration files */
  createNodes?: CreateNodesV2;
  /** Function to create dependencies between projects */
  createDependencies?: CreateDependencies;
  /** Function to create metadata for projects */
  createMetadata?: CreateMetadata;
}

/**
 * Union type of all supported plugin versions
 */
type NxPlugin = NxPluginV1 | NxPluginV2;

/**
 * Legacy plugin interface (deprecated)
 */
interface NxPluginV1 {
  name: string;
  processProjectGraph?(
    graph: ProjectGraph,
    context: ProjectGraphProcessorContext
  ): ProjectGraph;
  projectFilePatterns?: string[];
}

Usage Examples:

import { NxPluginV2 } from "@nrwl/devkit";

const myPlugin: NxPluginV2 = {
  name: 'my-custom-plugin',
  createNodes: [
    '**/my-config.json',
    (configFiles, options, context) => {
      // Create project nodes from configuration files
      const results = {};
      for (const configFile of configFiles) {
        // Process each config file and create project nodes
      }
      return Promise.resolve(results);
    }
  ],
  createDependencies: (options, context) => {
    // Analyze files and create project dependencies
    return [];
  }
};

export default myPlugin;

CreateNodes API

Interface for creating project nodes from configuration files.

/**
 * Modern create nodes API (recommended)
 */
type CreateNodesV2<T = any> = [
  /** Glob pattern for configuration files */
  projectFilePattern: string,
  /** Function to process matched files */
  createNodesFunction: CreateNodesFunctionV2<T>
];

/**
 * Function to create nodes from multiple configuration files
 */
type CreateNodesFunctionV2<T = any> = (
  /** Array of matched configuration file paths */
  projectConfigurationFiles: string[],
  /** Plugin options */
  options: T | undefined,
  /** Creation context */
  context: CreateNodesContextV2
) => Promise<CreateNodesResultV2>;

/**
 * Context provided to create nodes functions
 */
interface CreateNodesContextV2 {
  /** Workspace root directory */
  workspaceRoot: string;
  /** Nx JSON configuration */
  nxJsonConfiguration: NxJsonConfiguration;
  /** Configuration cache for performance */
  configFiles?: Record<string, any>;
}

/**
 * Result of creating nodes from configuration files
 */
interface CreateNodesResultV2 {
  /** Created project configurations */
  projects?: Record<string, ProjectConfiguration>;
  /** Created external nodes */
  externalNodes?: Record<string, ProjectGraphExternalNode>;
}

/**
 * Legacy create nodes API (deprecated)
 */
type CreateNodes<T = any> = [
  projectFilePattern: string,
  createNodesFunction: CreateNodesFunction<T>
];

type CreateNodesFunction<T = any> = (
  projectConfigurationFile: string,
  options: T | undefined,
  context: CreateNodesContext
) => CreateNodesResult | Promise<CreateNodesResult>;

Usage Examples:

import { 
  CreateNodesV2, 
  CreateNodesFunctionV2,
  ProjectConfiguration 
} from "@nrwl/devkit";

// Example: Plugin that creates projects from package.json files
const createNodesFunction: CreateNodesFunctionV2 = async (
  configFiles,
  options,
  context
) => {
  const projects: Record<string, ProjectConfiguration> = {};
  
  for (const configFile of configFiles) {
    const packageJsonPath = configFile;
    const packageJson = JSON.parse(
      readFileSync(join(context.workspaceRoot, packageJsonPath), 'utf-8')
    );
    
    const projectRoot = dirname(packageJsonPath);
    const projectName = packageJson.name || basename(projectRoot);
    
    projects[projectRoot] = {
      name: projectName,
      root: projectRoot,
      projectType: packageJson.private ? 'library' : 'application',
      targets: {
        build: {
          executor: 'nx:run-commands',
          options: {
            command: 'npm run build',
            cwd: projectRoot
          }
        }
      }
    };
  }
  
  return { projects };
};

export const createNodes: CreateNodesV2 = [
  '**/package.json',
  createNodesFunction
];

CreateDependencies API

Interface for analyzing files and creating project dependencies.

/**
 * Function to create dependencies between projects
 */
type CreateDependencies<T = any> = (
  /** Plugin options */
  options: T | undefined,
  /** Dependency creation context */
  context: CreateDependenciesContext
) => RawProjectGraphDependency[] | Promise<RawProjectGraphDependency[]>;

/**
 * Context provided to dependency creation functions
 */
interface CreateDependenciesContext {
  /** Current project graph */
  projects: Record<string, ProjectConfiguration>;
  /** External nodes in the graph */
  externalNodes: Record<string, ProjectGraphExternalNode>;
  /** File map for the workspace */
  fileMap: ProjectFileMap;
  /** Files that have changed */
  filesToProcess: FileData[];
  /** Workspace root directory */
  workspaceRoot: string;
  /** Nx JSON configuration */
  nxJsonConfiguration: NxJsonConfiguration;
}

/**
 * Raw dependency representation
 */
interface RawProjectGraphDependency {
  /** Source project name */
  source: string;
  /** Target project name */
  target: string;
  /** Type of dependency */
  type: DependencyType;
  /** Source file where dependency was found */
  sourceFile?: string;
}

Usage Examples:

import { 
  CreateDependencies, 
  RawProjectGraphDependency,
  DependencyType 
} from "@nrwl/devkit";

// Example: Plugin that finds import dependencies in TypeScript files
const createDependencies: CreateDependencies = (options, context) => {
  const dependencies: RawProjectGraphDependency[] = [];
  
  for (const [projectName, files] of Object.entries(context.fileMap)) {
    for (const file of files) {
      if (file.file.endsWith('.ts') || file.file.endsWith('.tsx')) {
        const content = readFileSync(
          join(context.workspaceRoot, file.file), 
          'utf-8'
        );
        
        // Simple regex to find imports (use proper parser in real implementation)
        const importMatches = content.match(/from ['"]([^'"]+)['"]/g) || [];
        
        for (const match of importMatches) {
          const importPath = match.match(/from ['"]([^'"]+)['"]/)?.[1];
          if (importPath?.startsWith('@myorg/')) {
            const targetProject = importPath.replace('@myorg/', '');
            if (context.projects[targetProject]) {
              dependencies.push({
                source: projectName,
                target: targetProject,
                type: DependencyType.static,
                sourceFile: file.file
              });
            }
          }
        }
      }
    }
  }
  
  return dependencies;
};

CreateMetadata API

Interface for generating metadata for projects in the graph.

/**
 * Function to create metadata for projects
 */
type CreateMetadata<T = any> = (
  /** Plugin options */
  options: T | undefined,
  /** Metadata creation context */
  context: CreateMetadataContext
) => Promise<ProjectsMetadata>;

/**
 * Context provided to metadata creation functions
 */
interface CreateMetadataContext {
  /** Current project graph */
  projectGraph: ProjectGraph;
  /** Nx JSON configuration */
  nxJsonConfiguration: NxJsonConfiguration;
  /** Workspace root directory */
  workspaceRoot: string;
}

/**
 * Map of project metadata
 */
type ProjectsMetadata = Record<string, Record<string, any>>;

Usage Examples:

import { CreateMetadata, ProjectsMetadata } from "@nrwl/devkit";

// Example: Plugin that adds build metadata to projects
const createMetadata: CreateMetadata = async (options, context) => {
  const metadata: ProjectsMetadata = {};
  
  for (const [projectName, node] of Object.entries(context.projectGraph.nodes)) {
    if (node.type !== 'npm') {
      const projectRoot = node.data.root;
      const packageJsonPath = join(context.workspaceRoot, projectRoot, 'package.json');
      
      if (existsSync(packageJsonPath)) {
        const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
        
        metadata[projectName] = {
          packageVersion: packageJson.version,
          hasTests: !!packageJson.scripts?.test,
          dependencies: Object.keys(packageJson.dependencies || {}),
          devDependencies: Object.keys(packageJson.devDependencies || {})
        };
      }
    }
  }
  
  return metadata;
};

Plugin Utilities

Utility functions for working with plugins.

/**
 * Create nodes from a list of configuration files
 * @param configFiles - Array of configuration file paths
 * @param createNodes - Create nodes configuration
 * @param options - Plugin options
 * @param context - Creation context
 * @returns Promise resolving to created nodes
 */
function createNodesFromFiles<T = any>(
  configFiles: string[],
  createNodes: CreateNodesV2<T>,
  options: T,
  context: CreateNodesContextV2
): Promise<CreateNodesResultV2>;

/**
 * Error aggregation for plugin operations
 */
class AggregateCreateNodesError extends Error {
  constructor(
    public readonly errors: Array<[file: string, error: Error]>,
    public readonly partialResults: CreateNodesResultV2
  ) {
    super('Multiple errors occurred while creating nodes');
  }
}

Usage Examples:

import { 
  createNodesFromFiles,
  AggregateCreateNodesError 
} from "@nrwl/devkit";

async function processConfigFiles(
  configFiles: string[],
  createNodes: CreateNodesV2,
  options: any,
  context: CreateNodesContextV2
) {
  try {
    const result = await createNodesFromFiles(
      configFiles,
      createNodes,
      options,
      context
    );
    
    return result;
  } catch (error) {
    if (error instanceof AggregateCreateNodesError) {
      console.error('Errors occurred:', error.errors);
      // Use partial results if available
      return error.partialResults;
    }
    throw error;
  }
}

Plugin Configuration

Types for configuring plugins in nx.json.

/**
 * Plugin configuration in nx.json
 */
interface PluginConfiguration {
  /** Plugin package name or path */
  plugin: string;
  /** Plugin-specific options */
  options?: any;
  /** Exclude patterns */
  exclude?: string[];
  /** Include patterns */
  include?: string[];
}

/**
 * Expanded plugin configuration with resolved information
 */
interface ExpandedPluginConfiguration extends PluginConfiguration {
  /** Resolved plugin name */
  name: string;
  /** Whether plugin creates nodes */
  createNodes?: [string, CreateNodesFunctionV2];
  /** Whether plugin creates dependencies */
  createDependencies?: CreateDependencies;
  /** Whether plugin creates metadata */
  createMetadata?: CreateMetadata;
}

Usage Examples:

// nx.json plugin configuration
{
  "plugins": [
    {
      "plugin": "@my-org/nx-plugin",
      "options": {
        "buildCommand": "npm run build"
      },
      "exclude": ["**/node_modules/**"]
    }
  ]
}

Install with Tessl CLI

npx tessl i tessl/npm-nrwl--devkit

docs

executors.md

generators.md

index.md

json-utilities.md

package-management.md

plugins.md

project-configuration.md

project-graph.md

string-path-utilities.md

testing-utilities.md

tree-filesystem.md

tile.json