Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,6 @@ Plain-JS shape's entry stays at project root, not under `src/`: with no bundler

`styles`/`react` are only settable when frontend is enabled — enforced twice: `CliSchema`'s `.refine()` checks (`schema.ts`) and structurally by `runPromptFlow.ts` (styles/react prompts only run `if (model.frontend)`). Keep both in sync if this changes. So the frontend axis collapses to 5 states — `false`, or enabled × `{none, styles-only, react-only, styles+react}` — not a raw 2×2 sub-cross.

Combined with `language` (2) and `hasBackend` (2): **20** distinct configs. `registry` (default vs. custom URL) is an independent axis, only toggling whether `generateBase` writes `.npmrc`. No package-manager (npm/yarn/pnpm) axis exists.
Combined with `language` (2) and `hasBackend` (2): **20** distinct configs. `nodeVersion` is an independent string input that only changes `.nvmrc` and `package.json#engines`; `registry` (default vs. custom URL) is another independent axis that only toggles whether `generateBase` writes `.npmrc`. No package-manager (npm/yarn/pnpm) axis exists.

What's actually observable at runtime per combo (browser vs stdout vs nothing), and current e2e coverage gaps: see `e2e/AGENTS.md`.
2 changes: 2 additions & 0 deletions README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

146 changes: 76 additions & 70 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"dependencies": {
"@clack/prompts": "^1.6.0",
"handlebars": "^4.7.9",
"semver": "^7.8.5",
"zod": "^4.4.3"
},
"devDependencies": {
Expand All @@ -37,6 +38,7 @@
"@gravity-ui/tsconfig": "^1.0.0",
"@playwright/test": "^1.61.1",
"@types/node": "^24.13.3",
"@types/semver": "^7.7.1",
"eslint": "^9.39.4",
"eslint-plugin-n": "^18.2.1",
"knip": "^6.23.0",
Expand Down
1 change: 1 addition & 0 deletions scripts/readme/readme.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Three shapes: app-builder layout (frontend and/or backend selected), plain TS en
```
.
|-- .gitignore
|-- .nvmrc
|-- .prettierrc.js
|-- .stylelintrc.json # only with styles
|-- README.md
Expand Down
12 changes: 11 additions & 1 deletion src/cli/args.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@ import {parseCli} from './args.js';

test.describe('parseCli', () => {
test('parses string and enum flags', (t: TestContext) => {
const result = parseCli(['--out', './my-app', '--language', 'ts']);
const result = parseCli([
'--out',
'./my-app',
'--language',
'ts',
'--node-version',
'24.1.0',
]);
t.assert.equal(result.out, './my-app');
t.assert.equal(result.language, 'ts');
t.assert.equal(result['node-version'], '24.1.0');
});

test('parses boolean flags', (t: TestContext) => {
Expand Down Expand Up @@ -52,6 +60,8 @@ test.describe('parseCli', () => {

test('formats a zod error for a flag with --prefix', (t: TestContext) => {
t.assert.throws(() => parseCli(['--language', 'cobol']), /^Error: --language: /);
t.assert.throws(() => parseCli(['--node-version', 'latest']), /^Error: --node-version: /);
t.assert.throws(() => parseCli(['--node-version', '21']), /^Error: --node-version: /);
});

test('formats the out field error without a -- prefix', (t: TestContext) => {
Expand Down
3 changes: 2 additions & 1 deletion src/cli/introspect.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ test.describe('listFields', () => {
[
'out',
'language',
'node-version',
'frontend',
'styles',
'react',
Expand Down Expand Up @@ -52,7 +53,7 @@ test.describe('listFields', () => {

test('classifies plain string fields as kind "string"', (t: TestContext) => {
const fields = listFields();
for (const name of ['out', 'registry']) {
for (const name of ['out', 'node-version', 'registry']) {
const field = fields.find((f) => f.name === name);
t.assert.equal(field?.kind, 'string');
}
Expand Down
Loading
Loading