or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-usage.mdcodemods.mdconfiguration.mdindex.mdlanguage-server.mdprogrammatic-api.md

codemods.mddocs/

0

# Codemods

1

2

Relay Compiler includes automated code transformation tools (codemods) for migrating and improving Relay codebases with built-in safety controls and rollout mechanisms.

3

4

## Running Codemods

5

6

```bash

7

{ .api }

8

relay-compiler codemod <CODEMOD> [OPTIONS]

9

```

10

11

### Global Options

12

13

```bash

14

{ .api }

15

--project, -p <PROJECT> # Target specific projects (repeatable)

16

--config <PATH> # Use specific config file

17

```

18

19

## Available Codemods

20

21

### Mark Dangerous Conditional Fragment Spreads

22

23

Identifies and marks potentially unsafe conditional fragment spreads that could cause runtime errors.

24

25

```bash

26

{ .api }

27

relay-compiler codemod mark-dangerous-conditional-fragment-spreads [OPTIONS]

28

```

29

30

#### Options

31

32

```bash

33

{ .api }

34

--rollout-percentage, -r <PERCENT> # Percentage or range for gradual rollout

35

--project, -p <PROJECT> # Target specific projects

36

--config <PATH> # Use specific config file

37

```

38

39

#### Percentage Formats

40

41

```typescript

42

{ .api }

43

type RolloutPercentage =

44

| string // Single percentage: "50"

45

| string; // Range: "20-30"

46

```

47

48

#### Usage Examples

49

50

```bash

51

# Apply to 50% of applicable files

52

relay-compiler codemod mark-dangerous-conditional-fragment-spreads --rollout-percentage 50

53

54

# Apply to files in a percentage range

55

relay-compiler codemod mark-dangerous-conditional-fragment-spreads -r 20-30

56

57

# Apply to specific project only

58

relay-compiler codemod mark-dangerous-conditional-fragment-spreads --project web

59

60

# Apply with custom config

61

relay-compiler codemod mark-dangerous-conditional-fragment-spreads --config ./custom-relay.config.json

62

63

# Apply to multiple projects

64

relay-compiler codemod mark-dangerous-conditional-fragment-spreads -p web -p mobile

65

```

66

67

#### What It Does

68

69

This codemod identifies conditional fragment spreads that might cause runtime errors due to missing alias information:

70

71

**Before:**

72

```graphql

73

fragment UserProfile on User {

74

name

75

... on AdminUser {

76

adminLevel

77

}

78

... on RegularUser {

79

memberSince

80

}

81

}

82

```

83

84

**After:**

85

```graphql

86

fragment UserProfile on User {

87

name

88

... on AdminUser @__dangerouslyUnaliasedConditional {

89

adminLevel

90

}

91

... on RegularUser @__dangerouslyUnaliasedConditional {

92

memberSince

93

}

94

}

95

```

96

97

The `@__dangerouslyUnaliasedConditional` directive serves as a marker for manual review and potential refactoring.

98

99

### Remove Unnecessary Required Directives

100

101

Removes `@required` directives from fields that are already non-null in the schema, cleaning up redundant code.

102

103

```bash

104

{ .api }

105

relay-compiler codemod remove-unnecessary-required-directives [OPTIONS]

106

```

107

108

#### Options

109

110

```bash

111

{ .api }

112

--project, -p <PROJECT> # Target specific projects

113

--config <PATH> # Use specific config file

114

```

115

116

#### Usage Examples

117

118

```bash

119

# Apply to all projects

120

relay-compiler codemod remove-unnecessary-required-directives

121

122

# Apply to specific project

123

relay-compiler codemod remove-unnecessary-required-directives --project web

124

125

# Apply with custom configuration

126

relay-compiler codemod remove-unnecessary-required-directives --config ./relay.config.json

127

128

# Apply to multiple projects

129

relay-compiler codemod remove-unnecessary-required-directives -p web -p mobile -p admin

130

```

131

132

#### What It Does

133

134

This codemod removes unnecessary `@required` directives from fields that are already non-null according to the GraphQL schema:

135

136

**Before:**

137

```graphql

138

fragment UserInfo on User {

139

id @required(action: LOG) # id is ID! in schema

140

name @required(action: THROW) # name is String! in schema

141

email # email is String? in schema

142

}

143

```

144

145

**After:**

146

```graphql

147

fragment UserInfo on User {

148

id # @required removed - field is already non-null

149

name # @required removed - field is already non-null

150

email # @required preserved - field is nullable

151

}

152

```

153

154

## Rollout Strategy

155

156

### Percentage-based Rollouts

157

158

Codemods support gradual rollouts to minimize risk:

159

160

```typescript

161

{ .api }

162

interface RolloutStrategy {

163

percentage: number; // 0-100

164

range?: [number, number]; // Alternative: range rollout

165

fileSelection: "random" | "deterministic";

166

}

167

```

168

169

**Deterministic Selection**: Files are selected based on a hash of their path, ensuring consistent selection across runs.

170

171

**Random Selection**: Files are selected randomly each time the codemod runs.

172

173

### Project-based Rollouts

174

175

```bash

176

# Start with a small project

177

relay-compiler codemod <CODEMOD> --project small-app

178

179

# Expand to larger projects

180

relay-compiler codemod <CODEMOD> --project web --project mobile

181

182

# Apply to all projects (no --project flag)

183

relay-compiler codemod <CODEMOD>

184

```

185

186

## Safety Mechanisms

187

188

### Dry Run Mode

189

190

All codemods include built-in validation to ensure they only make safe transformations:

191

192

```typescript

193

{ .api }

194

interface CodemodSafety {

195

validateBeforeTransform: boolean; // Validate AST before changes

196

validateAfterTransform: boolean; // Validate AST after changes

197

preserveComments: boolean; // Maintain code comments

198

preserveFormatting: boolean; // Maintain code style

199

}

200

```

201

202

### Backup Recommendations

203

204

Before running codemods on large codebases:

205

206

1. **Commit all changes**: Ensure clean working directory

207

2. **Run tests**: Verify baseline functionality

208

3. **Use version control**: Enable easy rollback

209

4. **Start small**: Test on subset before full rollout

210

211

## Custom Codemods

212

213

While the CLI doesn't expose custom codemod registration, you can use the programmatic API to build custom transformations:

214

215

```rust

216

{ .api }

217

// Codemod trait for custom implementations

218

pub trait Codemod {

219

fn name(&self) -> &'static str;

220

fn description(&self) -> &'static str;

221

fn transform(&self, program: &Program) -> Result<Program, CodemodError>;

222

}

223

224

// Built-in codemod implementations

225

pub struct MarkDangerousConditionalFragmentSpreads {

226

pub rollout_percentage: Option<f32>,

227

}

228

229

pub struct RemoveUnnecessaryRequiredDirectives;

230

```

231

232

### Custom Codemod Example

233

234

```rust

235

use relay_compiler::{Codemod, Program, CodemodError};

236

237

pub struct CustomCodemod;

238

239

impl Codemod for CustomCodemod {

240

fn name(&self) -> &'static str {

241

"custom-transformation"

242

}

243

244

fn description(&self) -> &'static str {

245

"Applies custom transformation logic"

246

}

247

248

fn transform(&self, program: &Program) -> Result<Program, CodemodError> {

249

// Custom transformation logic

250

let mut transformed_program = program.clone();

251

252

// Apply transformations to fragments, operations, etc.

253

// ...

254

255

Ok(transformed_program)

256

}

257

}

258

```

259

260

## Error Handling

261

262

Codemods provide detailed error reporting for various failure scenarios:

263

264

```typescript

265

{ .api }

266

interface CodemodErrors {

267

ParseError: string; // GraphQL parsing failures

268

ValidationError: string; // Schema validation failures

269

TransformationError: string; // Transformation logic failures

270

FileSystemError: string; // File read/write failures

271

ConfigurationError: string; // Invalid configuration

272

}

273

```

274

275

### Common Error Scenarios

276

277

1. **Invalid GraphQL syntax**: Codemod skips malformed files with warning

278

2. **Schema mismatch**: Reports fields not found in schema

279

3. **Permission errors**: File system access issues

280

4. **Configuration errors**: Invalid project names or paths

281

282

## Reporting and Logging

283

284

### Transformation Summary

285

286

After running a codemod, you'll receive a detailed summary:

287

288

```typescript

289

{ .api }

290

interface CodemodSummary {

291

filesProcessed: number; // Total files examined

292

filesTransformed: number; // Files that were modified

293

transformationsApplied: number; // Total number of changes made

294

errors: CodemodError[]; // Any errors encountered

295

warnings: string[]; // Non-fatal issues

296

}

297

```

298

299

### Example Output

300

301

```

302

Codemod: mark-dangerous-conditional-fragment-spreads

303

Rollout: 50% (deterministic selection)

304

Projects: web, mobile

305

306

Files processed: 234

307

Files transformed: 42

308

Transformations applied: 156

309

Errors: 0

310

Warnings: 3

311

312

Warnings:

313

- src/components/UserProfile.js: Fragment already marked (line 23)

314

- src/pages/AdminPanel.js: No conditional spreads found

315

- src/utils/fragments.js: Skipped - not a GraphQL file

316

317

Transformation complete!

318

```

319

320

### Verbose Logging

321

322

Use the `--output verbose` flag for detailed logging:

323

324

```bash

325

relay-compiler codemod mark-dangerous-conditional-fragment-spreads --output verbose --rollout-percentage 25

326

```

327

328

This provides file-by-file transformation details for debugging and verification.

329

330

## Integration with CI/CD

331

332

### Validation Mode

333

334

Run codemods in validation mode to check if transformations are needed without making changes:

335

336

```bash

337

# Check if codemod would make changes (exit code 2 if changes needed)

338

relay-compiler codemod remove-unnecessary-required-directives --validate

339

```

340

341

### Automated Rollouts

342

343

```yaml

344

# GitHub Actions example

345

name: Gradual Codemod Rollout

346

on:

347

schedule:

348

- cron: '0 2 * * MON' # Weekly rollout

349

350

jobs:

351

codemod:

352

runs-on: ubuntu-latest

353

steps:

354

- uses: actions/checkout@v2

355

- run: npm install

356

- run: |

357

# Gradual rollout: increase percentage weekly

358

WEEK=$(date +%U)

359

PERCENTAGE=$((WEEK * 10))

360

if [ $PERCENTAGE -le 100 ]; then

361

relay-compiler codemod mark-dangerous-conditional-fragment-spreads --rollout-percentage $PERCENTAGE

362

fi

363

- run: npm test

364

- run: git add -A && git commit -m "Codemod rollout: ${PERCENTAGE}%" && git push

365

```