Legacy wrapper providing comprehensive Nx devkit utilities for creating plugins, generators, and executors
npx @tessl/cli install tessl/npm-nrwl--devkit@19.8.0The @nrwl/devkit package provides a comprehensive toolkit for creating Nx plugins, generators, and executors. This is a legacy package that re-exports the complete API from @nx/devkit, offering utilities for file manipulation, project configuration, workspace management, and plugin development in Nx monorepos.
@nrwl/devkit serves as the foundational library for extending Nx workspaces with custom functionality. It enables developers to create sophisticated tooling through its comprehensive API surface covering virtual file systems, project management, dependency analysis, and code generation.
Key Features:
npm install @nrwl/devkitimport { Tree, readProjectConfiguration, logger } from "@nrwl/devkit";For CommonJS:
const { Tree, readProjectConfiguration, logger } = require("@nrwl/devkit");For testing utilities:
import { createTreeWithEmptyWorkspace } from "@nrwl/devkit/testing";import {
Tree,
formatFiles,
generateFiles,
addProjectConfiguration,
logger
} from "@nrwl/devkit";
// Example generator function
export default async function myGenerator(tree: Tree, options: any) {
// Generate files from templates
generateFiles(tree, path.join(__dirname, "files"), ".", {
...options,
template: ""
});
// Add a new project
addProjectConfiguration(tree, options.name, {
root: `libs/${options.name}`,
projectType: "library",
targets: {
build: {
executor: "@nx/js:tsc",
options: {
outputPath: `dist/libs/${options.name}`
}
}
}
});
// Format generated files
await formatFiles(tree);
}The @nrwl/devkit is built around several key architectural components:
Tree interface provides a virtual filesystem for reading, writing, and manipulating files during code generationCore virtual file system for reading, writing, and manipulating files during code generation and workspace modifications.
interface Tree {
read(filePath: string): Buffer | null;
read(filePath: string, encoding: BufferEncoding): string | null;
write(filePath: string, content: Buffer | string): void;
exists(filePath: string): boolean;
delete(filePath: string): void;
rename(from: string, to: string): void;
children(dirPath: string): string[];
listChanges(): FileChange[];
changePermissions(filePath: string, mode: Mode): void;
}
interface FileChange {
path: string;
type: 'CREATE' | 'UPDATE' | 'DELETE';
content?: Buffer;
}Tools for creating code generators that scaffold projects, components, and features with template-based file generation.
function formatFiles(tree: Tree): Promise<void>;
function generateFiles(
tree: Tree,
srcFolder: string,
target: string,
substitutions: Record<string, any>
): void;
type Generator<T = any> = (
tree: Tree,
schema: T
) => void | GeneratorCallback | Promise<void | GeneratorCallback>;
type GeneratorCallback = () => void | Promise<void>;APIs for managing workspace projects, reading and updating project configurations, and handling workspace-level settings.
function addProjectConfiguration(
tree: Tree,
projectName: string,
projectConfiguration: ProjectConfiguration
): void;
function readProjectConfiguration(tree: Tree, projectName: string): ProjectConfiguration;
function updateProjectConfiguration(
tree: Tree,
projectName: string,
projectConfiguration: ProjectConfiguration
): void;
interface ProjectConfiguration {
name?: string;
root: string;
sourceRoot?: string;
projectType?: ProjectType;
targets?: Record<string, TargetConfiguration>;
tags?: string[];
implicitDependencies?: string[];
}Framework for building custom executors that run build, test, lint, and other development tasks.
function runExecutor<T = any>(
targetDescription: Target,
options: T,
context: ExecutorContext
): Promise<AsyncIterableIterator<{ success: boolean; [key: string]: any }>>;
type Executor<T = any> = (
options: T,
context: ExecutorContext
) => Promise<{ success: boolean; [key: string]: any }> | AsyncIterableIterator<{ success: boolean; [key: string]: any }>;
interface ExecutorContext {
root: string;
cwd: string;
workspace: WorkspaceJsonConfiguration;
isVerbose: boolean;
projectName?: string;
targetName?: string;
configurationName?: string;
}Tools for analyzing and manipulating the dependency graph between workspace projects and external packages.
function createProjectGraphAsync(opts?: {
exitOnError?: boolean;
}): Promise<ProjectGraph>;
function readCachedProjectGraph(): ProjectGraph;
interface ProjectGraph {
nodes: Record<string, ProjectGraphProjectNode | ProjectGraphExternalNode>;
dependencies: Record<string, ProjectGraphDependency[]>;
}
interface ProjectGraphProjectNode {
name: string;
type: 'app' | 'lib' | 'e2e';
data: ProjectConfiguration;
}Comprehensive plugin system for extending Nx with custom node creation, dependency analysis, and metadata generation.
interface NxPluginV2 {
name: string;
createNodes?: CreateNodesV2;
createDependencies?: CreateDependencies;
createMetadata?: CreateMetadata;
}
type CreateNodesV2<T = any> = [
projectFilePattern: string,
createNodesFunction: CreateNodesFunctionV2<T>
];
type CreateNodesFunctionV2<T = any> = (
projectConfigurationFiles: string[],
options: T | undefined,
context: CreateNodesContextV2
) => Promise<CreateNodesResultV2>;Comprehensive JSON handling utilities for both virtual tree operations and filesystem I/O.
function readJson<T = any>(tree: Tree, path: string): T;
function writeJson<T = any>(tree: Tree, path: string, value: T): void;
function updateJson<T = any, U = T>(
tree: Tree,
path: string,
updater: (json: T) => U
): void;
function parseJson<T = any>(input: string, options?: JsonParseOptions): T;
function serializeJson<T = any>(input: T, options?: JsonSerializeOptions): string;Tools for detecting package managers, managing dependencies, and handling package.json operations.
type PackageManager = 'npm' | 'yarn' | 'pnpm' | 'bun';
function detectPackageManager(dir?: string): PackageManager;
function addDependenciesToPackageJson(
tree: Tree,
dependencies: Record<string, string>,
devDependencies: Record<string, string>,
packageJsonPath?: string
): GeneratorCallback;
function ensurePackage<T = any>(packageName: string, version: string): T;Utility functions for string manipulation, path operations, and code transformations.
function names(name: string): {
name: string;
className: string;
propertyName: string;
constantName: string;
fileName: string;
};
function joinPathFragments(...fragments: string[]): string;
function normalizePath(osSpecificPath: string): string;
function offsetFromRoot(dir: string): string;
function stripIndents(strings: TemplateStringsArray, ...values: any[]): string;Testing helpers for creating virtual workspaces and file systems for generator and executor testing.
function createTree(): Tree;
function createTreeWithEmptyWorkspace(): Tree;type ProjectType = 'application' | 'library';
type BufferEncoding = "ascii" | "utf8" | "utf-8" | "utf16le" | "ucs2" | "ucs-2" | "base64" | "base64url" | "latin1" | "binary" | "hex";
type Mode = string | number;
interface Target {
project: string;
target: string;
configuration?: string;
}
interface TargetConfiguration<T = any> {
executor: string;
options?: T;
configurations?: Record<string, Partial<T>>;
defaultConfiguration?: string;
dependsOn?: TargetDependencyConfig[];
inputs?: (InputDefinition | string)[];
outputs?: string[];
cache?: boolean;
metadata?: Record<string, any>;
}
interface TargetDependencyConfig {
projects?: string[] | string;
dependencies?: boolean;
target: string;
params?: 'ignore' | 'forward';
}
type InputDefinition =
| { input: string; projects: string | string[] }
| { input: string; dependencies: true }
| { input: string }
| { fileset: string }
| { runtime: string }
| { externalDependencies: string[] }
| { dependentTasksOutputFiles: string; transitive?: boolean }
| { env: string };
interface NxJsonConfiguration {
extends?: string;
npmScope?: string;
affected?: NxAffectedConfig;
implicitDependencies?: Record<string, string[] | '*'>;
targetDefaults?: TargetDefaults;
cli?: {
defaultCollection?: string;
packageManager?: PackageManager;
};
generators?: Record<string, any>;
tasksRunnerOptions?: Record<string, any>;
namedInputs?: Record<string, (InputDefinition | string)[]>;
plugins?: PluginConfiguration[];
parallel?: number;
cacheDirectory?: string;
defaultBase?: string;
nxCloudAccessToken?: string;
nxCloudEncryptionKey?: string;
nxCloudUrl?: string;
useDaemonProcess?: boolean;
}
interface NxAffectedConfig {
defaultBase?: string;
}
type TargetDefaults = Record<string, Partial<TargetConfiguration>>;
type PluginConfiguration = string | ExpandedPluginConfiguration;
interface ExpandedPluginConfiguration<T = unknown> {
plugin: string;
options?: T;
include?: string[];
exclude?: string[];
}
type WorkspaceJsonConfiguration = ProjectsConfigurations;
interface ProjectsConfigurations {
version: number;
projects: {
[projectName: string]: ProjectConfiguration;
};
}interface ProjectGraphDependency {
type: DependencyType | string;
target: string;
source: string;
}
enum DependencyType {
static = 'static',
dynamic = 'dynamic',
implicit = 'implicit',
}
interface ProjectGraphExternalNode {
type: 'npm';
name: `npm:${string}`;
data: {
version: string;
packageName: string;
hash?: string;
};
}interface CreateNodesContextV2 {
readonly nxJsonConfiguration: NxJsonConfiguration;
readonly workspaceRoot: string;
}
type CreateNodesResultV2 = Array<
readonly [configFileSource: string, result: CreateNodesResult]
>;
interface CreateNodesResult {
projects?: Record<string, Optional<ProjectConfiguration, 'root'>>;
externalNodes?: Record<string, ProjectGraphExternalNode>;
}
type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;interface JsonParseOptions {
expectComments?: boolean;
disallowComments?: boolean;
allowTrailingComma?: boolean;
}
interface JsonSerializeOptions {
spaces?: number;
}