CLI compatibility layer for older Nx workspaces that serves as a bridge to core nx functionality
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Comprehensive workspace discovery, project configuration parsing, and workspace utilities. Provides the core functionality for reading, parsing, and managing Nx workspace configurations and project structures.
Main class for workspace management operations including configuration reading and project discovery.
/**
* Main workspace management class
*/
export class Workspaces {
/**
* Create a new Workspaces instance
* @param root - Root directory of the workspace
*/
constructor(root: string);
/**
* Get relative path from workspace root to current working directory
* @param cwd - Current working directory
* @returns Relative path or null if outside workspace
*/
relativeCwd(cwd: string): string | null;
/**
* Calculate default project name based on current directory
* @param cwd - Current working directory
* @param projects - Projects configuration
* @param nxJson - Nx configuration
* @returns Default project name
*/
calculateDefaultProjectName(cwd: string, projects: ProjectsConfigurations, nxJson: NxJsonConfiguration): string;
/**
* Read all project configurations from the workspace
* @param opts - Options for reading configurations
* @returns Complete projects configuration
*/
readProjectsConfigurations(opts?: {
_ignorePluginInference?: boolean;
_includeProjectsFromAngularJson?: boolean;
}): ProjectsConfigurations;
/**
* @deprecated Use readProjectsConfigurations instead
* Read workspace configuration (projects + nx.json combined)
*/
readWorkspaceConfiguration(opts?: any): ProjectsConfigurations & NxJsonConfiguration;
/**
* Check if an executor is an Nx executor
* @param nodeModule - Node module name
* @param executor - Executor name
* @returns True if it's an Nx executor
*/
isNxExecutor(nodeModule: string, executor: string): boolean;
/**
* Check if a generator is an Nx generator
* @param collectionName - Collection name
* @param generatorName - Generator name
* @returns True if it's an Nx generator
*/
isNxGenerator(collectionName: string, generatorName: string): boolean;
/**
* Read executor configuration
* @param nodeModule - Node module name
* @param executor - Executor name
* @returns Executor configuration with compatibility info
*/
readExecutor(nodeModule: string, executor: string): ExecutorConfig & { isNgCompat: boolean };
/**
* Read generator information
* @param collectionName - Collection name
* @param generatorName - Generator name
* @returns Generator information
*/
readGenerator(collectionName: string, generatorName: string): GeneratorInfo;
/**
* Check if workspace has nx.json file
* @returns True if nx.json exists
*/
hasNxJson(): boolean;
/**
* Read nx.json configuration
* @returns Nx configuration object
*/
readNxJson(): NxJsonConfiguration;
}Functions for finding and organizing project files within the workspace.
/**
* Convert file path to project name
* @param fileName - File path to convert
* @returns Project name derived from path
*/
export function toProjectName(fileName: string): string;
/**
* @deprecated Use getGlobPatternsFromPluginsAsync instead
* Get glob patterns from configured plugins
* @param nxJson - Nx configuration
* @param paths - Paths to search
* @param root - Workspace root
* @returns Array of glob patterns
*/
export function getGlobPatternsFromPlugins(
nxJson: NxJsonConfiguration,
paths: string[],
root?: string
): string[];
/**
* Get glob patterns from configured plugins (async version)
* @param nxJson - Nx configuration
* @param paths - Paths to search
* @param root - Workspace root
* @returns Promise resolving to array of glob patterns
*/
export function getGlobPatternsFromPluginsAsync(
nxJson: NxJsonConfiguration,
paths: string[],
root?: string
): Promise<string[]>;
/**
* Get glob patterns from package manager workspace configurations
* @param root - Workspace root directory
* @returns Array of glob patterns from package.json workspaces
*/
export function getGlobPatternsFromPackageManagerWorkspaces(root: string): string[];
/**
* Find project files using glob patterns
* @param root - Workspace root
* @param pluginsGlobPatterns - Glob patterns from plugins
* @param nxJson - Nx configuration (optional)
* @returns Array of project file paths
*/
export function globForProjectFiles(
root: string,
pluginsGlobPatterns: string[],
nxJson?: NxJsonConfiguration
): string[];
/**
* Remove duplicate project files from array
* @param files - Array of file paths
* @returns Array with duplicates removed
*/
export function deduplicateProjectFiles(files: string[]): string[];Functions for processing and merging project configurations.
/**
* Infer project configuration from non-standard project files
* @param file - File path to analyze
* @returns Project configuration with name
*/
export function inferProjectFromNonStandardFile(file: string): ProjectConfiguration & { name: string };
/**
* Build project configurations from glob results
* @param nxJson - Nx configuration
* @param projectFiles - Array of project files
* @param readProjectConfiguration - Function to read project config
* @param root - Workspace root
* @returns Complete projects configuration
*/
export function buildProjectsConfigurationsFromGlobs(
nxJson: NxJsonConfiguration,
projectFiles: string[],
readProjectConfiguration: (path: string) => ProjectConfiguration & { name: string },
root: string
): ProjectsConfigurations;
/**
* Merge target configurations with defaults
* @param project - Project configuration
* @param targetName - Name of the target
* @param target - Target configuration
* @param projectDefaults - Project-level defaults
* @param executor - Executor name
* @returns Merged target configuration
*/
export function mergeTargetConfigurations(
project: ProjectConfiguration,
targetName: string,
target: TargetConfiguration,
projectDefaults: TargetDefaults | undefined,
executor: string
): TargetConfiguration;
/**
* Read target defaults for a specific target
* @param targetName - Name of the target
* @param targetDefaults - Target defaults configuration
* @param executor - Executor name
* @returns Target defaults for the specified target
*/
export function readTargetDefaultsForTarget(
targetName: string,
targetDefaults: TargetDefaults | undefined,
executor: string
): TargetDefaults[string];General utility functions for workspace operations.
/**
* Rename object property while preserving key order
* @param obj - Object to modify
* @param from - Current property name
* @param to - New property name
*/
export function renamePropertyWithStableKeys(obj: any, from: string, to: string): void;import { Workspaces } from "@nrwl/tao/shared/workspace";
import { workspaceRoot } from "@nrwl/tao/utils/app-root";
// Create workspace instance
const workspaces = new Workspaces(workspaceRoot);
// Check if this is an Nx workspace
if (workspaces.hasNxJson()) {
console.log('This is an Nx workspace');
// Read configurations
const nxConfig = workspaces.readNxJson();
const projects = workspaces.readProjectsConfigurations();
console.log(`Workspace scope: ${nxConfig.npmScope}`);
console.log(`Found ${Object.keys(projects.projects).length} projects`);
// List all projects
Object.entries(projects.projects).forEach(([name, config]) => {
console.log(` ${name} (${config.projectType || 'unknown'}) - ${config.root}`);
});
} else {
console.log('Not an Nx workspace');
}import {
Workspaces,
globForProjectFiles,
getGlobPatternsFromPackageManagerWorkspaces,
toProjectName
} from "@nrwl/tao/shared/workspace";
import { workspaceRoot } from "@nrwl/tao/utils/app-root";
const workspaces = new Workspaces(workspaceRoot);
const nxJson = workspaces.readNxJson();
// Get glob patterns from different sources
const pmPatterns = getGlobPatternsFromPackageManagerWorkspaces(workspaceRoot);
console.log('Package manager patterns:', pmPatterns);
// Find all project files
const projectFiles = globForProjectFiles(workspaceRoot, pmPatterns, nxJson);
console.log(`Found ${projectFiles.length} project files`);
// Convert file paths to project names
const projectNames = projectFiles.map(toProjectName);
console.log('Inferred project names:', projectNames);import { Workspaces } from "@nrwl/tao/shared/workspace";
import { workspaceRoot } from "@nrwl/tao/utils/app-root";
const workspaces = new Workspaces(workspaceRoot);
// Check executor types
const isBuildExecutorNx = workspaces.isNxExecutor('@nx/webpack', 'webpack');
const isLintExecutorNx = workspaces.isNxExecutor('@angular-eslint/builder', 'lint');
console.log(`@nx/webpack:webpack is Nx executor: ${isBuildExecutorNx}`);
console.log(`@angular-eslint/builder:lint is Nx executor: ${isLintExecutorNx}`);
// Read executor configuration
if (isBuildExecutorNx) {
const executorConfig = workspaces.readExecutor('@nx/webpack', 'webpack');
console.log('Webpack executor config:', executorConfig);
}
// Check generators
const isNxGenerator = workspaces.isNxGenerator('@nx/react', 'component');
console.log(`@nx/react:component is Nx generator: ${isNxGenerator}`);
if (isNxGenerator) {
const generatorInfo = workspaces.readGenerator('@nx/react', 'component');
console.log('React component generator info:', generatorInfo);
}import { Workspaces } from "@nrwl/tao/shared/workspace";
import { workspaceRoot } from "@nrwl/tao/utils/app-root";
const workspaces = new Workspaces(workspaceRoot);
const nxJson = workspaces.readNxJson();
const projects = workspaces.readProjectsConfigurations();
// Calculate default project based on current directory
const cwd = process.cwd();
const defaultProject = workspaces.calculateDefaultProjectName(cwd, projects, nxJson);
console.log(`Current directory: ${cwd}`);
console.log(`Relative to workspace: ${workspaces.relativeCwd(cwd)}`);
console.log(`Default project: ${defaultProject}`);
// This is useful for CLI commands that need to infer which project to operate on
if (defaultProject) {
console.log(`Operating on project: ${defaultProject}`);
} else {
console.log('No default project could be determined');
}import {
mergeTargetConfigurations,
readTargetDefaultsForTarget,
type TargetConfiguration,
type TargetDefaults
} from "@nrwl/tao/shared/workspace";
// Example target defaults
const targetDefaults: TargetDefaults = {
build: {
cache: true,
inputs: ['production', '^production']
},
test: {
cache: true,
inputs: ['default', '^production', { externalDependencies: ['jest'] }]
}
};
// Project-specific target configuration
const projectConfig = {
name: 'my-app',
root: 'apps/my-app',
targets: {
build: {
executor: '@nx/webpack:webpack',
options: {
outputPath: 'dist/apps/my-app'
}
}
}
};
// Get defaults for build target
const buildDefaults = readTargetDefaultsForTarget('build', targetDefaults, '@nx/webpack:webpack');
console.log('Build target defaults:', buildDefaults);
// Merge project target with defaults
const mergedBuildTarget = mergeTargetConfigurations(
projectConfig,
'build',
projectConfig.targets.build,
targetDefaults,
'@nx/webpack:webpack'
);
console.log('Merged build target:', mergedBuildTarget);import {
buildProjectsConfigurationsFromGlobs,
inferProjectFromNonStandardFile,
deduplicateProjectFiles
} from "@nrwl/tao/shared/workspace";
import { workspaceRoot } from "@nrwl/tao/utils/app-root";
// Custom project file discovery
const customProjectFiles = [
'apps/web/project.json',
'libs/shared/package.json',
'tools/custom-project.config.js'
];
// Remove duplicates
const uniqueFiles = deduplicateProjectFiles(customProjectFiles);
// Infer project configurations from non-standard files
const inferredProjects = uniqueFiles.map(file => {
try {
return inferProjectFromNonStandardFile(file);
} catch (error) {
console.warn(`Could not infer project from ${file}:`, error.message);
return null;
}
}).filter(Boolean);
console.log('Inferred projects:', inferredProjects);
// Build complete configuration (this is a simplified example)
// In real usage, you'd provide a proper readProjectConfiguration function
function readProjectConfiguration(path: string) {
// This would read and parse the actual project file
return inferProjectFromNonStandardFile(path);
}
const projectsConfig = buildProjectsConfigurationsFromGlobs(
{ npmScope: 'myorg' }, // minimal nx.json
uniqueFiles,
readProjectConfiguration,
workspaceRoot
);
console.log('Built projects configuration:', projectsConfig);Workspace management integrates closely with other @nrwl/tao APIs:
import { Workspaces } from "@nrwl/tao/shared/workspace";
import { detectPackageManager } from "@nrwl/tao/shared/package-manager";
import { logger } from "@nrwl/tao/shared/logger";
import { workspaceRoot } from "@nrwl/tao/utils/app-root";
function setupWorkspace() {
const workspaces = new Workspaces(workspaceRoot);
if (!workspaces.hasNxJson()) {
logger.error('This is not an Nx workspace');
return;
}
const nxJson = workspaces.readNxJson();
const projects = workspaces.readProjectsConfigurations();
// Ensure package manager is configured
const detectedPm = detectPackageManager(workspaceRoot);
if (!nxJson.cli?.packageManager) {
nxJson.cli = { ...nxJson.cli, packageManager: detectedPm };
logger.info(`Configured package manager: ${detectedPm}`);
}
// Log workspace information
logger.info(`Workspace: ${nxJson.npmScope || 'unnamed'}`);
logger.info(`Projects: ${Object.keys(projects.projects).length}`);
logger.info(`Package manager: ${nxJson.cli?.packageManager || detectedPm}`);
return { nxJson, projects, packageManager: detectedPm };
}Install with Tessl CLI
npx tessl i tessl/npm-nrwl--tao