or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

executors.mdgenerators.mdindex.mdpackage-management.mdplugin-development.mdproject-graph.mdtree-operations.mdutilities.mdworkspace-configuration.md

utilities.mddocs/

0

# Utility Functions

1

2

General utility functions for string manipulation, path operations, naming conventions, workspace layout management, and common development tasks.

3

4

## Capabilities

5

6

### Naming Utilities

7

8

Generate various naming conventions from a base name for consistent file and variable naming.

9

10

```typescript { .api }

11

/**

12

* Generate different naming conventions from a base name

13

* @param name - Base name to generate variations from

14

* @returns Object with different naming conventions

15

*/

16

function names(name: string): {

17

/** Original name */

18

name: string;

19

/** PascalCase class name */

20

className: string;

21

/** camelCase property name */

22

propertyName: string;

23

/** CONSTANT_CASE constant name */

24

constantName: string;

25

/** kebab-case file name */

26

fileName: string;

27

};

28

```

29

30

**Usage Examples:**

31

32

```typescript

33

import { names } from "@nx/devkit";

34

35

function createComponent(componentName: string) {

36

const nameVariations = names(componentName);

37

38

console.log(nameVariations);

39

// Input: "user-profile"

40

// Output: {

41

// name: "user-profile",

42

// className: "UserProfile",

43

// propertyName: "userProfile",

44

// constantName: "USER_PROFILE",

45

// fileName: "user-profile"

46

// }

47

48

// Use in templates

49

const templateVars = {

50

...nameVariations,

51

// Template will use: <%= className %>, <%= propertyName %>, etc.

52

};

53

}

54

```

55

56

### Path Utilities

57

58

Utilities for working with file paths, calculating relative paths, and handling cross-platform path operations.

59

60

```typescript { .api }

61

/**

62

* Calculate relative path from project directory to workspace root

63

* @param fullPathToDir - Full path to directory

64

* @returns Relative path string (e.g., "../.." or "../../..")

65

*/

66

function offsetFromRoot(fullPathToDir: string): string;

67

68

/**

69

* Join path fragments in a cross-platform way

70

* @param fragments - Path segments to join

71

* @returns Joined path string

72

*/

73

function joinPathFragments(...fragments: string[]): string;

74

75

/**

76

* Normalize path separators for current platform

77

* @param osSpecificPath - Path with OS-specific separators

78

* @returns Normalized path string

79

*/

80

function normalizePath(osSpecificPath: string): string;

81

82

/**

83

* Workspace root directory path

84

*/

85

const workspaceRoot: string;

86

```

87

88

**Usage Examples:**

89

90

```typescript

91

import {

92

offsetFromRoot,

93

joinPathFragments,

94

normalizePath,

95

workspaceRoot

96

} from "@nx/devkit";

97

98

function generateProjectFiles(projectRoot: string) {

99

// Calculate relative path to workspace root

100

const rootOffset = offsetFromRoot(projectRoot);

101

console.log(`From ${projectRoot} to root: ${rootOffset}`);

102

// "libs/my-lib" → "../../"

103

// "apps/my-app/src" → "../../../"

104

105

// Join path fragments safely

106

const configPath = joinPathFragments(projectRoot, "src", "config", "settings.json");

107

console.log(`Config path: ${configPath}`);

108

// "libs/my-lib/src/config/settings.json"

109

110

// Normalize paths from different sources

111

const windowsPath = "libs\\my-lib\\src\\index.ts";

112

const normalizedPath = normalizePath(windowsPath);

113

console.log(`Normalized: ${normalizedPath}`);

114

// "libs/my-lib/src/index.ts"

115

116

// Use workspace root for absolute paths

117

const absoluteProjectPath = joinPathFragments(workspaceRoot, projectRoot);

118

console.log(`Absolute project path: ${absoluteProjectPath}`);

119

}

120

```

121

122

### String Manipulation

123

124

Advanced string manipulation utilities for applying changes and transformations.

125

126

```typescript { .api }

127

/**

128

* Apply a series of changes to a string

129

* @param text - Original text

130

* @param changes - Array of changes to apply

131

* @returns Modified text with all changes applied

132

*/

133

function applyChangesToString(

134

text: string,

135

changes: StringChange[]

136

): string;

137

138

/**

139

* Remove leading indentation from template strings

140

* @param strings - Template string parts

141

* @param values - Template values

142

* @returns String with consistent indentation removed

143

*/

144

function stripIndents(strings: TemplateStringsArray, ...values: any[]): string;

145

146

/**

147

* String change operation

148

*/

149

type StringChange = StringInsertion | StringDeletion;

150

151

/**

152

* Insert text at specific position

153

*/

154

interface StringInsertion {

155

type: ChangeType.Insert;

156

index: number;

157

text: string;

158

}

159

160

/**

161

* Delete text from specific range

162

*/

163

interface StringDeletion {

164

type: ChangeType.Delete;

165

start: number;

166

length: number;

167

}

168

169

enum ChangeType {

170

Insert = "insert",

171

Delete = "delete"

172

}

173

```

174

175

**Usage Examples:**

176

177

```typescript

178

import {

179

applyChangesToString,

180

stripIndents,

181

ChangeType,

182

StringChange

183

} from "@nx/devkit";

184

185

function modifySourceCode() {

186

const originalCode = `

187

function hello() {

188

console.log("Hello");

189

}

190

`;

191

192

// Define changes to apply

193

const changes: StringChange[] = [

194

{

195

type: ChangeType.Insert,

196

index: originalCode.indexOf('"Hello"'),

197

text: 'name: string, '

198

},

199

{

200

type: ChangeType.Insert,

201

index: originalCode.indexOf('"Hello"') + 7,

202

text: ', ${name}'

203

}

204

];

205

206

// Apply changes

207

const modifiedCode = applyChangesToString(originalCode, changes);

208

console.log(modifiedCode);

209

210

// Use stripIndents for clean template strings

211

const template = stripIndents`

212

export class ${className} {

213

constructor(private name: string) {}

214

215

greet(): string {

216

return \`Hello, \${this.name}!\`;

217

}

218

}

219

`;

220

221

console.log(template); // No leading indentation

222

}

223

```

224

225

### JSON Utilities

226

227

Low-level JSON parsing and serialization utilities for direct file system operations.

228

229

```typescript { .api }

230

/**

231

* Parse JSON string with comment support and error handling

232

* @param input - JSON string to parse

233

* @param options - Parsing options

234

* @returns Parsed object

235

*/

236

function parseJson<T = any>(input: string, options?: JsonParseOptions): T;

237

238

/**

239

* Serialize object to JSON string with formatting

240

* @param input - Object to serialize

241

* @param options - Serialization options

242

* @returns Formatted JSON string

243

*/

244

function serializeJson<T = any>(

245

input: T,

246

options?: JsonSerializeOptions

247

): string;

248

249

/**

250

* Remove comments from JSON string

251

* @param text - JSON string with comments

252

* @returns Clean JSON string

253

*/

254

function stripJsonComments(text: string): string;

255

256

/**

257

* Read and parse JSON file from disk

258

* @param path - File path

259

* @returns Parsed JSON object

260

*/

261

function readJsonFile<T = any>(path: string): T;

262

263

/**

264

* Write object to JSON file on disk

265

* @param path - File path

266

* @param data - Object to write

267

*/

268

function writeJsonFile<T = any>(path: string, data: T): void;

269

270

interface JsonParseOptions {

271

/** Allow trailing commas */

272

allowTrailingComma?: boolean;

273

/** Expect comments in JSON */

274

expectComments?: boolean;

275

/** Disable comments */

276

disallowComments?: boolean;

277

}

278

279

interface JsonSerializeOptions {

280

/** Number of spaces for indentation */

281

spaces?: number;

282

/** Replacer function for custom serialization */

283

replacer?: (key: string, value: any) => any;

284

}

285

```

286

287

**Usage Examples:**

288

289

```typescript

290

import {

291

parseJson,

292

serializeJson,

293

stripJsonComments,

294

readJsonFile,

295

writeJsonFile

296

} from "@nx/devkit";

297

298

function processJsonFiles() {

299

// Parse JSON with comments

300

const jsonWithComments = `{

301

// Project configuration

302

"name": "my-project",

303

/* Dependencies */

304

"dependencies": {

305

"react": "^18.0.0", // Latest React

306

}

307

}`;

308

309

const parsed = parseJson(jsonWithComments, { expectComments: true });

310

console.log(parsed);

311

312

// Remove comments from JSON string

313

const cleanJson = stripJsonComments(jsonWithComments);

314

console.log("Clean JSON:", cleanJson);

315

316

// Serialize with formatting

317

const formatted = serializeJson(parsed, { spaces: 2 });

318

console.log("Formatted:", formatted);

319

320

// Read/write JSON files directly

321

const packageJson = readJsonFile("package.json");

322

packageJson.scripts = { ...packageJson.scripts, build: "nx build" };

323

writeJsonFile("package.json", packageJson);

324

}

325

```

326

327

### Workspace Layout

328

329

Manage workspace directory structure and understand project organization patterns.

330

331

```typescript { .api }

332

/**

333

* Get workspace layout configuration including apps and libs directories

334

* @param tree - File system tree

335

* @returns Workspace layout configuration

336

*/

337

function getWorkspaceLayout(tree: Tree): {

338

appsDir: string;

339

libsDir: string;

340

standaloneAsDefault: boolean;

341

};

342

343

/**

344

* Extract layout directory information from a path

345

* @param directory - Directory path to analyze

346

* @returns Layout directory components

347

*/

348

function extractLayoutDirectory(directory?: string): {

349

layoutDirectory: string | null;

350

projectDirectory?: string;

351

};

352

353

/**

354

* Default workspace layout configuration

355

*/

356

const workspaceLayout: {

357

appsDir: string;

358

libsDir: string;

359

};

360

```

361

362

**Usage Examples:**

363

364

```typescript

365

import {

366

Tree,

367

getWorkspaceLayout,

368

extractLayoutDirectory,

369

workspaceLayout

370

} from "@nx/devkit";

371

372

function organizeProject(tree: Tree, options: {

373

name: string;

374

directory?: string;

375

projectType: "application" | "library"

376

}) {

377

// Get current workspace layout

378

const layout = getWorkspaceLayout(tree);

379

console.log(`Apps directory: ${layout.appsDir}`); // "apps"

380

console.log(`Libs directory: ${layout.libsDir}`); // "libs"

381

382

// Parse directory option

383

const { layoutDirectory, projectDirectory } = extractLayoutDirectory(options.directory);

384

// Input: "ui/components" → { layoutDirectory: "ui", projectDirectory: "components" }

385

386

// Determine final project path

387

const baseDir = options.projectType === "application"

388

? layout.appsDir

389

: layout.libsDir;

390

391

let projectPath: string;

392

if (layoutDirectory && projectDirectory) {

393

projectPath = `${baseDir}/${layoutDirectory}/${projectDirectory}`;

394

} else if (options.directory) {

395

projectPath = `${baseDir}/${options.directory}`;

396

} else {

397

projectPath = `${baseDir}/${options.name}`;

398

}

399

400

console.log(`Final project path: ${projectPath}`);

401

402

// Use default layout for fallback

403

if (!layout.appsDir) {

404

console.log(`Using default apps directory: ${workspaceLayout.appsDir}`);

405

}

406

}

407

```

408

409

### Logging and Output

410

411

Structured logging and formatted output utilities for generators and executors.

412

413

```typescript { .api }

414

/**

415

* Structured logger with different log levels

416

*/

417

const logger: {

418

/** Debug level logging (hidden by default) */

419

debug(message: string, ...args: any[]): void;

420

/** Informational logging */

421

info(message: string, ...args: any[]): void;

422

/** Warning level logging */

423

warn(message: string, ...args: any[]): void;

424

/** Error level logging */

425

error(message: string, ...args: any[]): void;

426

/** Fatal error logging */

427

fatal(message: string, ...args: any[]): void;

428

/** Log without formatting */

429

log(message: string, ...args: any[]): void;

430

};

431

432

/**

433

* Formatted output utilities for console display

434

*/

435

const output: {

436

/** Write formatted output */

437

write(str: string): void;

438

/** Write line with formatting */

439

writeLine(str: string): void;

440

/** Add vertical whitespace */

441

addVerticalSeparator(): void;

442

/** Add horizontal separator */

443

addHorizontalSeparator(): void;

444

/** Display success message */

445

success(message: string): void;

446

/** Display error message */

447

error(message: string): void;

448

/** Display warning message */

449

warn(message: string): void;

450

/** Display note/info message */

451

note(message: string): void;

452

};

453

```

454

455

**Usage Examples:**

456

457

```typescript

458

import { logger, output } from "@nx/devkit";

459

460

export default function myGenerator(tree: Tree, options: any) {

461

// Use structured logging

462

logger.info(`Generating ${options.name} project...`);

463

logger.debug(`Options: ${JSON.stringify(options)}`);

464

465

try {

466

// Generate files...

467

logger.info("Files generated successfully");

468

469

// Use formatted output

470

output.success(`✓ Created ${options.name} project`);

471

output.addVerticalSeparator();

472

output.note("Next steps:");

473

output.writeLine(" 1. Run nx build " + options.name);

474

output.writeLine(" 2. Run nx test " + options.name);

475

476

} catch (error) {

477

logger.error("Generation failed:", error.message);

478

output.error(`✗ Failed to create ${options.name} project`);

479

output.warn("Check the logs for more details");

480

throw error;

481

}

482

}

483

```

484

485

### Cache and Performance

486

487

Utilities for working with Nx's caching system and performance optimization.

488

489

```typescript { .api }

490

/**

491

* Cache directory path

492

*/

493

const cacheDir: string;

494

495

/**

496

* Check if Nx daemon is enabled and running

497

* @returns Whether daemon is enabled

498

*/

499

function isDaemonEnabled(): boolean;

500

501

/**

502

* Hash an array of values for cache key generation

503

* @param values - Array of values to hash

504

* @returns Hash string

505

*/

506

function hashArray(values: any[]): string;

507

```

508

509

**Usage Examples:**

510

511

```typescript

512

import { cacheDir, isDaemonEnabled, hashArray } from "@nx/devkit";

513

import { existsSync, readFileSync } from "fs";

514

import { join } from "path";

515

516

function checkCacheStatus() {

517

// Check cache directory

518

console.log(`Cache directory: ${cacheDir}`);

519

520

if (existsSync(cacheDir)) {

521

console.log("Cache directory exists");

522

523

// Check cache contents

524

const lockFilePath = join(cacheDir, "d", "daemon.lock");

525

if (existsSync(lockFilePath)) {

526

console.log("Daemon lock file found");

527

}

528

}

529

530

// Check if daemon is running

531

const daemonEnabled = isDaemonEnabled();

532

console.log(`Daemon enabled: ${daemonEnabled}`);

533

534

if (daemonEnabled) {

535

console.log("Using Nx daemon for better performance");

536

} else {

537

console.log("Running without daemon (slower but more reliable)");

538

}

539

540

// Generate cache keys using hash function

541

const cacheInputs = ["src/**/*.ts", "package.json", process.env.NODE_ENV];

542

const cacheKey = hashArray(cacheInputs);

543

console.log(`Cache key: ${cacheKey}`);

544

}

545

```

546

547

### Framework Conversion

548

549

Convert between Nx and other framework conventions.

550

551

```typescript { .api }

552

/**

553

* Convert Nx generator to Angular DevKit schematic

554

* @param generator - Nx generator function

555

* @param skipWritingConfigInOldFormat - Skip legacy config format

556

* @returns Angular DevKit schematic

557

*/

558

function convertNxGenerator<T = any>(

559

generator: Generator<T>,

560

skipWritingConfigInOldFormat?: boolean

561

): any;

562

563

/**

564

* Convert Nx executor to Angular DevKit builder

565

* @param executor - Nx executor function

566

* @returns Angular DevKit builder

567

*/

568

function convertNxExecutor(executor: Executor): any;

569

```

570

571

**Usage Examples:**

572

573

```typescript

574

import { convertNxGenerator, convertNxExecutor, Generator, Executor } from "@nx/devkit";

575

576

// Convert Nx generator for use in Angular CLI

577

const myGenerator: Generator = (tree, options) => {

578

// Nx generator implementation

579

};

580

581

const angularSchematic = convertNxGenerator(myGenerator);

582

583

// Convert Nx executor for use in Angular CLI

584

const myExecutor: Executor = (options, context) => {

585

// Nx executor implementation

586

return Promise.resolve({ success: true });

587

};

588

589

const angularBuilder = convertNxExecutor(myExecutor);

590

591

// Export for Angular CLI collections

592

export { angularSchematic as mySchematic, angularBuilder as myBuilder };

593

```