or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli.mdenvironment.mdfilesystem.mdgenerator-discovery.mdgenerator-management.mdindex.mdmodule-lookup.md

filesystem.mddocs/

0

# File System Operations

1

2

Memory filesystem operations, conflict resolution, and file transforms for generator output management and package installation tasks.

3

4

## Capabilities

5

6

### Commit Shared FileSystem

7

8

Commits the memory filesystem to disk with conflict resolution and transforms.

9

10

```typescript { .api }

11

/**

12

* Commits the MemFs to disc with conflict resolution

13

* @param options - Configuration for commit operation

14

*/

15

function commitSharedFsTask(options: {

16

/** I/O adapter for user interaction */

17

adapter: InputOutputAdapter;

18

/** Options for conflict resolution */

19

conflicterOptions?: ConflicterOptions;

20

/** Memory filesystem store to commit */

21

sharedFs: Store<MemFsEditorFile>;

22

}): Promise<void>;

23

```

24

25

**Usage Example:**

26

27

```typescript

28

import { commitSharedFsTask } from "yeoman-environment";

29

import { create as createMemFs } from "mem-fs";

30

import { QueuedAdapter } from "@yeoman/adapter";

31

32

// Create memory filesystem and adapter

33

const memFs = createMemFs();

34

const adapter = new QueuedAdapter();

35

36

// Commit filesystem with conflict resolution

37

await commitSharedFsTask({

38

adapter,

39

sharedFs: memFs,

40

conflicterOptions: {

41

force: false,

42

bail: false,

43

whitespace: true

44

}

45

});

46

```

47

48

### Package Manager Installation

49

50

Execute package manager install with auto-detection and error handling.

51

52

```typescript { .api }

53

/**

54

* Executes package manager install with detection and error handling

55

* @param options - Configuration for package manager installation

56

* @returns Promise resolving to true if installation succeeded

57

*/

58

function packageManagerInstallTask(options: PackageManagerInstallTaskOptions): Promise<boolean>;

59

60

interface PackageManagerInstallTaskOptions {

61

/** Memory filesystem store */

62

memFs: Store<MemFsEditorFile>;

63

/** Path to directory containing package.json */

64

packageJsonLocation: string;

65

/** I/O adapter for user interaction */

66

adapter: InputOutputAdapter;

67

/** Preferred package manager (npm, yarn, pnpm) */

68

nodePackageManager?: string;

69

/** Custom install task function or boolean to disable */

70

customInstallTask?: boolean | ((nodePackageManager: string | undefined, defaultTask: () => Promise<boolean>) => void | Promise<void>);

71

/** Skip installation entirely */

72

skipInstall?: boolean;

73

}

74

```

75

76

**Usage Examples:**

77

78

```typescript

79

import { packageManagerInstallTask } from "yeoman-environment";

80

import { create as createMemFs } from "mem-fs";

81

import { QueuedAdapter } from "@yeoman/adapter";

82

83

const memFs = createMemFs();

84

const adapter = new QueuedAdapter();

85

86

// Basic package manager install

87

const success = await packageManagerInstallTask({

88

memFs,

89

packageJsonLocation: "/project/path",

90

adapter

91

});

92

93

// With preferred package manager

94

await packageManagerInstallTask({

95

memFs,

96

packageJsonLocation: "/project/path",

97

adapter,

98

nodePackageManager: "yarn"

99

});

100

101

// With custom install task

102

await packageManagerInstallTask({

103

memFs,

104

packageJsonLocation: "/project/path",

105

adapter,

106

customInstallTask: async (packageManager, defaultTask) => {

107

console.log(`Installing with ${packageManager}...`);

108

await defaultTask();

109

console.log("Installation complete!");

110

}

111

});

112

113

// Skip installation

114

await packageManagerInstallTask({

115

memFs,

116

packageJsonLocation: "/project/path",

117

adapter,

118

skipInstall: true

119

});

120

```

121

122

### Environment FileSystem Integration

123

124

File system methods available on Environment instances for generator operations.

125

126

```typescript { .api }

127

/**

128

* Watch for package manager install operations

129

* Available on Environment and EnvironmentBase instances

130

* @param options - Watch configuration options

131

*/

132

watchForPackageManagerInstall(options?: any): void;

133

134

/**

135

* Apply transforms to filesystem

136

* Available on Environment and EnvironmentBase instances

137

* @param transformStreams - Transform streams to apply

138

* @param options - Transform options

139

*/

140

applyTransforms(transformStreams: any[], options?: any): Promise<void>;

141

142

/**

143

* Install local generator packages

144

* Available on Environment instances

145

* @param packages - Map of package names to versions

146

* @returns True if installation succeeded

147

*/

148

installLocalGenerators(packages: Record<string, string | undefined>): Promise<boolean>;

149

```

150

151

**Usage Examples:**

152

153

```typescript

154

import { createEnv } from "yeoman-environment";

155

156

const env = createEnv();

157

158

// Watch for package manager operations

159

env.watchForPackageManagerInstall({

160

detectExisting: true,

161

watchGlob: "**/package.json"

162

});

163

164

// Apply file transforms

165

await env.applyTransforms([

166

myTransformStream,

167

anotherTransform

168

], {

169

filter: (file) => file.path.endsWith('.js')

170

});

171

172

// Install local generators

173

const installed = await env.installLocalGenerators({

174

"generator-webapp": "^4.0.1",

175

"generator-node": "latest"

176

});

177

```

178

179

## Conflict Resolution

180

181

The commit process includes sophisticated conflict resolution:

182

183

### Conflict Resolution Options

184

185

```typescript { .api }

186

interface ConflicterOptions {

187

/** Override all existing files without prompting */

188

force?: boolean;

189

/** Fail immediately on first file conflict */

190

bail?: boolean;

191

/** Treat whitespace-only changes as non-conflicts */

192

whitespace?: boolean;

193

/** Skip conflict resolution for .yo-resolve files */

194

skipYoResolve?: boolean;

195

/** Custom conflict resolution adapter */

196

adapter?: InputOutputAdapter;

197

/** Dry run mode - show conflicts without applying */

198

dryRun?: boolean;

199

}

200

```

201

202

### Conflict Resolution Process

203

204

1. **File Scanning**: Identify files that will be modified

205

2. **Existing File Check**: Compare with existing files on disk

206

3. **Conflict Detection**: Detect content differences

207

4. **User Interaction**: Prompt for resolution strategy (if not forced)

208

5. **Resolution Application**: Apply chosen resolution

209

6. **Transform Pipeline**: Apply any configured transforms

210

7. **Disk Commit**: Write final files to disk

211

212

**Conflict Resolution Strategies:**

213

- **Skip**: Keep existing file, don't write new content

214

- **Force**: Overwrite existing file with new content

215

- **Merge**: Attempt automatic merge (if possible)

216

- **Manual**: Open editor for manual conflict resolution

217

218

### File Transform Pipeline

219

220

The commit process supports transform streams for file processing:

221

222

```typescript

223

import { transform } from "@yeoman/transform";

224

225

// Example transform usage

226

await env.applyTransforms([

227

// Prettier formatting

228

transform.prettierTransform(),

229

230

// ESLint fixing

231

transform.eslintTransform(),

232

233

// Custom transform

234

transform((file) => {

235

if (file.path.endsWith('.js')) {

236

file.contents = Buffer.from(

237

file.contents.toString().replace(/var /g, 'const ')

238

);

239

}

240

return file;

241

})

242

]);

243

```

244

245

## Package Manager Detection

246

247

The package manager installation system automatically detects the preferred package manager:

248

249

### Detection Priority

250

251

1. **Explicit Option**: `nodePackageManager` option

252

2. **Lock Files**: Presence of `yarn.lock`, `pnpm-lock.yaml`, etc.

253

3. **Environment Variables**: `npm_config_user_agent`

254

4. **Fallback**: npm (default)

255

256

### Supported Package Managers

257

258

- **npm**: Default Node.js package manager

259

- **yarn**: Yarn package manager (v1 and v2+)

260

- **pnpm**: Fast, disk space efficient package manager

261

- **bun**: Fast all-in-one JavaScript runtime (if detected)

262

263

**Custom Package Manager Example:**

264

265

```typescript

266

await packageManagerInstallTask({

267

memFs,

268

packageJsonLocation: "/project",

269

adapter,

270

customInstallTask: async (detectedPM, defaultTask) => {

271

if (detectedPM === "bun") {

272

// Custom bun installation

273

const { execa } = await import("execa");

274

await execa("bun", ["install"], { cwd: "/project" });

275

} else {

276

// Use default task for other package managers

277

await defaultTask();

278

}

279

}

280

});

281

```

282

283

## Advanced FileSystem Operations

284

285

### Memory FileSystem Integration

286

287

```typescript

288

import { create as createMemFs } from "mem-fs";

289

import { create as createEditor } from "mem-fs-editor";

290

291

// Create and configure memory filesystem

292

const memFs = createMemFs();

293

const editor = createEditor(memFs);

294

295

// Write files to memory filesystem

296

editor.write("/project/src/index.js", "console.log('Hello!');");

297

editor.copyTpl("/templates/component.js", "/project/src/component.js", {

298

name: "MyComponent"

299

});

300

301

// Commit to disk

302

await commitSharedFsTask({

303

adapter: myAdapter,

304

sharedFs: memFs,

305

conflicterOptions: { force: false }

306

});

307

```

308

309

### File State Management

310

311

```typescript { .api }

312

// File states in memory filesystem

313

interface MemFsEditorFile {

314

/** File path */

315

path: string;

316

/** File contents */

317

contents: Buffer | null;

318

/** File state (created, modified, deleted, etc.) */

319

state?: string;

320

/** File history */

321

history?: string[];

322

}

323

```

324

325

**File State Checking:**

326

327

```typescript

328

import { isFilePending } from "mem-fs-editor/state";

329

330

// Check if file has pending changes

331

const file = memFs.get("/project/src/index.js");

332

if (isFilePending(file)) {

333

console.log("File has pending changes");

334

}

335

```

336

337

## Error Handling

338

339

### Installation Errors

340

341

```typescript

342

try {

343

const success = await packageManagerInstallTask({

344

memFs,

345

packageJsonLocation: "/project",

346

adapter

347

});

348

349

if (!success) {

350

console.log("Installation failed but did not throw");

351

}

352

} catch (error) {

353

console.error("Installation error:", error.message);

354

355

// Handle specific error types

356

if (error.code === "ENOENT") {

357

console.error("package.json not found");

358

} else if (error.code === "EACCES") {

359

console.error("Permission denied");

360

}

361

}

362

```

363

364

### Commit Errors

365

366

```typescript

367

try {

368

await commitSharedFsTask({

369

adapter,

370

sharedFs: memFs,

371

conflicterOptions: { bail: true }

372

});

373

} catch (error) {

374

if (error.message.includes("conflict")) {

375

console.error("File conflict detected:", error.filePath);

376

} else if (error.code === "EPERM") {

377

console.error("Permission error writing file");

378

}

379

}

380

```