@aws/nx-plugin-mcp 0.120.0 → 0.121.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/aws-nx-mcp.js +23 -35
- package/docs/guides/astro-docs.mdx +142 -0
- package/docs/guides/connection/py-agent-a2a.mdx +105 -0
- package/docs/guides/connection/py-agent-mcp.mdx +147 -0
- package/docs/guides/connection/react-agui.mdx +240 -0
- package/docs/guides/connection/react-fastapi.mdx +1476 -0
- package/docs/guides/connection/react-py-agent.mdx +198 -0
- package/docs/guides/connection/react-smithy.mdx +1355 -0
- package/docs/guides/connection/react-trpc.mdx +447 -0
- package/docs/guides/connection/react-ts-agent.mdx +198 -0
- package/docs/guides/connection/smithy-rdb.mdx +161 -0
- package/docs/guides/connection/trpc-rdb.mdx +127 -0
- package/docs/guides/connection/ts-agent-a2a.mdx +106 -0
- package/docs/guides/connection/ts-agent-mcp.mdx +144 -0
- package/docs/guides/connection/ts-agent-rdb.mdx +141 -0
- package/docs/guides/connection/ts-mcp-server-rdb.mdx +135 -0
- package/docs/guides/connection.mdx +126 -0
- package/docs/guides/docker-bundling.mdx +403 -0
- package/docs/guides/fastapi.mdx +509 -0
- package/docs/guides/license.mdx +293 -0
- package/docs/guides/nx-generator.mdx +588 -0
- package/docs/guides/py-agent.mdx +483 -0
- package/docs/guides/py-mcp-server.mdx +161 -0
- package/docs/guides/python-lambda-function.mdx +207 -0
- package/docs/guides/python-project.mdx +228 -0
- package/docs/guides/react-website-auth.mdx +216 -0
- package/docs/guides/react-website.mdx +421 -0
- package/docs/guides/runtime-config.mdx +312 -0
- package/docs/guides/terraform-project.mdx +317 -0
- package/docs/guides/trpc.mdx +816 -0
- package/docs/guides/ts-agent.mdx +436 -0
- package/docs/guides/ts-lambda-function.mdx +218 -0
- package/docs/guides/ts-mcp-server.mdx +169 -0
- package/docs/guides/ts-nx-plugin.mdx +159 -0
- package/docs/guides/ts-rdb.mdx +759 -0
- package/docs/guides/ts-smithy-api.mdx +661 -0
- package/docs/guides/typescript-infrastructure.mdx +408 -0
- package/docs/guides/typescript-project.mdx +312 -0
- package/docs/guides/workspace.mdx +181 -0
- package/docs/snippets/agent/architecture.mdx +72 -0
- package/docs/snippets/agent/bedrock-deployment.mdx +172 -0
- package/docs/snippets/agent/runtime-arn.mdx +64 -0
- package/docs/snippets/api/api-architecture.mdx +93 -0
- package/docs/snippets/api/api-choice-note.mdx +6 -0
- package/docs/snippets/api/cors-configuration-cdk-note.mdx +25 -0
- package/docs/snippets/api/cors-configuration-terraform-note.mdx +28 -0
- package/docs/snippets/api/shared-constructs.mdx +38 -0
- package/docs/snippets/api/type-safe-api-integrations.mdx +643 -0
- package/docs/snippets/api/waf-configuration.mdx +37 -0
- package/docs/snippets/connection/a2a-infrastructure.mdx +63 -0
- package/docs/snippets/connection/lambda-rdb-ssl-requirements.mdx +40 -0
- package/docs/snippets/connection/mcp-server-rdb-ssl-requirements.mdx +35 -0
- package/docs/snippets/connection/rdb-api-infrastructure.mdx +72 -0
- package/docs/snippets/connection/react-agent-infrastructure.mdx +61 -0
- package/docs/snippets/connection/strands-agent-rdb-ssl-requirements.mdx +35 -0
- package/docs/snippets/lambda-function/architecture.mdx +36 -0
- package/docs/snippets/lambda-function/deploying-your-function.mdx +118 -0
- package/docs/snippets/mcp/architecture.mdx +58 -0
- package/docs/snippets/mcp/assistant-docs.mdx +10 -0
- package/docs/snippets/mcp/bedrock-deployment.mdx +167 -0
- package/docs/snippets/mcp/config.mdx +13 -0
- package/docs/snippets/mcp/configuration-py.mdx +42 -0
- package/docs/snippets/mcp/configuration-ts.mdx +53 -0
- package/docs/snippets/mcp/observability.mdx +8 -0
- package/docs/snippets/mcp/shared-constructs.mdx +32 -0
- package/docs/snippets/pdk-migration/example/01-migrate-api.mdx +602 -0
- package/docs/snippets/pdk-migration/example/02-migrate-website.mdx +915 -0
- package/docs/snippets/pdk-migration/example/03-migrate-infra.mdx +161 -0
- package/docs/snippets/pdk-migration/example/04-deploy.mdx +229 -0
- package/docs/snippets/pdk-migration/faq/aws-arch.mdx +17 -0
- package/docs/snippets/pdk-migration/faq/cdk-graph.mdx +29 -0
- package/docs/snippets/pdk-migration/faq/infrastructure-python-java.mdx +19 -0
- package/docs/snippets/pdk-migration/faq/pdk-nag.mdx +15 -0
- package/docs/snippets/pdk-migration/faq/pipeline.mdx +15 -0
- package/docs/snippets/pdk-migration/faq/type-safe-api.mdx +310 -0
- package/docs/snippets/pdk-migration/faq/use-of-projen.mdx +15 -0
- package/docs/snippets/prerequisites.mdx +20 -0
- package/docs/snippets/required-prerequisites.mdx +12 -0
- package/docs/snippets/shared-constructs.mdx +40 -0
- package/docs/snippets/tools/acurl.mdx +73 -0
- package/docs/snippets/ts-bundle.mdx +14 -0
- package/package.json +1 -1
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Nx Generator Generator
|
|
3
|
+
description: Generates an Nx Generator
|
|
4
|
+
generator: ts#nx-generator
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
import { FileTree } from '@astrojs/starlight/components';
|
|
8
|
+
import RunGenerator from '@components/run-generator.astro';
|
|
9
|
+
import NxCommands from '@components/nx-commands.astro';
|
|
10
|
+
import GeneratorParameters from '@components/generator-parameters.astro';
|
|
11
|
+
import Drawer from '@components/drawer.astro';
|
|
12
|
+
import Link from '@components/link.astro';
|
|
13
|
+
|
|
14
|
+
Adds an [Nx Generator](https://nx.dev/recipes/generators/local-generators) to a TypeScript project, to help you automate repetitive tasks such as scaffolding components or enforcing particular project structures.
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
### Generate a Generator
|
|
19
|
+
|
|
20
|
+
You can generate a generator in two ways:
|
|
21
|
+
|
|
22
|
+
<RunGenerator generator="ts#nx-generator" />
|
|
23
|
+
|
|
24
|
+
:::tip[Recommended Setup]
|
|
25
|
+
We recommend using the <Link path="/guides/ts-nx-plugin">`ts#nx-plugin`</Link> generator as the base project for any generators you create, since it also provides an MCP Server which helps AI to use your generators.
|
|
26
|
+
:::
|
|
27
|
+
|
|
28
|
+
### Options
|
|
29
|
+
|
|
30
|
+
<GeneratorParameters generator="ts#nx-generator" />
|
|
31
|
+
|
|
32
|
+
## Generator Output
|
|
33
|
+
|
|
34
|
+
The generator will create the following project files within the given `project`:
|
|
35
|
+
|
|
36
|
+
<FileTree>
|
|
37
|
+
- src/\<name>/
|
|
38
|
+
- schema.json Schema for input to your generator
|
|
39
|
+
- schema.d.ts TypeScript types for your schema
|
|
40
|
+
- generator.ts Stub generator implementation
|
|
41
|
+
- generator.spec.ts Tests for your generator
|
|
42
|
+
- README.md Documentation for your generator
|
|
43
|
+
- generators.json Nx configuration to define your generators
|
|
44
|
+
- package.json Created or updated to add a "generators" entry
|
|
45
|
+
- tsconfig.json Updated to use CommonJS
|
|
46
|
+
</FileTree>
|
|
47
|
+
|
|
48
|
+
:::warning[Project Modification]
|
|
49
|
+
This generator will update the selected `project` to use CommonJS, as Nx Generators only support CommonJS at present ([refer to this GitHub issue for ESM support](https://github.com/nrwl/nx/issues/15682)).
|
|
50
|
+
:::
|
|
51
|
+
|
|
52
|
+
## Local Generators
|
|
53
|
+
|
|
54
|
+
:::tip[Dedicated Plugin Project]
|
|
55
|
+
We recommend generating a dedicated TypeScript project for all your generators using the `ts#nx-plugin` generator first. For example:
|
|
56
|
+
|
|
57
|
+
<RunGenerator generator="ts#nx-plugin" requiredParameters={{ name: 'nx-plugin', directory: 'tools' }} />
|
|
58
|
+
:::
|
|
59
|
+
|
|
60
|
+
Select your local `nx-plugin` project when running the `ts#nx-generator` generator, and specify a name and optional directory and description.
|
|
61
|
+
|
|
62
|
+
### Defining the Schema
|
|
63
|
+
|
|
64
|
+
The `schema.json` file defines the options that your generator accepts. It follows the [JSON Schema](https://json-schema.org/) format with [Nx-specific extensions](https://nx.dev/extending-nx/recipes/generator-options).
|
|
65
|
+
|
|
66
|
+
#### Basic Structure
|
|
67
|
+
|
|
68
|
+
A schema.json file has the following basic structure:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"$schema": "https://json-schema.org/schema",
|
|
73
|
+
"$id": "YourGeneratorName",
|
|
74
|
+
"title": "Your Generator Title",
|
|
75
|
+
"description": "Description of what your generator does",
|
|
76
|
+
"type": "object",
|
|
77
|
+
"properties": {
|
|
78
|
+
// Your generator options go here
|
|
79
|
+
},
|
|
80
|
+
"required": ["requiredOption1", "requiredOption2"]
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
#### Simple Example
|
|
85
|
+
|
|
86
|
+
Here's a simple example with a few basic options:
|
|
87
|
+
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"$schema": "https://json-schema.org/schema",
|
|
91
|
+
"$id": "ComponentGenerator",
|
|
92
|
+
"title": "Create a Component",
|
|
93
|
+
"description": "Creates a new React component",
|
|
94
|
+
"type": "object",
|
|
95
|
+
"properties": {
|
|
96
|
+
"name": {
|
|
97
|
+
"type": "string",
|
|
98
|
+
"description": "Component name",
|
|
99
|
+
"x-priority": "important"
|
|
100
|
+
},
|
|
101
|
+
"directory": {
|
|
102
|
+
"type": "string",
|
|
103
|
+
"description": "Directory where the component will be created",
|
|
104
|
+
"default": "src/components"
|
|
105
|
+
},
|
|
106
|
+
"withTests": {
|
|
107
|
+
"type": "boolean",
|
|
108
|
+
"description": "Whether to generate test files",
|
|
109
|
+
"default": true
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
"required": ["name"]
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
#### Interactive Prompts (CLI)
|
|
117
|
+
|
|
118
|
+
You can customise the prompts displayed when running your generator via the CLI by adding the `x-prompt` property:
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
"name": {
|
|
122
|
+
"type": "string",
|
|
123
|
+
"description": "Component name",
|
|
124
|
+
"x-prompt": "What is the name of your component?"
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
For boolean options, you can use a yes/no prompt:
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
"withTests": {
|
|
132
|
+
"type": "boolean",
|
|
133
|
+
"description": "Whether to generate test files",
|
|
134
|
+
"x-prompt": "Would you like to generate test files?"
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
#### Dropdown Selections
|
|
139
|
+
|
|
140
|
+
For options with a fixed set of choices, use `enum` so that users can select from one of the options.
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
"style": {
|
|
144
|
+
"type": "string",
|
|
145
|
+
"description": "The styling approach to use",
|
|
146
|
+
"enum": ["css", "scss", "styled-components", "none"],
|
|
147
|
+
"default": "css"
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
#### Project Selection Dropdown
|
|
152
|
+
|
|
153
|
+
A common pattern is to let users select from existing projects in the workspace:
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
"project": {
|
|
157
|
+
"type": "string",
|
|
158
|
+
"description": "The project to add the component to",
|
|
159
|
+
"x-prompt": "Which project would you like to add the component to?",
|
|
160
|
+
"x-dropdown": "projects"
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The `x-dropdown: "projects"` property tells Nx to populate the dropdown with all projects in the workspace.
|
|
165
|
+
|
|
166
|
+
#### Positional Arguments
|
|
167
|
+
|
|
168
|
+
You can configure options to be passed as positional arguments when running the generator from the command line:
|
|
169
|
+
|
|
170
|
+
```json
|
|
171
|
+
"name": {
|
|
172
|
+
"type": "string",
|
|
173
|
+
"description": "Component name",
|
|
174
|
+
"x-priority": "important",
|
|
175
|
+
"$default": {
|
|
176
|
+
"$source": "argv",
|
|
177
|
+
"index": 0
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
This allows users to run your generator like `nx g your-generator my-component` instead of `nx g your-generator --name=my-component`.
|
|
183
|
+
|
|
184
|
+
#### Setting Priorities
|
|
185
|
+
|
|
186
|
+
Use the `x-priority` property to indicate which options are most important:
|
|
187
|
+
|
|
188
|
+
```json
|
|
189
|
+
"name": {
|
|
190
|
+
"type": "string",
|
|
191
|
+
"description": "Component name",
|
|
192
|
+
"x-priority": "important"
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Options can have priorities of `"important"` or `"internal"`. This helps Nx to order properties in the Nx VSCode extension and Nx CLI.
|
|
197
|
+
|
|
198
|
+
#### Default Values
|
|
199
|
+
|
|
200
|
+
You can provide default values for options:
|
|
201
|
+
|
|
202
|
+
```json
|
|
203
|
+
"directory": {
|
|
204
|
+
"type": "string",
|
|
205
|
+
"description": "Directory where the component will be created",
|
|
206
|
+
"default": "src/components"
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
#### More Information
|
|
211
|
+
|
|
212
|
+
For more details on schemas, refer to the [Nx Generator Options documentation](https://nx.dev/extending-nx/recipes/generator-options).
|
|
213
|
+
|
|
214
|
+
#### TypeScript Types with schema.d.ts
|
|
215
|
+
|
|
216
|
+
Along with `schema.json`, the generator creates a `schema.d.ts` file that provides TypeScript types for your generator options:
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
export interface YourGeneratorSchema {
|
|
220
|
+
name: string;
|
|
221
|
+
directory?: string;
|
|
222
|
+
withTests?: boolean;
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
This interface is used in your generator implementation to provide type safety and code completion:
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
import { YourGeneratorSchema } from './schema';
|
|
230
|
+
|
|
231
|
+
export default async function (tree: Tree, options: YourGeneratorSchema) {
|
|
232
|
+
// TypeScript knows the types of all your options
|
|
233
|
+
const { name, directory = 'src/components', withTests = true } = options;
|
|
234
|
+
// ...
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
:::caution[Schema Changes]
|
|
239
|
+
Whenever you modify `schema.json`, you must update `schema.d.ts` to match. This includes:
|
|
240
|
+
|
|
241
|
+
- Adding or removing properties
|
|
242
|
+
- Changing property types
|
|
243
|
+
- Making properties required or optional (use the `?` suffix for optional properties)
|
|
244
|
+
|
|
245
|
+
The TypeScript interface should accurately reflect the structure defined in your JSON schema.
|
|
246
|
+
:::
|
|
247
|
+
|
|
248
|
+
### Implementing a Generator
|
|
249
|
+
|
|
250
|
+
After creating the new generator as above, you can write your implementation in `generator.ts`.
|
|
251
|
+
|
|
252
|
+
A generator is a function which mutates a virtual filesystem (the `Tree`), reading and writing files to make the desired changes. Changes from the `Tree` are only written to disk once the generator finishes executing, unless it is run in "dry-run" mode. An empty generator looks as follows:
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
export const myGenerator = async (tree: Tree, options: MyGeneratorSchema) => {
|
|
256
|
+
// Use the tree to apply changes
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
export default myGenerator;
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Here are some common operations you might want to perform in your generator:
|
|
263
|
+
|
|
264
|
+
#### Reading and Writing Files
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
// Read a file
|
|
268
|
+
const content = tree.read('path/to/file.ts', 'utf-8');
|
|
269
|
+
|
|
270
|
+
// Write a file
|
|
271
|
+
tree.write('path/to/new-file.ts', 'export const hello = "world";');
|
|
272
|
+
|
|
273
|
+
// Check if a file exists
|
|
274
|
+
if (tree.exists('path/to/file.ts')) {
|
|
275
|
+
// Do something
|
|
276
|
+
}
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
#### Generating Files from Templates
|
|
280
|
+
|
|
281
|
+
You can generate files with the `generateFiles` utility from `@nx/devkit`. This allows you to define templates in [EJS](https://ejs.co/) syntax, and substitute variables.
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
import { generateFiles, joinPathFragments } from '@nx/devkit';
|
|
285
|
+
|
|
286
|
+
// Generate files from templates
|
|
287
|
+
generateFiles(
|
|
288
|
+
tree,
|
|
289
|
+
joinPathFragments(__dirname, 'files'), // Template directory
|
|
290
|
+
'path/to/output', // Output directory
|
|
291
|
+
{
|
|
292
|
+
// Variables to replace in templates
|
|
293
|
+
name: options.name,
|
|
294
|
+
nameCamelCase: camelCase(options.name),
|
|
295
|
+
nameKebabCase: kebabCase(options.name),
|
|
296
|
+
// Add more variables as needed
|
|
297
|
+
},
|
|
298
|
+
);
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
#### Code Transforms with GritQL
|
|
302
|
+
|
|
303
|
+
You can use [GritQL](https://docs.grit.io/) to declaratively search and transform source code in your generators. GritQL supports multiple languages including TypeScript, JavaScript, Python, HCL (Terraform), and more — so you can use the same pattern syntax across your entire stack.
|
|
304
|
+
|
|
305
|
+
The Nx Plugin for AWS exposes two helpers:
|
|
306
|
+
|
|
307
|
+
- `applyGritQL(tree, filePath, pattern)` — applies a GritQL rewrite pattern to a file and returns `Promise<boolean>` indicating whether changes were made
|
|
308
|
+
- `matchGritQL(tree, filePath, pattern)` — checks whether a GritQL pattern matches anywhere in a file and returns `Promise<boolean>`
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
import { applyGritQL, matchGritQL } from '@aws/nx-plugin/sdk/utils/ast';
|
|
312
|
+
|
|
313
|
+
// Replace a function call
|
|
314
|
+
await applyGritQL(
|
|
315
|
+
tree,
|
|
316
|
+
'src/app.ts',
|
|
317
|
+
'`console.log($msg)` => `logger.info($msg)`',
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
// Add an element to an array only if not already present
|
|
321
|
+
await applyGritQL(
|
|
322
|
+
tree,
|
|
323
|
+
'src/plugins.ts',
|
|
324
|
+
'`plugins: [$items]` => `plugins: [$items, myPlugin()]` where { $items <: not contains `myPlugin` }',
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
// Check if a pattern exists before making changes
|
|
328
|
+
if (!(await matchGritQL(tree, filePath, '`import { Auth } from "./auth"`'))) {
|
|
329
|
+
// Add the import
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
GritQL patterns also work on non-TypeScript files. Prefix your pattern with `language <name>` to target other languages:
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
// Python: replace print statements with logging calls
|
|
337
|
+
await applyGritQL(
|
|
338
|
+
tree,
|
|
339
|
+
'src/handler.py',
|
|
340
|
+
'language python\n`print($msg)` => `logger.info($msg)`',
|
|
341
|
+
);
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
GritQL patterns use backtick-delimited code snippets with `$metavariables` as wildcards. Use `=>` for rewrites and `where` clauses for conditions.
|
|
345
|
+
|
|
346
|
+
:::tip[GritQL Playground]
|
|
347
|
+
You can try out GritQL patterns in the [GritQL Playground](https://docs.grit.io/playground), or install the GritQL CLI locally to test patterns against your files:
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
npm install -g @getgrit/cli
|
|
351
|
+
grit apply '`console.log($msg)` => `logger.info($msg)`' --dry-run
|
|
352
|
+
```
|
|
353
|
+
:::
|
|
354
|
+
|
|
355
|
+
:::tip[AI Coding Agents]
|
|
356
|
+
If you use an AI coding agent to help write generators, add the [Context7 MCP server](https://context7.com/) to give it up-to-date documentation. Prompt it to look up `gritql` and `docs.grit.io` for GritQL pattern syntax reference, and provide access to the GritQL CLI so it can test patterns directly.
|
|
357
|
+
:::
|
|
358
|
+
|
|
359
|
+
#### Adding Dependencies
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
import { addDependenciesToPackageJson } from '@nx/devkit';
|
|
363
|
+
|
|
364
|
+
// Add dependencies to package.json
|
|
365
|
+
addDependenciesToPackageJson(
|
|
366
|
+
tree,
|
|
367
|
+
{
|
|
368
|
+
'new-dependency': '^1.0.0',
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
'new-dev-dependency': '^2.0.0',
|
|
372
|
+
},
|
|
373
|
+
);
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
:::note[Package Dependencies]
|
|
377
|
+
If you add dependencies to a package.json, you can then install them for the user as part of the generator callback:
|
|
378
|
+
|
|
379
|
+
```ts
|
|
380
|
+
import { installPackagesTask } from '@nx/devkit';
|
|
381
|
+
|
|
382
|
+
// Generators return a callback which can run any post-generation tasks, such as installing dependencies
|
|
383
|
+
return () => {
|
|
384
|
+
installPackagesTask(tree);
|
|
385
|
+
};
|
|
386
|
+
```
|
|
387
|
+
:::
|
|
388
|
+
|
|
389
|
+
#### Formatting Generated Files
|
|
390
|
+
|
|
391
|
+
```typescript
|
|
392
|
+
import { formatFilesInSubtree } from '@aws/nx-plugin/sdk/utils/format';
|
|
393
|
+
|
|
394
|
+
// Format all files that were modified
|
|
395
|
+
await formatFilesInSubtree(tree, 'optional/path/to/format');
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
#### Reading and Updating JSON Files
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
import { readJson, updateJson } from '@nx/devkit';
|
|
402
|
+
|
|
403
|
+
// Read a JSON file
|
|
404
|
+
const packageJson = readJson(tree, 'package.json');
|
|
405
|
+
|
|
406
|
+
// Update a JSON file
|
|
407
|
+
updateJson(tree, 'tsconfig.json', (json) => {
|
|
408
|
+
json.compilerOptions = {
|
|
409
|
+
...json.compilerOptions,
|
|
410
|
+
strict: true,
|
|
411
|
+
};
|
|
412
|
+
return json;
|
|
413
|
+
});
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
#### Extending a Generator from the Nx Plugin for AWS
|
|
417
|
+
|
|
418
|
+
You can import generators from the Nx Plugin for AWS, and extend or compose them as you wish, for example you might wish to create a generator which builds on top of a TypeScript project:
|
|
419
|
+
|
|
420
|
+
```ts
|
|
421
|
+
import { tsProjectGenerator } from '@aws/nx-plugin/sdk/ts';
|
|
422
|
+
|
|
423
|
+
export const myGenerator = async (tree: Tree, schema: MyGeneratorSchema) => {
|
|
424
|
+
const callback = await tsProjectGenerator(tree, { ... });
|
|
425
|
+
|
|
426
|
+
// Extend the TypeScript project generator here
|
|
427
|
+
|
|
428
|
+
// Return the callback to ensure dependencies are installed.
|
|
429
|
+
// You can wrap the callback if you wish to perform additional operations in the generator callback.
|
|
430
|
+
return callback;
|
|
431
|
+
};
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
#### OpenAPI Generators
|
|
435
|
+
|
|
436
|
+
You can use and extend the generators we use for TypeScript clients and hooks in a similar way to the above:
|
|
437
|
+
|
|
438
|
+
```ts
|
|
439
|
+
import { openApiTsClientGenerator } from '@aws/nx-plugin/sdk/open-api';
|
|
440
|
+
|
|
441
|
+
export const myGenerator = async (tree: Tree, schema: MyGeneratorSchema) => {
|
|
442
|
+
await openApiTsClientGenerator(tree, { ... });
|
|
443
|
+
|
|
444
|
+
// Add additional files here
|
|
445
|
+
};
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
We also expose a method which allows you to build a data structure that can be used to iterate over operations in an OpenAPI specification and therefore instrument your own code generation, for example:
|
|
449
|
+
|
|
450
|
+
```ts
|
|
451
|
+
import { buildOpenApiCodeGenerationData } from '@aws/nx-plugin/sdk/open-api.js';
|
|
452
|
+
|
|
453
|
+
export const myGenerator = async (tree: Tree, schema: MyGeneratorSchema) => {
|
|
454
|
+
const data = await buildOpenApiCodeGenerationData(tree, 'path/to/spec.json');
|
|
455
|
+
|
|
456
|
+
generateFiles(
|
|
457
|
+
tree,
|
|
458
|
+
joinPathFragments(__dirname, 'files'), // Template directory
|
|
459
|
+
'path/to/output', // Output directory
|
|
460
|
+
data,
|
|
461
|
+
);
|
|
462
|
+
};
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
Which then allows you to write templates such as:
|
|
466
|
+
|
|
467
|
+
```ejs
|
|
468
|
+
// files/my-operations.ts.template
|
|
469
|
+
export const myOperationNames = [
|
|
470
|
+
<%_ allOperations.forEach((op) => { _%>
|
|
471
|
+
'<%- op.name %>',
|
|
472
|
+
<%_ }); _%>
|
|
473
|
+
];
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
Refer to the [codebase on GitHub](https://github.com/awslabs/nx-plugin-for-aws/) for more complex example templates.
|
|
477
|
+
|
|
478
|
+
### Running Your Generator
|
|
479
|
+
|
|
480
|
+
You can run your generator in two ways:
|
|
481
|
+
|
|
482
|
+
<RunGenerator namespace="@my-project/nx-plugin" generator="my-generator" />
|
|
483
|
+
|
|
484
|
+
:::note[Generator Not Showing]
|
|
485
|
+
If you don't see your generator in the VSCode plugin UI, you can refresh your Nx Workspace with:
|
|
486
|
+
|
|
487
|
+
<NxCommands commands={['reset']} />
|
|
488
|
+
:::
|
|
489
|
+
|
|
490
|
+
### Testing Your Generator
|
|
491
|
+
|
|
492
|
+
Unit tests for generators are straightforward to implement. Here's a typical pattern:
|
|
493
|
+
|
|
494
|
+
```typescript
|
|
495
|
+
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
|
496
|
+
import { yourGenerator } from './generator';
|
|
497
|
+
|
|
498
|
+
describe('your generator', () => {
|
|
499
|
+
let tree;
|
|
500
|
+
|
|
501
|
+
beforeEach(() => {
|
|
502
|
+
// Create an empty workspace tree
|
|
503
|
+
tree = createTreeWithEmptyWorkspace();
|
|
504
|
+
|
|
505
|
+
// Add any files that should already exist in the tree
|
|
506
|
+
tree.write(
|
|
507
|
+
'project.json',
|
|
508
|
+
JSON.stringify({
|
|
509
|
+
name: 'test-project',
|
|
510
|
+
sourceRoot: 'src',
|
|
511
|
+
}),
|
|
512
|
+
);
|
|
513
|
+
|
|
514
|
+
tree.write('src/existing-file.ts', 'export const existing = true;');
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
it('should generate expected files', async () => {
|
|
518
|
+
// Run the generator
|
|
519
|
+
await yourGenerator(tree, {
|
|
520
|
+
name: 'test',
|
|
521
|
+
// Add other required options
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
// Check that files were created
|
|
525
|
+
expect(tree.exists('src/test/file.ts')).toBeTruthy();
|
|
526
|
+
|
|
527
|
+
// Check file content
|
|
528
|
+
const content = tree.read('src/test/file.ts', 'utf-8');
|
|
529
|
+
expect(content).toContain('export const test');
|
|
530
|
+
|
|
531
|
+
// You can also use snapshots
|
|
532
|
+
expect(tree.read('src/test/file.ts', 'utf-8')).toMatchSnapshot();
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
it('should update existing files', async () => {
|
|
536
|
+
// Run the generator
|
|
537
|
+
await yourGenerator(tree, {
|
|
538
|
+
name: 'test',
|
|
539
|
+
// Add other required options
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
// Check that existing files were updated
|
|
543
|
+
const content = tree.read('src/existing-file.ts', 'utf-8');
|
|
544
|
+
expect(content).toContain('import { test } from');
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
it('should handle errors', async () => {
|
|
548
|
+
// Expect the generator to throw an error in certain conditions
|
|
549
|
+
await expect(
|
|
550
|
+
yourGenerator(tree, {
|
|
551
|
+
name: 'invalid',
|
|
552
|
+
// Add options that should cause an error
|
|
553
|
+
}),
|
|
554
|
+
).rejects.toThrow('Expected error message');
|
|
555
|
+
});
|
|
556
|
+
});
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
Key points for testing generators:
|
|
560
|
+
|
|
561
|
+
- Use `createTreeWithEmptyWorkspace()` to create a virtual file system
|
|
562
|
+
- Set up any prerequisite files before running the generator
|
|
563
|
+
- Test both the creation of new files and updates to existing files
|
|
564
|
+
- Use snapshots for complex file content
|
|
565
|
+
- Test error conditions to ensure your generator fails gracefully
|
|
566
|
+
|
|
567
|
+
## Contributing Generators to @aws/nx-plugin
|
|
568
|
+
|
|
569
|
+
You can also use `ts#nx-generator` to scaffold a generator within `@aws/nx-plugin`.
|
|
570
|
+
|
|
571
|
+
When this generator is run in our repository, it'll generate the following files for you:
|
|
572
|
+
|
|
573
|
+
<FileTree>
|
|
574
|
+
- packages/nx-plugin/src/\<name>/
|
|
575
|
+
- schema.json Schema for input to your generator
|
|
576
|
+
- schema.d.ts TypeScript types for your schema
|
|
577
|
+
- generator.ts Generator implementation
|
|
578
|
+
- generator.spec.ts Tests for your generator
|
|
579
|
+
- docs/src/content/docs/guides/
|
|
580
|
+
- \<name>.mdx Documentation page for your generator
|
|
581
|
+
- packages/nx-plugin/generators.json Updated to include your generator
|
|
582
|
+
</FileTree>
|
|
583
|
+
|
|
584
|
+
You can then start to implement your generator.
|
|
585
|
+
|
|
586
|
+
:::tip[Contributing Generators]
|
|
587
|
+
For a more in-depth guide regarding contributing to the Nx Plugin for AWS, please refer to the <Link path="get_started/tutorials/contribute-generator">tutorial here</Link>.
|
|
588
|
+
:::
|