or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli.mddevkit-core.mddevkit-files.mddevkit-tasks.mdgenerators-executors.mdindex.mdplugins.md

devkit-files.mddocs/

0

# File Operations

1

2

File system utilities and virtual file tree operations for generators, code transformations, and automated workspace modifications.

3

4

## Capabilities

5

6

### JSON File Operations

7

8

High-level utilities for reading, writing, and updating JSON files with type safety.

9

10

```typescript { .api }

11

/**

12

* Reads and parses a JSON file

13

* @param path - Absolute or workspace-relative path to JSON file

14

* @returns Parsed JSON object

15

*/

16

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

17

18

/**

19

* Writes an object to a JSON file with formatting

20

* @param path - Absolute or workspace-relative path to JSON file

21

* @param data - Object to serialize as JSON

22

*/

23

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

24

25

/**

26

* Updates a JSON file using an updater function

27

* @param path - Absolute or workspace-relative path to JSON file

28

* @param updater - Function that receives current data and returns updated data

29

*/

30

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

31

32

/**

33

* Reads and parses a JSON file from virtual tree

34

* @param tree - Virtual file tree

35

* @param path - Path to JSON file

36

* @returns Parsed JSON object

37

*/

38

function readJson<T = any>(tree: Tree, path: string): T;

39

40

/**

41

* Writes an object to a JSON file in virtual tree

42

* @param tree - Virtual file tree

43

* @param path - Path to JSON file

44

* @param data - Object to serialize as JSON

45

*/

46

function writeJson<T = any>(tree: Tree, path: string, data: T): void;

47

48

/**

49

* Updates a JSON file in virtual tree using an updater function

50

* @param tree - Virtual file tree

51

* @param path - Path to JSON file

52

* @param updater - Function that receives current data and returns updated data

53

*/

54

function updateJson<T = any>(tree: Tree, path: string, updater: (data: T) => T): void;

55

```

56

57

### Virtual File Tree

58

59

Virtual file system for generators that allows batch operations before writing to disk.

60

61

```typescript { .api }

62

/**

63

* Virtual file system interface for generators

64

*/

65

interface Tree {

66

/** Read file contents as buffer */

67

read(filePath: string): Buffer | null;

68

/** Read file contents as string with optional encoding */

69

read(filePath: string, encoding: BufferEncoding): string | null;

70

/** Write file contents from buffer or string */

71

write(filePath: string, content: Buffer | string): void;

72

/** Check if file exists */

73

exists(filePath: string): boolean;

74

/** Delete file */

75

delete(filePath: string): void;

76

/** Rename file */

77

rename(from: string, to: string): void;

78

/** Check if path is a file */

79

isFile(filePath: string): boolean;

80

/** List children of directory */

81

children(dirPath: string): string[];

82

/** Get file change type */

83

listChanges(): FileChange[];

84

}

85

86

interface FileChange {

87

path: string;

88

type: 'CREATE' | 'DELETE' | 'UPDATE';

89

content?: Buffer | string;

90

}

91

92

/**

93

* Creates a virtual file tree from the current file system

94

* @param root - Root directory path (defaults to workspace root)

95

* @returns Virtual file tree

96

*/

97

function createFsTree(root?: string): FsTree;

98

99

/**

100

* File system-based tree implementation

101

*/

102

declare class FsTree implements Tree {

103

constructor(root: string, isVerbose: boolean);

104

105

read(filePath: string): Buffer | null;

106

read(filePath: string, encoding: BufferEncoding): string | null;

107

write(filePath: string, content: Buffer | string): void;

108

exists(filePath: string): boolean;

109

delete(filePath: string): void;

110

rename(from: string, to: string): void;

111

isFile(filePath: string): boolean;

112

children(dirPath: string): string[];

113

listChanges(): FileChange[];

114

}

115

```

116

117

### File Tree Operations

118

119

Functions for applying changes from virtual trees to the actual file system.

120

121

```typescript { .api }

122

/**

123

* Applies all changes from a virtual tree to the file system

124

* @param tree - Virtual file tree with pending changes

125

* @param verbose - Whether to log changes being applied

126

*/

127

function flushChanges(tree: Tree, verbose?: boolean): void;

128

129

/**

130

* Applies string changes to content

131

* @param content - Original string content

132

* @param changes - Array of string insertions and deletions

133

* @returns Modified string content

134

*/

135

function applyChangesToString(

136

content: string,

137

changes: (StringInsertion | StringDeletion)[]

138

): string;

139

140

interface StringInsertion {

141

type: 'insertion';

142

index: number;

143

text: string;

144

}

145

146

interface StringDeletion {

147

type: 'deletion';

148

start: number;

149

length: number;

150

}

151

```

152

153

### Path Utilities

154

155

Utilities for working with file paths in a cross-platform manner.

156

157

```typescript { .api }

158

/**

159

* Joins path fragments using the correct separator

160

* @param fragments - Path fragments to join

161

* @returns Joined path string

162

*/

163

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

164

165

/**

166

* Normalizes a path by resolving . and .. segments

167

* @param path - Path to normalize

168

* @returns Normalized path string

169

*/

170

function normalizePath(path: string): string;

171

172

/**

173

* Gets the relative path from one path to another

174

* @param from - Source path

175

* @param to - Target path

176

* @returns Relative path string

177

*/

178

function getRelativePath(from: string, to: string): string;

179

180

/**

181

* Converts Windows-style paths to Unix-style paths

182

* @param path - Path to convert

183

* @returns Unix-style path

184

*/

185

function toUnixPath(path: string): string;

186

```

187

188

### Template Processing

189

190

Functions for processing file templates with variable substitution.

191

192

```typescript { .api }

193

/**

194

* Generates files from templates with variable substitution

195

* @param tree - Virtual file tree

196

* @param templatePath - Path to template directory

197

* @param targetPath - Target directory for generated files

198

* @param substitutions - Variables for template substitution

199

*/

200

function generateFiles(

201

tree: Tree,

202

templatePath: string,

203

targetPath: string,

204

substitutions: any

205

): void;

206

207

/**

208

* Offset from template file names for substitution patterns

209

* @param name - Template file name

210

* @param substitutions - Variables for substitution

211

* @returns Processed file name

212

*/

213

function offsetFromRoot(name: string): string;

214

215

/**

216

* Names utility functions for template processing

217

*/

218

interface Names {

219

/** Convert to className format */

220

className: (name: string) => string;

221

/** Convert to propertyName format */

222

propertyName: (name: string) => string;

223

/** Convert to constantName format */

224

constantName: (name: string) => string;

225

/** Convert to fileName format */

226

fileName: (name: string) => string;

227

}

228

229

const names: Names;

230

```

231

232

### File Filtering and Visiting

233

234

Utilities for traversing and filtering files in the workspace.

235

236

```typescript { .api }

237

/**

238

* Visits files that are not ignored by .gitignore

239

* @param tree - Virtual file tree

240

* @param dirPath - Directory to start from (default: workspace root)

241

* @param visitor - Function called for each file

242

*/

243

function visitNotIgnoredFiles(

244

tree: Tree,

245

dirPath: string,

246

visitor: (filePath: string) => void

247

): void;

248

249

/**

250

* Gets all files matching a glob pattern

251

* @param tree - Virtual file tree

252

* @param pattern - Glob pattern to match

253

* @returns Array of matching file paths

254

*/

255

function getMatchingFiles(tree: Tree, pattern: string): string[];

256

257

/**

258

* Checks if a file should be ignored based on .gitignore rules

259

* @param filePath - Path to check

260

* @param root - Root directory for .gitignore lookup

261

* @returns True if file should be ignored

262

*/

263

function isIgnored(filePath: string, root?: string): boolean;

264

```

265

266

## Usage Examples

267

268

### Basic File Operations

269

270

```typescript

271

import {

272

readJsonFile,

273

writeJsonFile,

274

updateJsonFile,

275

logger

276

} from "nx/src/devkit-exports";

277

278

// Read package.json

279

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

280

logger.info(`Project: ${packageJson.name} v${packageJson.version}`);

281

282

// Update package.json

283

updateJsonFile('package.json', (json) => ({

284

...json,

285

scripts: {

286

...json.scripts,

287

'custom-build': 'nx build --configuration=production'

288

}

289

}));

290

291

// Write new configuration file

292

writeJsonFile('nx-custom.json', {

293

customSetting: 'value',

294

options: {

295

enableFeature: true

296

}

297

});

298

```

299

300

### Generator File Operations

301

302

```typescript

303

import {

304

Tree,

305

generateFiles,

306

formatFiles,

307

joinPathFragments,

308

names

309

} from "nx/src/devkit-exports";

310

311

interface ComponentGeneratorSchema {

312

name: string;

313

project: string;

314

directory?: string;

315

}

316

317

export default async function componentGenerator(

318

tree: Tree,

319

options: ComponentGeneratorSchema

320

) {

321

const projectRoot = readProjectConfiguration(tree, options.project).root;

322

const componentDir = options.directory

323

? joinPathFragments(projectRoot, 'src', options.directory)

324

: joinPathFragments(projectRoot, 'src');

325

326

// Generate component files from templates

327

generateFiles(

328

tree,

329

joinPathFragments(__dirname, 'files'),

330

componentDir,

331

{

332

...options,

333

...names(options.name),

334

template: '' // Remove __template__ from file names

335

}

336

);

337

338

// Update barrel export

339

const indexPath = joinPathFragments(componentDir, 'index.ts');

340

const componentName = names(options.name).className;

341

342

if (tree.exists(indexPath)) {

343

const content = tree.read(indexPath, 'utf-8');

344

const updatedContent = `${content}\nexport * from './${names(options.name).fileName}';`;

345

tree.write(indexPath, updatedContent);

346

} else {

347

tree.write(indexPath, `export * from './${names(options.name).fileName}';`);

348

}

349

350

// Format generated files

351

await formatFiles(tree);

352

}

353

```

354

355

### Advanced Tree Operations

356

357

```typescript

358

import {

359

Tree,

360

visitNotIgnoredFiles,

361

applyChangesToString,

362

StringInsertion

363

} from "nx/src/devkit-exports";

364

365

function addImportToFiles(tree: Tree, importStatement: string) {

366

visitNotIgnoredFiles(tree, '', (filePath) => {

367

if (!filePath.endsWith('.ts') && !filePath.endsWith('.tsx')) {

368

return;

369

}

370

371

const content = tree.read(filePath, 'utf-8');

372

if (!content || content.includes(importStatement)) {

373

return;

374

}

375

376

// Add import at the top of the file

377

const changes: StringInsertion[] = [{

378

type: 'insertion',

379

index: 0,

380

text: `${importStatement}\n`

381

}];

382

383

const updatedContent = applyChangesToString(content, changes);

384

tree.write(filePath, updatedContent);

385

});

386

}

387

388

// Usage: Add import to all TypeScript files

389

addImportToFiles(tree, "import { logger } from 'nx/src/devkit-exports';");

390

```

391

392

### Template File Structure

393

394

Template files use substitution patterns in file names and content:

395

396

```

397

files/

398

├── __name@fileName__.component.ts__template__

399

├── __name@fileName__.component.spec.ts__template__

400

└── __name@fileName__.module.ts__template__

401

```

402

403

Template content example (`__name@fileName__.component.ts__template__`):

404

405

```typescript

406

import { Component } from '@angular/core';

407

408

@Component({

409

selector: '<%= selector %>',

410

templateUrl: './<%= fileName %>.component.html',

411

styleUrls: ['./<%= fileName %>.component.css']

412

})

413

export class <%= className %>Component {

414

title = '<%= name %>';

415

}

416

```

417

418

### Working with Configuration Files

419

420

```typescript

421

import { Tree, updateJsonFile, readProjectConfiguration } from "nx/src/devkit-exports";

422

423

function updateProjectTsConfig(tree: Tree, projectName: string, options: any) {

424

const projectConfig = readProjectConfiguration(tree, projectName);

425

const tsConfigPath = joinPathFragments(projectConfig.root, 'tsconfig.json');

426

427

if (tree.exists(tsConfigPath)) {

428

updateJsonFile(tree, tsConfigPath, (tsconfig) => ({

429

...tsconfig,

430

compilerOptions: {

431

...tsconfig.compilerOptions,

432

...options.compilerOptions

433

}

434

}));

435

}

436

}

437

```