@department-of-veterans-affairs/generator-vets-website
Version:
Generate a React app for vets-website
336 lines (245 loc) • 9.82 kB
Markdown
> Yeoman generator for applications on VA.gov
## Requirements
- Node.js 22.0.0+
## Installation
The generator is already installed as a `devDependency` of [`vets-website`](https://github.com/department-of-veterans-affairs/vets-website).
## Local Development Setup
If you're working on this generator itself, you'll need to link it locally to test your changes.
### Quick Start (Recommended)
```sh
# From generator-vets-website root:
nvm use # Use Node version from .nvmrc
npm install # Install dependencies
npm run link:vets-website # Link to vets-website for testing
```
This creates a symlink so vets-website uses your local development version.
### Test Your Changes
```sh
# From generator-vets-website root:
npm run generate
```
This runs the generator in vets-website using a compatible `yo` CLI version. Any changes to the generator will be automatically reflected due to the npm link.
> **Why `npm run generate` instead of `yarn new:app`?**
>
> Generator v4.0.0 uses `yeoman-generator@7.x` which requires a compatible version of the `yo` CLI. If vets-website has not yet been updated, its older `yo` version will cause errors like "Cannot add property resolved, object is not extensible". The `npm run generate` command uses the compatible `yo` from this repo's node_modules.
>
> Once vets-website updates its dependencies, you can use `yarn new:app` directly from vets-website.
### Clean Up
```sh
# From generator-vets-website root:
npm run unlink:vets-website
```
### Manual Setup (Alternative)
If you prefer to set up the links manually:
1. **Create global symlink** (from generator-vets-website):
```sh
npm link
```
2. **Link into vets-website** (from vets-website):
```sh
npm link @department-of-veterans-affairs/generator-vets-website
```
3. **Clean up when done**:
```sh
# From vets-website:
npm unlink --no-save @department-of-veterans-affairs/generator-vets-website
# From generator-vets-website:
npm unlink
```
## Available Scripts
| Script | Description |
|--------|-------------|
| `npm test` | Run unit tests (89 tests) |
| `npm run lint` | Run ESLint |
| `npm run e2e` | Run all E2E tests |
| `npm run e2e:dry-run` | Run E2E tests for dry-run modes only |
| `npm run e2e:real` | Run E2E tests with real file generation |
| `npm run link:vets-website` | Link generator to vets-website for local development |
| `npm run unlink:vets-website` | Remove link from vets-website |
| `npm run generate` | Run generator in vets-website (uses compatible yo version) |
### E2E Testing
The E2E test suite validates the generator works correctly end-to-end:
```sh
# Run all E2E tests (unit tests + dry-run + real generation)
npm run e2e
# Run only dry-run E2E tests (no files created)
npm run e2e:dry-run
# Run real file generation tests (creates files in temp directory)
npm run e2e:real
```
**Note:** E2E tests require `vets-website` to be cloned as a sibling directory (`../vets-website`).
## Usage
The generator supports two modes of operation:
### Interactive Mode
```bash
# From vets-website directory
yarn run new:app
```
The generator will guide you through all required information with helpful prompts and validation.
#### Dry Run Interactive Mode
To preview what files would be generated without actually creating them:
```bash
yo @department-of-veterans-affairs/vets-website \
--dry-run-interactive \
--appName="My App" \
--folderName="my-app" \
--entryName="my-app" \
--rootUrl="/my-app" \
--isForm=true
```
This mode:
- Shows what prompts would have been asked if this were a standard interactive run, what defaults would be used, and what would be missing
- Displays a list of files that would be generated
- Does not create any actual files or modify the filesystem
### Non-Interactive Mode
Provide all arguments upfront to skip prompts entirely. **Note:** CLI mode requires explicit values for most fields since it cannot rely on interactive prompts or defaults:
```bash
# From vets-website directory
yo @department-of-veterans-affairs/vets-website \
--force \
--appName="My App" \
--folderName="my-app" \
--entryName="my-app" \
--rootUrl="/my-app" \
--isForm=true \
--slackGroup="@my-group" \
--contentLoc="../vagov-content" \
--formNumber="21P-530" \
--trackingPrefix="burials-530-" \
--respondentBurden="30" \
--ombNumber="2900-0797" \
--expirationDate="12/31/2026" \
--benefitDescription="burial benefits" \
--usesVetsJsonSchema=false \
--usesMinimalHeader=true \
--addToMyVaSip=true \
--templateType="WITH_1_PAGE"
```
Use `--force` option to automatically overwrite existing files without prompting.
#### Dry Run Non-Interactive Mode
To preview what files would be generated without creating them, using predefined arguments. **This mode requires all necessary CLI arguments** since it cannot prompt for missing values:
```bash
yo @department-of-veterans-affairs/vets-website \
--dry-run-non-interactive \
--appName="My App" \
--folderName="my-app" \
--entryName="my-app" \
--rootUrl="/my-app" \
--isForm=true \
--slackGroup="@my-group" \
--contentLoc="../vagov-content" \
--formNumber="21P-530" \
--trackingPrefix="burials-530-" \
--respondentBurden="30" \
--ombNumber="2900-0797" \
--expirationDate="12/31/2026" \
--benefitDescription="burial benefits" \
--usesVetsJsonSchema=false \
--usesMinimalHeader=true \
--addToMyVaSip=true \
--templateType="WITH_1_PAGE"
```
This mode:
- Requires explicit values for all necessary fields (stricter than interactive mode)
- Shows a detailed list of files that would be generated
- Does not create any actual files or modify the filesystem
Use `--force` option to automatically overwrite existing files without prompting.
### Resources
- [Guide on using this Yeoman generator with example answers for each prompt](https://department-of-veterans-affairs.github.io/veteran-facing-services-tools/platform/tools/generator/)
- [Basic tutorial for creating and modifying a form application](https://department-of-veterans-affairs.github.io/veteran-facing-services-tools/forms/form-tutorial-basic)
These resources are also provided by the generator at startup.
### Generator Architecture
For specifics on writing a generator, [refer to the official Yeoman documentation](https://yeoman.github.io/generator/).
## Publishing to npm
When you're ready to publish a new version of the generator to npm:
1. **Ensure you're logged in to npm:**
```sh
npm login
```
You'll need to be added as a maintainer of the `@department-of-veterans-affairs/generator-vets-website` package.
2. **Update the version number:**
```sh
npm version patch # for bug fixes (3.14.1 → 3.14.2)
npm version minor # for new features (3.14.1 → 3.15.0)
npm version major # for breaking changes (3.14.1 → 4.0.0)
```
This will update `package.json` and create a git tag.
3. **Run pre-publish checks:**
```sh
npm run prepublishOnly
```
This runs `npm run prepublishOnly` to check for security vulnerabilities.
4. **Publish to npm:**
```sh
npm publish
```
## Adding New Prompts
If you need to add a new prompt to the generator, follow these steps:
### 1. Define the Field
Add your new field to the field definitions in `lib/prompts.js`:
```javascript
const fieldDefinitions = {
// ... existing fields
myNewField: {
type: 'input',
message: 'What is your new field value?',
validate: (input) => {
if (!input || input.trim() === '') {
return 'This field is required.';
}
return true;
},
filter: (input) => input.trim(),
},
};
```
### 2. Add to Field Groups
Include your field in the appropriate field group(s):
```javascript
const fieldGroups = {
core: ['appName', 'folderName', 'entryName', 'rootUrl', 'isForm', 'myNewField'],
form: ['formNumber', 'ombNumber', 'expirationDate', 'myNewField'],
// ... other groups
};
```
### 3. Add CLI Validation (Optional)
If the field should be available as a CLI argument, add validation in `lib/cli-validation.js`:
```javascript
function validateMyNewField(value) {
if (!value) {
return 'myNewField is required';
}
// Add specific validation logic
return null; // Return null if valid, error string if invalid
}
```
### 4. Update Templates
Use the new field in your templates with EJS syntax:
```html
<!-- In any .ejs template file -->
<div>My new field value: <%= myNewField %></div>
```
### 5. Add to CLI Arguments (Optional)
If you want the field to be available as a command-line argument, add it to the options in `generators/app/index.js`:
```javascript
// This is typically handled automatically by the field definitions,
// but you may need to add custom logic for complex fields
```
### 6. Test Your Changes
1. Link the generator locally: `npm run link:vets-website`
2. Run unit tests: `npm test`
3. Run E2E tests: `npm run e2e`
4. Test manually in vets-website: `yarn new:app`
5. Verify the field appears in prompts and generates correctly in templates
## Node.js Version Migration Notes
### Current State (Node 22+)
This generator requires Node.js 22.0.0+ and uses:
- `yeoman-generator@^7.5.0` (ESM-only, Node 18.17+ required)
- ES Modules throughout the codebase
- All dependencies are compatible with Node 22+
### Migration from v3.x (Node 14)
Version 4.0.0 is a major breaking change that requires Node.js 22+ due to:
1. **ESM Conversion**: All code has been converted from CommonJS to ES Modules
2. **Dependency Upgrades**: yeoman-generator, chalk, and other packages now require Node 18.17+
3. **Consumer Requirements**: Users must upgrade to Node 22+ to use this generator
If you need to use the generator with Node 14, please use version 3.x