Create custom Nx generators for SEA-Forge™ to scaffold new bounded contexts, services, or components following the spec-first pipeline.
1
nx g @nx/plugin:generator <generator-name> --project=generators
This creates:
1
2
3
4
5
6
generators/
<generator-name>/
schema.json # Input schema
schema.d.ts # TypeScript types
generator.ts # Implementation
generator.spec.ts # Tests
Edit schema.json to define inputs:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"$schema": "http://json-schema.org/schema",
"id": "<generator-name>",
"title": "<Generator Title>",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name of the item to generate",
"$default": {
"$source": "argv",
"index": 0
}
},
"context": {
"type": "string",
"description": "Bounded context name"
}
},
"required": ["name", "context"]
}
Edit generator.ts:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import { Tree, formatFiles, installPackagesTask } from '@nx/devkit';
import { Schema } from './schema';
export default async function (tree: Tree, options: Schema) {
// 1. Validate inputs
if (!options.name) {
throw new Error('Name is required');
}
// 2. Generate files from templates
generateFiles(
tree,
path.join(__dirname, 'files'),
`libs/${options.context}`,
{
...options,
tmpl: '',
}
);
// 3. Update configuration
await formatFiles(tree);
return () => {
installPackagesTask(tree);
};
}
Create template files in files/ directory:
1
2
3
4
files/
__name__/
__name__.ts__tmpl__
README.md__tmpl__
Template content (uses EJS):
1
2
3
4
5
6
// __name__.ts__tmpl__
export class <%= className %> {
constructor() {
console.log('<%= name %> initialized');
}
}
1
nx g generators:<generator-name> my-feature --context=semantic-core --dry-run
See existing generator:
1
2
3
4
5
# View source
cat generators/bounded-context/generator.ts
# Run generator
nx g generators:bounded-context inventory
What it creates:
libs/inventory/ directory structureproject.json with targets--dry-run firstformatFiles() to apply Prettiernx.json or project.json as needed1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// generator.spec.ts
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { Tree } from '@nx/devkit';
import generator from './generator';
describe('my-generator', () => {
let tree: Tree;
beforeEach(() => {
tree = createTreeWithEmptyWorkspace();
});
it('should generate files', async () => {
await generator(tree, { name: 'test', context: 'semantic-core' });
expect(tree.exists('libs/semantic-core/test/test.ts')).toBeTruthy();
});
});