or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

angular-cli-adapter.mdconfiguration.mdindex.mdlogging.mdpackage-manager.mdproject-graph.mdtree-api.mdworkspace-management.mdworkspace-root.md

project-graph.mddocs/

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

```