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

workspace-root.mddocs/

0

# Workspace Root

1

2

Utilities for finding and working with workspace root directories. Provides reliable detection of Nx workspace boundaries and root path resolution.

3

4

## Capabilities

5

6

### Workspace Root Constant

7

8

Pre-calculated workspace root directory for the current process.

9

10

```typescript { .api }

11

/**

12

* The root directory of the current workspace

13

* Automatically detected by looking for nx.json, workspace.json, or nx executable

14

*/

15

export const workspaceRoot: string;

16

```

17

18

**Usage Examples:**

19

20

```typescript

21

import { workspaceRoot } from "@nrwl/tao/utils/app-root";

22

23

console.log('Current workspace root:', workspaceRoot);

24

25

// Use in file operations

26

const nxJsonPath = `${workspaceRoot}/nx.json`;

27

const packageJsonPath = `${workspaceRoot}/package.json`;

28

29

// Use with other APIs

30

import { Workspaces } from "@nrwl/tao/shared/workspace";

31

const workspaces = new Workspaces(workspaceRoot);

32

```

33

34

### Workspace Root Detection

35

36

Internal function for finding workspace root directories.

37

38

```typescript { .api }

39

/**

40

* Internal function to find workspace root by looking for nx.json, nx, or nx.bat files

41

* @param dir - Directory to start searching from

42

* @param candidateRoot - Previously found candidate root (for recursion)

43

* @returns Path to the workspace root directory

44

*/

45

export function workspaceRootInner(dir: string, candidateRoot: string | null): string;

46

```

47

48

**Usage Examples:**

49

50

```typescript

51

import { workspaceRootInner } from "@nrwl/tao/utils/app-root";

52

53

// Find workspace root starting from specific directory

54

const rootFromPath = workspaceRootInner('/path/to/some/nested/directory', null);

55

console.log('Workspace root:', rootFromPath);

56

57

// Find workspace root with candidate (useful for optimization)

58

const rootWithCandidate = workspaceRootInner(

59

'/path/to/nested/dir',

60

'/path/to/potential/root'

61

);

62

```

63

64

## Detection Logic

65

66

The workspace root detection follows this priority order:

67

68

1. **nx.json file** - Primary indicator of an Nx workspace

69

2. **nx executable** - Unix/Linux nx binary in the directory

70

3. **nx.bat file** - Windows nx batch file in the directory

71

4. **Traversal** - Recursively searches parent directories until found

72

73

## Usage Examples

74

75

### Basic Workspace Operations

76

77

```typescript

78

import { workspaceRoot } from "@nrwl/tao/utils/app-root";

79

import { existsSync, readFileSync } from 'fs';

80

import { join } from 'path';

81

82

// Check if we're in an Nx workspace

83

function isNxWorkspace(): boolean {

84

return existsSync(join(workspaceRoot, 'nx.json'));

85

}

86

87

// Read workspace package.json

88

function getWorkspacePackageJson() {

89

const packageJsonPath = join(workspaceRoot, 'package.json');

90

91

if (existsSync(packageJsonPath)) {

92

return JSON.parse(readFileSync(packageJsonPath, 'utf-8'));

93

}

94

95

return null;

96

}

97

98

// Get relative path from workspace root

99

function getRelativePath(absolutePath: string): string {

100

return absolutePath.replace(workspaceRoot, '').replace(/^\//, '');

101

}

102

103

console.log('Is Nx workspace:', isNxWorkspace());

104

console.log('Workspace package.json:', getWorkspacePackageJson());

105

console.log('Current relative path:', getRelativePath(process.cwd()));

106

```

107

108

### Path Resolution Utilities

109

110

```typescript

111

import { workspaceRoot } from "@nrwl/tao/utils/app-root";

112

import { join, relative, resolve } from 'path';

113

114

class WorkspacePathUtils {

115

static resolveFromRoot(...paths: string[]): string {

116

return join(workspaceRoot, ...paths);

117

}

118

119

static resolveToRoot(path: string): string {

120

return resolve(workspaceRoot, path);

121

}

122

123

static getRelativeToRoot(absolutePath: string): string {

124

return relative(workspaceRoot, absolutePath);

125

}

126

127

static isInWorkspace(path: string): boolean {

128

const relativePath = this.getRelativeToRoot(path);

129

return !relativePath.startsWith('../');

130

}

131

}

132

133

// Usage examples

134

const appPath = WorkspacePathUtils.resolveFromRoot('apps', 'my-app');

135

const libPath = WorkspacePathUtils.resolveFromRoot('libs', 'shared', 'ui');

136

const configPath = WorkspacePathUtils.resolveFromRoot('nx.json');

137

138

console.log('App path:', appPath);

139

console.log('Lib path:', libPath);

140

console.log('Config path:', configPath);

141

142

// Check if paths are within workspace

143

console.log('Is app in workspace:', WorkspacePathUtils.isInWorkspace(appPath));

144

console.log('Is external path in workspace:', WorkspacePathUtils.isInWorkspace('/tmp/external'));

145

```

146

147

### Custom Workspace Detection

148

149

```typescript

150

import { workspaceRootInner } from "@nrwl/tao/utils/app-root";

151

import { existsSync } from 'fs';

152

import { dirname } from 'path';

153

154

function findWorkspaceRoot(startPath: string): string | null {

155

try {

156

return workspaceRootInner(startPath, null);

157

} catch (error) {

158

return null;

159

}

160

}

161

162

function findNearestWorkspace(filePath: string): string | null {

163

let currentDir = dirname(filePath);

164

165

// Search up the directory tree

166

while (currentDir !== dirname(currentDir)) {

167

const workspaceRoot = findWorkspaceRoot(currentDir);

168

if (workspaceRoot) {

169

return workspaceRoot;

170

}

171

currentDir = dirname(currentDir);

172

}

173

174

return null;

175

}

176

177

// Usage

178

const fileInProject = '/path/to/deep/nested/file.ts';

179

const nearestWorkspace = findNearestWorkspace(fileInProject);

180

181

if (nearestWorkspace) {

182

console.log(`Found workspace: ${nearestWorkspace}`);

183

} else {

184

console.log('No workspace found');

185

}

186

```

187

188

### Multi-Workspace Support

189

190

```typescript

191

import { workspaceRootInner } from "@nrwl/tao/utils/app-root";

192

import { readdirSync, statSync } from 'fs';

193

import { join } from 'path';

194

195

class MultiWorkspaceManager {

196

private workspaces: Map<string, string> = new Map();

197

198

constructor(private searchRoot: string) {

199

this.discoverWorkspaces();

200

}

201

202

private discoverWorkspaces(): void {

203

this.searchDirectory(this.searchRoot);

204

}

205

206

private searchDirectory(dir: string): void {

207

try {

208

const entries = readdirSync(dir);

209

210

for (const entry of entries) {

211

const fullPath = join(dir, entry);

212

213

if (statSync(fullPath).isDirectory()) {

214

// Try to find workspace in this directory

215

try {

216

const workspaceRoot = workspaceRootInner(fullPath, null);

217

if (workspaceRoot && !this.workspaces.has(workspaceRoot)) {

218

this.workspaces.set(entry, workspaceRoot);

219

}

220

} catch {

221

// Not a workspace, continue searching subdirectories

222

this.searchDirectory(fullPath);

223

}

224

}

225

}

226

} catch (error) {

227

// Directory might not be accessible

228

}

229

}

230

231

getWorkspaces(): Map<string, string> {

232

return new Map(this.workspaces);

233

}

234

235

getWorkspaceByName(name: string): string | undefined {

236

return this.workspaces.get(name);

237

}

238

239

getAllWorkspaceRoots(): string[] {

240

return Array.from(this.workspaces.values());

241

}

242

}

243

244

// Usage

245

const manager = new MultiWorkspaceManager('/path/to/monorepo');

246

const workspaces = manager.getWorkspaces();

247

248

console.log('Discovered workspaces:');

249

workspaces.forEach((root, name) => {

250

console.log(` ${name}: ${root}`);

251

});

252

```

253

254

### Environment Integration

255

256

```typescript

257

import { workspaceRoot } from "@nrwl/tao/utils/app-root";

258

259

function setupWorkspaceEnvironment() {

260

// Set environment variables for tools

261

process.env.NX_WORKSPACE_ROOT = workspaceRoot;

262

process.env.WORKSPACE_ROOT = workspaceRoot;

263

264

// Add workspace bin to PATH

265

const workspaceBin = `${workspaceRoot}/node_modules/.bin`;

266

if (!process.env.PATH?.includes(workspaceBin)) {

267

process.env.PATH = `${workspaceBin}:${process.env.PATH}`;

268

}

269

270

// Set working directory to workspace root if needed

271

if (process.cwd() !== workspaceRoot) {

272

console.log(`Changing directory to workspace root: ${workspaceRoot}`);

273

process.chdir(workspaceRoot);

274

}

275

}

276

277

// Validate workspace environment

278

function validateWorkspaceEnvironment(): boolean {

279

const checks = [

280

{ name: 'Workspace root exists', check: () => existsSync(workspaceRoot) },

281

{ name: 'nx.json exists', check: () => existsSync(`${workspaceRoot}/nx.json`) },

282

{ name: 'package.json exists', check: () => existsSync(`${workspaceRoot}/package.json`) },

283

{ name: 'node_modules exists', check: () => existsSync(`${workspaceRoot}/node_modules`) }

284

];

285

286

let allValid = true;

287

288

checks.forEach(({ name, check }) => {

289

const isValid = check();

290

console.log(`${isValid ? '✓' : '✗'} ${name}`);

291

if (!isValid) allValid = false;

292

});

293

294

return allValid;

295

}

296

297

// Usage

298

setupWorkspaceEnvironment();

299

const isValid = validateWorkspaceEnvironment();

300

301

if (!isValid) {

302

console.error('Workspace environment validation failed');

303

process.exit(1);

304

}

305

```

306

307

## Integration with Other APIs

308

309

The workspace root utilities integrate with all other @nrwl/tao APIs:

310

311

```typescript

312

import { workspaceRoot } from "@nrwl/tao/utils/app-root";

313

import { Workspaces } from "@nrwl/tao/shared/workspace";

314

import { detectPackageManager } from "@nrwl/tao/shared/package-manager";

315

import { FsTree } from "@nrwl/tao/shared/tree";

316

import { logger } from "@nrwl/tao/shared/logger";

317

318

function initializeWorkspaceTools() {

319

logger.info(`Initializing tools for workspace: ${workspaceRoot}`);

320

321

// Initialize workspace management

322

const workspaces = new Workspaces(workspaceRoot);

323

const hasNxJson = workspaces.hasNxJson();

324

325

if (!hasNxJson) {

326

logger.error('Not a valid Nx workspace');

327

return null;

328

}

329

330

// Initialize package manager detection

331

const packageManager = detectPackageManager(workspaceRoot);

332

logger.info(`Detected package manager: ${packageManager}`);

333

334

// Initialize virtual file system

335

const tree = new FsTree(workspaceRoot);

336

337

// Read workspace configuration

338

const nxJson = workspaces.readNxJson();

339

const projects = workspaces.readProjectsConfigurations();

340

341

logger.info(`Workspace '${nxJson.npmScope || 'unnamed'}' initialized`);

342

logger.info(`Found ${Object.keys(projects.projects).length} projects`);

343

344

return {

345

root: workspaceRoot,

346

workspaces,

347

packageManager,

348

tree,

349

nxJson,

350

projects

351

};

352

}

353

354

// Usage

355

const tools = initializeWorkspaceTools();

356

if (tools) {

357

console.log('Workspace tools initialized successfully');

358

console.log(`Working in: ${tools.root}`);

359

}

360

```