CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-nrwl--tao

CLI compatibility layer for older Nx workspaces that serves as a bridge to core nx functionality

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

project-graph.mddocs/

Project Graph

Types and interfaces for analyzing project dependencies and workspace structure. Provides comprehensive type definitions for working with project graphs, dependency relationships, and file metadata within Nx workspaces.

Capabilities

Project Graph Interface

Main interface representing the complete project dependency graph.

/**
 * Main project graph interface representing workspace structure and dependencies
 */
export interface ProjectGraph {
  /** Map of project names to project nodes */
  nodes: Record<string, ProjectGraphProjectNode>;
  /** Map of external dependency names to external nodes (e.g., npm packages) */
  externalNodes?: Record<string, ProjectGraphExternalNode>;
  /** Map of project names to their dependency arrays */
  dependencies: Record<string, ProjectGraphDependency[]>;
  /** All workspace files with metadata */
  allWorkspaceFiles?: FileData[];
  /** Version of the project graph format */
  version?: string;
}

Project Node Types

Type definitions for different types of nodes in the project graph.

/**
 * Workspace project node representing internal projects
 */
export interface ProjectGraphProjectNode {
  /** Type of project */
  type: 'app' | 'e2e' | 'lib';
  /** Project name */
  name: string;
  /** Project configuration and metadata */
  data: ProjectConfiguration & { 
    files: FileData[]; 
    description?: string; 
  };
}

/**
 * External dependency node representing npm packages and other external dependencies
 */
export interface ProjectGraphExternalNode {
  /** Type of external dependency */
  type: 'npm';
  /** External node name with prefix */
  name: `npm:${string}`;
  /** External dependency metadata */
  data: { 
    version: string; 
    packageName: string; 
    hash?: string; 
  };
}

Dependency Relationships

Types for representing dependency relationships between projects.

/**
 * Dependency relationship between projects or external dependencies
 */
export interface ProjectGraphDependency {
  /** Type of dependency relationship */
  type: DependencyType | string;
  /** Target project or dependency name */
  target: string;
  /** Source project name */
  source: string;
}

/**
 * Types of dependency relationships
 */
export enum DependencyType {
  /** Static imports and explicit dependencies */
  static = 'static',
  /** Dynamic imports and runtime dependencies */
  dynamic = 'dynamic',
  /** Implicit dependencies configured in nx.json */
  implicit = 'implicit'
}

File Metadata

Types for representing file information and dependencies.

/**
 * File metadata with hash and dependency information
 */
export interface FileData {
  /** File path relative to workspace root */
  file: string;
  /** Content hash of the file */
  hash: string;
  /** @deprecated Use dependencies instead */
  deps?: string[];
  /** Dependencies discovered in this file */
  dependencies?: ProjectGraphDependency[];
}

/** Map of project names to their file arrays */
export type ProjectFileMap = Record<string, FileData[]>;

Graph Processing

Types for extending and processing project graphs.

/**
 * Context provided to project graph processors
 */
export interface ProjectGraphProcessorContext {
  /** Current workspace root path */
  workspaceRoot: string;
  /** Projects configuration */
  projectsConfigurations: ProjectsConfigurations;
  /** Nx configuration */
  nxJsonConfiguration: NxJsonConfiguration;
  /** Files mapped by project */
  fileMap: ProjectFileMap;
  /** Files mapped by project (updated by processors) */
  filesToProcess: ProjectFileMap;
}

/**
 * Function type for processing and extending project graphs
 */
export type ProjectGraphProcessor = (
  graph: ProjectGraph,
  context: ProjectGraphProcessorContext
) => ProjectGraph;

Usage Examples

Analyzing Project Dependencies

import type { ProjectGraph, ProjectGraphDependency, DependencyType } from "@nrwl/tao/shared/project-graph";

function analyzeProjectDependencies(graph: ProjectGraph, projectName: string) {
  const dependencies = graph.dependencies[projectName] || [];
  
  // Group dependencies by type
  const staticDeps = dependencies.filter(dep => dep.type === DependencyType.static);
  const dynamicDeps = dependencies.filter(dep => dep.type === DependencyType.dynamic);
  const implicitDeps = dependencies.filter(dep => dep.type === DependencyType.implicit);
  
  console.log(`${projectName} dependencies:`);
  console.log(`  Static: ${staticDeps.length}`);
  console.log(`  Dynamic: ${dynamicDeps.length}`);
  console.log(`  Implicit: ${implicitDeps.length}`);
  
  return {
    static: staticDeps,
    dynamic: dynamicDeps,
    implicit: implicitDeps
  };
}

Working with Project Nodes

import type { ProjectGraph, ProjectGraphProjectNode } from "@nrwl/tao/shared/project-graph";

function getProjectsByType(graph: ProjectGraph): Record<string, ProjectGraphProjectNode[]> {
  const projects = Object.values(graph.nodes);
  
  return {
    apps: projects.filter(p => p.type === 'app'),
    libs: projects.filter(p => p.type === 'lib'),
    e2e: projects.filter(p => p.type === 'e2e')
  };
}

function getProjectFileCount(graph: ProjectGraph, projectName: string): number {
  const project = graph.nodes[projectName];
  return project?.data.files?.length || 0;
}

Analyzing External Dependencies

import type { ProjectGraph, ProjectGraphExternalNode } from "@nrwl/tao/shared/project-graph";

function analyzeExternalDependencies(graph: ProjectGraph) {
  const externalNodes = graph.externalNodes || {};
  
  const npmPackages = Object.values(externalNodes)
    .filter((node): node is ProjectGraphExternalNode => node.type === 'npm')
    .map(node => ({
      name: node.data.packageName,
      version: node.data.version
    }));
  
  console.log(`External dependencies: ${npmPackages.length}`);
  npmPackages.forEach(pkg => {
    console.log(`  ${pkg.name}@${pkg.version}`);
  });
  
  return npmPackages;
}

Finding Dependency Chains

import type { ProjectGraph, ProjectGraphDependency } from "@nrwl/tao/shared/project-graph";

function findDependencyChain(graph: ProjectGraph, from: string, to: string): string[] | null {
  const visited = new Set<string>();
  const path: string[] = [];
  
  function dfs(current: string): boolean {
    if (current === to) {
      path.push(current);
      return true;
    }
    
    if (visited.has(current)) {
      return false;
    }
    
    visited.add(current);
    path.push(current);
    
    const dependencies = graph.dependencies[current] || [];
    for (const dep of dependencies) {
      if (dfs(dep.target)) {
        return true;
      }
    }
    
    path.pop();
    return false;
  }
  
  return dfs(from) ? path : null;
}

Working with File Data

import type { FileData, ProjectFileMap } from "@nrwl/tao/shared/project-graph";

function getChangedFiles(fileMap: ProjectFileMap, previousHashes: Record<string, string>): FileData[] {
  const changedFiles: FileData[] = [];
  
  Object.values(fileMap).forEach(projectFiles => {
    projectFiles.forEach(file => {
      const previousHash = previousHashes[file.file];
      if (!previousHash || previousHash !== file.hash) {
        changedFiles.push(file);
      }
    });
  });
  
  return changedFiles;
}

function getFilesWithDependencies(fileMap: ProjectFileMap): FileData[] {
  return Object.values(fileMap)
    .flat()
    .filter(file => file.dependencies && file.dependencies.length > 0);
}

Integration with Workspace APIs

The project graph types integrate with other @nrwl/tao workspace management APIs:

import type { ProjectGraph } from "@nrwl/tao/shared/project-graph";
import { Workspaces } from "@nrwl/tao/shared/workspace";
import { logger } from "@nrwl/tao/shared/logger";

function analyzeWorkspaceStructure(root: string, graph: ProjectGraph) {
  const workspaces = new Workspaces(root);
  const projects = workspaces.readProjectsConfigurations();
  
  // Compare project graph with workspace configuration
  const configuredProjects = Object.keys(projects.projects);
  const graphProjects = Object.keys(graph.nodes);
  
  const missingFromGraph = configuredProjects.filter(p => !graphProjects.includes(p));
  const missingFromConfig = graphProjects.filter(p => !configuredProjects.includes(p));
  
  if (missingFromGraph.length > 0) {
    logger.warn(`Projects missing from graph: ${missingFromGraph.join(', ')}`);
  }
  
  if (missingFromConfig.length > 0) {
    logger.warn(`Projects missing from config: ${missingFromConfig.join(', ')}`);
  }
}

Install with Tessl CLI

npx tessl i tessl/npm-nrwl--tao

docs

angular-cli-adapter.md

configuration.md

index.md

logging.md

package-manager.md

project-graph.md

tree-api.md

workspace-management.md

workspace-root.md

tile.json