0
# Project Graph
1
2
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.
3
4
## Capabilities
5
6
### Project Graph Interface
7
8
Main interface representing the complete project dependency graph.
9
10
```typescript { .api }
11
/**
12
* Main project graph interface representing workspace structure and dependencies
13
*/
14
export interface ProjectGraph {
15
/** Map of project names to project nodes */
16
nodes: Record<string, ProjectGraphProjectNode>;
17
/** Map of external dependency names to external nodes (e.g., npm packages) */
18
externalNodes?: Record<string, ProjectGraphExternalNode>;
19
/** Map of project names to their dependency arrays */
20
dependencies: Record<string, ProjectGraphDependency[]>;
21
/** All workspace files with metadata */
22
allWorkspaceFiles?: FileData[];
23
/** Version of the project graph format */
24
version?: string;
25
}
26
```
27
28
### Project Node Types
29
30
Type definitions for different types of nodes in the project graph.
31
32
```typescript { .api }
33
/**
34
* Workspace project node representing internal projects
35
*/
36
export interface ProjectGraphProjectNode {
37
/** Type of project */
38
type: 'app' | 'e2e' | 'lib';
39
/** Project name */
40
name: string;
41
/** Project configuration and metadata */
42
data: ProjectConfiguration & {
43
files: FileData[];
44
description?: string;
45
};
46
}
47
48
/**
49
* External dependency node representing npm packages and other external dependencies
50
*/
51
export interface ProjectGraphExternalNode {
52
/** Type of external dependency */
53
type: 'npm';
54
/** External node name with prefix */
55
name: `npm:${string}`;
56
/** External dependency metadata */
57
data: {
58
version: string;
59
packageName: string;
60
hash?: string;
61
};
62
}
63
```
64
65
### Dependency Relationships
66
67
Types for representing dependency relationships between projects.
68
69
```typescript { .api }
70
/**
71
* Dependency relationship between projects or external dependencies
72
*/
73
export interface ProjectGraphDependency {
74
/** Type of dependency relationship */
75
type: DependencyType | string;
76
/** Target project or dependency name */
77
target: string;
78
/** Source project name */
79
source: string;
80
}
81
82
/**
83
* Types of dependency relationships
84
*/
85
export enum DependencyType {
86
/** Static imports and explicit dependencies */
87
static = 'static',
88
/** Dynamic imports and runtime dependencies */
89
dynamic = 'dynamic',
90
/** Implicit dependencies configured in nx.json */
91
implicit = 'implicit'
92
}
93
```
94
95
### File Metadata
96
97
Types for representing file information and dependencies.
98
99
```typescript { .api }
100
/**
101
* File metadata with hash and dependency information
102
*/
103
export interface FileData {
104
/** File path relative to workspace root */
105
file: string;
106
/** Content hash of the file */
107
hash: string;
108
/** @deprecated Use dependencies instead */
109
deps?: string[];
110
/** Dependencies discovered in this file */
111
dependencies?: ProjectGraphDependency[];
112
}
113
114
/** Map of project names to their file arrays */
115
export type ProjectFileMap = Record<string, FileData[]>;
116
```
117
118
### Graph Processing
119
120
Types for extending and processing project graphs.
121
122
```typescript { .api }
123
/**
124
* Context provided to project graph processors
125
*/
126
export interface ProjectGraphProcessorContext {
127
/** Current workspace root path */
128
workspaceRoot: string;
129
/** Projects configuration */
130
projectsConfigurations: ProjectsConfigurations;
131
/** Nx configuration */
132
nxJsonConfiguration: NxJsonConfiguration;
133
/** Files mapped by project */
134
fileMap: ProjectFileMap;
135
/** Files mapped by project (updated by processors) */
136
filesToProcess: ProjectFileMap;
137
}
138
139
/**
140
* Function type for processing and extending project graphs
141
*/
142
export type ProjectGraphProcessor = (
143
graph: ProjectGraph,
144
context: ProjectGraphProcessorContext
145
) => ProjectGraph;
146
```
147
148
## Usage Examples
149
150
### Analyzing Project Dependencies
151
152
```typescript
153
import type { ProjectGraph, ProjectGraphDependency, DependencyType } from "@nrwl/tao/shared/project-graph";
154
155
function analyzeProjectDependencies(graph: ProjectGraph, projectName: string) {
156
const dependencies = graph.dependencies[projectName] || [];
157
158
// Group dependencies by type
159
const staticDeps = dependencies.filter(dep => dep.type === DependencyType.static);
160
const dynamicDeps = dependencies.filter(dep => dep.type === DependencyType.dynamic);
161
const implicitDeps = dependencies.filter(dep => dep.type === DependencyType.implicit);
162
163
console.log(`${projectName} dependencies:`);
164
console.log(` Static: ${staticDeps.length}`);
165
console.log(` Dynamic: ${dynamicDeps.length}`);
166
console.log(` Implicit: ${implicitDeps.length}`);
167
168
return {
169
static: staticDeps,
170
dynamic: dynamicDeps,
171
implicit: implicitDeps
172
};
173
}
174
```
175
176
### Working with Project Nodes
177
178
```typescript
179
import type { ProjectGraph, ProjectGraphProjectNode } from "@nrwl/tao/shared/project-graph";
180
181
function getProjectsByType(graph: ProjectGraph): Record<string, ProjectGraphProjectNode[]> {
182
const projects = Object.values(graph.nodes);
183
184
return {
185
apps: projects.filter(p => p.type === 'app'),
186
libs: projects.filter(p => p.type === 'lib'),
187
e2e: projects.filter(p => p.type === 'e2e')
188
};
189
}
190
191
function getProjectFileCount(graph: ProjectGraph, projectName: string): number {
192
const project = graph.nodes[projectName];
193
return project?.data.files?.length || 0;
194
}
195
```
196
197
### Analyzing External Dependencies
198
199
```typescript
200
import type { ProjectGraph, ProjectGraphExternalNode } from "@nrwl/tao/shared/project-graph";
201
202
function analyzeExternalDependencies(graph: ProjectGraph) {
203
const externalNodes = graph.externalNodes || {};
204
205
const npmPackages = Object.values(externalNodes)
206
.filter((node): node is ProjectGraphExternalNode => node.type === 'npm')
207
.map(node => ({
208
name: node.data.packageName,
209
version: node.data.version
210
}));
211
212
console.log(`External dependencies: ${npmPackages.length}`);
213
npmPackages.forEach(pkg => {
214
console.log(` ${pkg.name}@${pkg.version}`);
215
});
216
217
return npmPackages;
218
}
219
```
220
221
### Finding Dependency Chains
222
223
```typescript
224
import type { ProjectGraph, ProjectGraphDependency } from "@nrwl/tao/shared/project-graph";
225
226
function findDependencyChain(graph: ProjectGraph, from: string, to: string): string[] | null {
227
const visited = new Set<string>();
228
const path: string[] = [];
229
230
function dfs(current: string): boolean {
231
if (current === to) {
232
path.push(current);
233
return true;
234
}
235
236
if (visited.has(current)) {
237
return false;
238
}
239
240
visited.add(current);
241
path.push(current);
242
243
const dependencies = graph.dependencies[current] || [];
244
for (const dep of dependencies) {
245
if (dfs(dep.target)) {
246
return true;
247
}
248
}
249
250
path.pop();
251
return false;
252
}
253
254
return dfs(from) ? path : null;
255
}
256
```
257
258
### Working with File Data
259
260
```typescript
261
import type { FileData, ProjectFileMap } from "@nrwl/tao/shared/project-graph";
262
263
function getChangedFiles(fileMap: ProjectFileMap, previousHashes: Record<string, string>): FileData[] {
264
const changedFiles: FileData[] = [];
265
266
Object.values(fileMap).forEach(projectFiles => {
267
projectFiles.forEach(file => {
268
const previousHash = previousHashes[file.file];
269
if (!previousHash || previousHash !== file.hash) {
270
changedFiles.push(file);
271
}
272
});
273
});
274
275
return changedFiles;
276
}
277
278
function getFilesWithDependencies(fileMap: ProjectFileMap): FileData[] {
279
return Object.values(fileMap)
280
.flat()
281
.filter(file => file.dependencies && file.dependencies.length > 0);
282
}
283
```
284
285
## Integration with Workspace APIs
286
287
The project graph types integrate with other @nrwl/tao workspace management APIs:
288
289
```typescript
290
import type { ProjectGraph } from "@nrwl/tao/shared/project-graph";
291
import { Workspaces } from "@nrwl/tao/shared/workspace";
292
import { logger } from "@nrwl/tao/shared/logger";
293
294
function analyzeWorkspaceStructure(root: string, graph: ProjectGraph) {
295
const workspaces = new Workspaces(root);
296
const projects = workspaces.readProjectsConfigurations();
297
298
// Compare project graph with workspace configuration
299
const configuredProjects = Object.keys(projects.projects);
300
const graphProjects = Object.keys(graph.nodes);
301
302
const missingFromGraph = configuredProjects.filter(p => !graphProjects.includes(p));
303
const missingFromConfig = graphProjects.filter(p => !configuredProjects.includes(p));
304
305
if (missingFromGraph.length > 0) {
306
logger.warn(`Projects missing from graph: ${missingFromGraph.join(', ')}`);
307
}
308
309
if (missingFromConfig.length > 0) {
310
logger.warn(`Projects missing from config: ${missingFromConfig.join(', ')}`);
311
}
312
}
313
```