0
# Code Generation
1
2
Powerful code generation utilities for creating files from templates, formatting code, and managing project scaffolding with EJS templating support.
3
4
## Capabilities
5
6
### File Generation from Templates
7
8
Generate files and directories from template folders with variable substitution and conditional logic.
9
10
```typescript { .api }
11
/**
12
* Generates a folder of files based on provided templates
13
* Performs template substitutions using EJS and filename replacements
14
* @param tree - File system tree
15
* @param srcFolder - Source template folder (absolute path)
16
* @param target - Target directory relative to workspace root
17
* @param substitutions - Variables for template substitution
18
* @param options - Generation options including overwrite strategy
19
*/
20
function generateFiles(
21
tree: Tree,
22
srcFolder: string,
23
target: string,
24
substitutions: { [k: string]: any },
25
options?: GenerateFilesOptions
26
): void;
27
28
interface GenerateFilesOptions {
29
/** Strategy for handling existing files */
30
overwriteStrategy?: OverwriteStrategy;
31
}
32
33
enum OverwriteStrategy {
34
/** Replace existing files */
35
Overwrite = "overwrite",
36
/** Keep existing files unchanged */
37
KeepExisting = "keepExisting",
38
/** Throw error if file exists */
39
ThrowIfExisting = "throwIfExisting"
40
}
41
```
42
43
**Usage Examples:**
44
45
```typescript
46
import { Tree, generateFiles, OverwriteStrategy } from "@nx/devkit";
47
import * as path from "path";
48
49
export default function myGenerator(tree: Tree, options: { name: string; description?: string }) {
50
// Generate files from templates with substitutions
51
generateFiles(
52
tree,
53
path.join(__dirname, "files"), // Template source folder
54
`libs/${options.name}`, // Target directory
55
{
56
...options,
57
tmpl: "", // Remove __tmpl__ suffix from filenames
58
className: options.name.charAt(0).toUpperCase() + options.name.slice(1),
59
},
60
{
61
overwriteStrategy: OverwriteStrategy.ThrowIfExisting
62
}
63
);
64
}
65
66
// Template structure example:
67
// files/
68
// src/
69
// index.ts__tmpl__
70
// lib/
71
// __name__.ts__tmpl__
72
// README.md__tmpl__
73
// package.json__tmpl__
74
75
// Template file content example (index.ts__tmpl__):
76
/*
77
export * from './lib/<%= name %>';
78
79
// Generated with className: <%= className %>
80
// Description: <%= description || 'No description provided' %>
81
*/
82
```
83
84
### Code Formatting
85
86
Format generated code using Prettier and other formatting tools.
87
88
```typescript { .api }
89
/**
90
* Formats all created or updated files using Prettier
91
* Only formats if Prettier is detected in the workspace
92
* @param tree - File system tree
93
* @param options - Formatting options
94
*/
95
function formatFiles(
96
tree: Tree,
97
options?: {
98
sortRootTsconfigPaths?: boolean;
99
}
100
): Promise<void>;
101
```
102
103
**Usage Examples:**
104
105
```typescript
106
import { Tree, generateFiles, formatFiles } from "@nx/devkit";
107
108
export default async function myGenerator(tree: Tree, options: any) {
109
// Generate files
110
generateFiles(tree, templatePath, targetPath, substitutions);
111
112
// Format all generated files
113
await formatFiles(tree, {
114
sortRootTsconfigPaths: true // Sort paths in tsconfig.json
115
});
116
}
117
```
118
119
### TypeScript to JavaScript Conversion
120
121
Convert TypeScript files to JavaScript and update configurations accordingly.
122
123
```typescript { .api }
124
/**
125
* Rename and transpile TypeScript files to JavaScript
126
* @param tree - File system tree
127
* @param options - Conversion options
128
*/
129
function toJS(tree: Tree, options?: ToJSOptions): void;
130
131
/**
132
* Update TypeScript configurations to allow JavaScript files
133
* @param tree - File system tree
134
* @param options - Configuration options
135
*/
136
function updateTsConfigsToJs(
137
tree: Tree,
138
options: { projectRoot: string }
139
): void;
140
141
interface ToJSOptions {
142
/** Convert all files in the tree */
143
all?: boolean;
144
/** Specific files to convert */
145
files?: string[];
146
}
147
```
148
149
**Usage Examples:**
150
151
```typescript
152
import { Tree, toJS, updateTsConfigsToJs } from "@nx/devkit";
153
154
export default function convertToJs(tree: Tree, options: { projectRoot: string }) {
155
// Convert TypeScript files to JavaScript
156
toJS(tree);
157
158
// Update tsconfig files to allow JS
159
updateTsConfigsToJs(tree, {
160
projectRoot: options.projectRoot
161
});
162
}
163
```
164
165
### Task Management
166
167
Manage and sequence generator callbacks for post-generation tasks.
168
169
```typescript { .api }
170
/**
171
* Run multiple generator callbacks in sequence
172
* @param tasks - Array of callback functions to execute
173
* @returns Combined callback that runs all tasks in order
174
*/
175
function runTasksInSerial(...tasks: GeneratorCallback[]): GeneratorCallback;
176
177
/**
178
* Callback function type returned by generators
179
* Used for post-generation tasks like installing packages
180
*/
181
type GeneratorCallback = () => void | Promise<void>;
182
```
183
184
**Usage Examples:**
185
186
```typescript
187
import {
188
Tree,
189
GeneratorCallback,
190
runTasksInSerial,
191
addDependenciesToPackageJson,
192
installPackagesTask
193
} from "@nx/devkit";
194
195
export default function myGenerator(tree: Tree, options: any): GeneratorCallback {
196
// Generate files...
197
198
// Create multiple tasks
199
const addDepsTask = addDependenciesToPackageJson(
200
tree,
201
{ react: "^18.0.0" },
202
{ "@types/react": "^18.0.0" }
203
);
204
205
const installTask = () => installPackagesTask(tree);
206
207
const customTask = () => {
208
console.log("Running custom post-generation task");
209
};
210
211
// Return combined task that runs in sequence
212
return runTasksInSerial(addDepsTask, installTask, customTask);
213
}
214
```
215
216
### File Processing Utilities
217
218
Utilities for processing files and handling ignored files.
219
220
```typescript { .api }
221
/**
222
* Visit all files that are not ignored by git
223
* @param tree - File system tree
224
* @param dirPath - Directory to visit (defaults to root)
225
* @param visitor - Function called for each non-ignored file
226
*/
227
function visitNotIgnoredFiles(
228
tree: Tree,
229
dirPath?: string,
230
visitor: (path: string) => void
231
): void;
232
```
233
234
**Usage Examples:**
235
236
```typescript
237
import { Tree, visitNotIgnoredFiles } from "@nx/devkit";
238
239
export default function processFiles(tree: Tree) {
240
// Process all non-ignored TypeScript files
241
visitNotIgnoredFiles(tree, "src", (filePath) => {
242
if (filePath.endsWith(".ts") && !filePath.endsWith(".spec.ts")) {
243
const content = tree.read(filePath, "utf-8");
244
// Process the file content
245
const processedContent = content.replace(/old-pattern/g, "new-pattern");
246
tree.write(filePath, processedContent);
247
}
248
});
249
}
250
```
251
252
## Generator Types
253
254
### Core Generator Interface
255
256
```typescript { .api }
257
/**
258
* Generator function signature
259
* Can return void, a callback, or a promise of either
260
*/
261
type Generator<T = any> = (
262
tree: Tree,
263
schema: T
264
) => void | GeneratorCallback | Promise<void | GeneratorCallback>;
265
266
/**
267
* Migration function signature for updating existing code
268
*/
269
type Migration<T = any> = (
270
tree: Tree,
271
schema: T
272
) => void | GeneratorCallback | Promise<void | GeneratorCallback>;
273
274
/**
275
* Schema definition for generators.json
276
*/
277
interface GeneratorsJson {
278
generators?: Record<string, GeneratorDescription>;
279
schematics?: Record<string, GeneratorDescription>; // Legacy support
280
}
281
282
interface GeneratorDescription {
283
/** Path to the generator implementation */
284
implementation?: string;
285
/** Path to the schema JSON file */
286
schema?: string;
287
/** Aliases for the generator */
288
aliases?: string[];
289
/** Whether generator is hidden from help */
290
hidden?: boolean;
291
/** Description of the generator */
292
description?: string;
293
}
294
```
295
296
### Template Substitution
297
298
The `generateFiles` function supports EJS templating with these features:
299
300
**Filename Substitution:**
301
- `__name__` → replaced with `substitutions.name`
302
- `__className__` → replaced with `substitutions.className`
303
- `__tmpl__` → removed (use `tmpl: ""` in substitutions)
304
305
**Content Substitution:**
306
- `<%= variable %>` → outputs variable value
307
- `<%- variable %>` → outputs unescaped variable value
308
- `<% if (condition) { %>...content...<% } %>` → conditional content
309
- `<% for (item of items) { %>...content...<% } %>` → loops
310
311
**Advanced Usage Examples:**
312
313
```typescript
314
// Template file: __name__.service.ts__tmpl__
315
/*
316
<% if (type === 'api') { %>
317
import { Injectable } from '@angular/core';
318
import { HttpClient } from '@angular/common/http';
319
320
@Injectable({
321
providedIn: 'root'
322
})
323
export class <%= className %>Service {
324
constructor(private http: HttpClient) {}
325
326
<% for (method of methods) { %>
327
<%= method.name %>(<%- method.params %>): <%= method.returnType %> {
328
return this.http.<%= method.httpMethod %>('/<%= name %>/<%= method.endpoint %>');
329
}
330
331
<% } %>
332
}
333
<% } else { %>
334
export class <%= className %>Service {
335
// Simple service implementation
336
}
337
<% } %>
338
*/
339
340
// Generator usage:
341
generateFiles(tree, templatePath, targetPath, {
342
name: 'user',
343
className: 'User',
344
type: 'api',
345
methods: [
346
{
347
name: 'getUsers',
348
params: '',
349
returnType: 'Observable<User[]>',
350
httpMethod: 'get',
351
endpoint: 'list'
352
},
353
{
354
name: 'createUser',
355
params: 'user: User',
356
returnType: 'Observable<User>',
357
httpMethod: 'post',
358
endpoint: 'create'
359
}
360
],
361
tmpl: ''
362
});
363
```
364
365
### Framework Integration
366
367
Converting Nx generators for use with other frameworks:
368
369
```typescript { .api }
370
/**
371
* Convert an Nx Generator to Angular Devkit Schematic
372
* @param generator - Nx generator function
373
* @param skipWritingConfigInOldFormat - Skip legacy format
374
* @returns Angular DevKit schematic
375
*/
376
function convertNxGenerator<T = any>(
377
generator: Generator<T>,
378
skipWritingConfigInOldFormat?: boolean
379
): any;
380
```
381
382
**Usage Examples:**
383
384
```typescript
385
import { convertNxGenerator } from "@nx/devkit";
386
387
// Convert Nx generator to Angular schematic
388
const schematic = convertNxGenerator(myNxGenerator);
389
390
// Use in Angular CLI collection
391
export default schematic;
392
```