Skip to content

Commit 846eeff

Browse files
polygraph-snapshot-app[bot]AgentEnder
authored andcommitted
fix(misc): multi-version compliance for @nx/express, @nx/node, and @nx/nest (nrwl#35807)
## Current Behavior **`@nx/express`** - Peer dep declares `express: ^4.21.2` only; Express v5 has been ACTIVE since 2025-03-31 and v4 is in MAINT, so the plugin's advertised window doesn't match the upstream support window. - Generators install a single literal `express ^4.21.2` regardless of what's installed; no per-major routing for `express` or `@types/express`. - `keepExistingVersions` schema default is `false`, so re-running the generator silently overwrites a user's pinned `express` version. - No floor enforcement: a workspace on an unsupported (sub-floor) `express` version sees no error. **`@nx/node`** - No `peerDependencies` for `express`, `koa`, or `fastify`. Init/application generators write framework deps unconditionally, ignoring what's installed. - `keepExistingVersions` defaults to `false`; framework installs override user pins. - `migrations.json` `22.0.2` bumps `koa` from v2 to v3 with no `requires` block — every workspace on koa v2 gets pushed to v3 unconditionally. - `migrations.json` `20.4.0` mixes a cross-major fastify v4→v5 bump with same-major express bumps under one entry, with no `requires` (AND-semantics would gate same-major bumps incorrectly if added naively). - No floor enforcement for any framework. **`@nx/nest`** - `peerDependencies` block is missing from `package.json` entirely; workspaces have no advertised compatible range for any `@nestjs/*` package. - Versions module has flat constants; the plugin ships v11-only even though NestJS v10.4.x still receives upstream patches (N & N-1 baseline calls for v10 + v11). - `migrations.json` `21.2.0-beta.2` uses a bare key `nest` which is not a real npm package — the entry is effectively a no-op. The real cross-major v10→v11 bump for `@nestjs/common`, `@nestjs/core`, `@nestjs/platform-express`, `@nestjs/testing` is missing, as is a `requires` source-major gate. - No floor enforcement for any NestJS version. ## Expected Behavior **`@nx/express` (NXC-4390)** - Per-major `versionMap` keyed on `express` major covering both `express` and `@types/express` for v4 and v5; fresh installs default to v5.1.0. - `assertSupportedExpressVersion(tree)` (calls shared `assertSupportedPackageVersion`) is the first statement of `initGenerator` and `applicationGeneratorInternal`. - Peer widened to `express: ">=4.0.0 <6.0.0"` (still optional). - All `addDependenciesToPackageJson` call sites from generators pass `keepExistingVersions ?? true`; schema defaults flipped to `true`. Init now installs `@types/express` (previously a dead export). - New `all-generators-enforce-floor.spec.ts` exercises every generator entry at `subFloorVersion: '~3.21.0'`. - Supported-versions docs page updated. **`@nx/node` (NXC-4396)** - Per-package `versionMap` + `versions(tree)` for `express` (v4+v5), `koa` (v2+v3), `fastify` (v4+v5), and `@types/node` (v22+v24). Fresh installs default to active LTS / latest stable. - `assertSupportedFrameworkVersion(tree, schema.framework)` (dispatches to one wrapper per framework) is the first statement of `applicationGeneratorInternal`, only firing when `--framework` selects a non-`none`/`nest` lane. - Framework + `@types/node` installs route through `versions(tree)` and pass `keepExistingVersions ?? true`. Init schema default flipped to `true`. - `migrations.json`: `22.0.2` koa v2→v3 gated with `requires: { koa: ">=2.0.0 <3.0.0" }`. `22.6.0` koa CVE patch gated bilaterally to v3 only. `20.4.0` split into the original same-major express bumps (no gate) and a new `20.4.0-fastify` entry gated on `requires: { fastify: ">=4.0.0 <5.0.0" }`. - Optional `peerDependencies` declared for `express`, `koa`, `fastify`. Added `semver: "catalog:"` to deps (now imported by `versions.ts`). `@nx/dependency-checks` allow-list updated. **`@nx/nest` (NXC-4394)** - Per-major `versionMap` covering NestJS v10 and v11 for the full `@nestjs/*` family plus `rxjs` and `reflect-metadata`. Fresh installs default to NestJS v11, with `reflect-metadata` bumped from `^0.1.13` to `^0.2.0` to match v11's requirement. - `assertSupportedNestJsVersion(tree)` is the first statement of the `init`, `application`, and `library` generators. - `ensureDependencies` and the init `addDependencies` helper route through `versions(tree)` and pass `keepExistingVersions: true` (`?? true` on the init path); init schema default flipped to `true`. - Optional `peerDependencies` declared for `@nestjs/core`, `@nestjs/common`, `reflect-metadata`, `rxjs`. Added `semver: "catalog:"` to deps and extended `@nx/dependency-checks` allow-list. - `migrations.json` `21.2.0-beta.2` rewritten with real package keys (the previous bare `nest` key was a typo / no-op) and gated on `requires: { "@nestjs/core": ">=10.0.0 <11.0.0" }`. The entry now also bumps `reflect-metadata` to `^0.2.0` for v11 compatibility. - Supported-versions docs page updated. ## Related Issue(s) Fixes NXC-4390 Fixes NXC-4396 Fixes NXC-4394 --------- Co-authored-by: Craigory Coppola <craigorycoppola@gmail.com>
1 parent 70268b5 commit 846eeff

36 files changed

Lines changed: 807 additions & 78 deletions

astro-docs/src/content/docs/technologies/node/express/introduction.mdoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ The `@nx/express` plugin supports the following package versions.
1616

1717
| Package | Supported Versions |
1818
| --------- | ------------------ |
19-
| `express` | ^4.21.2 |
19+
| `express` | ^4.0.0, ^5.0.0 |
2020

2121
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
2222

astro-docs/src/content/docs/technologies/node/nest/introduction.mdoc

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,19 @@ Many conventions and best practices used in Angular applications can be also be
1919

2020
## Requirements
2121

22-
The `@nx/nest` plugin depends on `@nestjs/schematics` for code generation, which pins the supported NestJS major version.
22+
The `@nx/nest` plugin supports the following NestJS package versions.
2323

24-
| Nx Version | NestJS Version |
25-
| -------------- | -------------- |
26-
| 22.x (current) | ^11.0.0 |
27-
| 21.x | ^11.0.0 |
28-
| 20.x | ^10.0.0 |
24+
| Package | Supported Versions |
25+
| -------------- | ------------------ |
26+
| `@nestjs/core` | ^10.0.0, ^11.0.0 |
27+
28+
The plugin detects the installed `@nestjs/core` major and routes the rest of the `@nestjs/*` family (plus `rxjs` and `reflect-metadata`) to versions that pair with it. Fresh installs default to NestJS v11.
29+
30+
| Nx Version | Default NestJS Version |
31+
| -------------- | ---------------------- |
32+
| 22.x (current) | ^11.0.0 |
33+
| 21.x | ^11.0.0 |
34+
| 20.x | ^10.0.0 |
2935

3036
[Nx generators](/docs/features/generate-code) install the latest supported versions automatically when scaffolding new projects.
3137

packages/express/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,11 @@
3535
"@nx/devkit": "workspace:*",
3636
"@nx/js": "workspace:*",
3737
"@nx/node": "workspace:*",
38+
"semver": "catalog:",
3839
"tslib": "catalog:typescript"
3940
},
4041
"peerDependencies": {
41-
"express": "^4.21.2"
42+
"express": ">=4.0.0 <6.0.0"
4243
},
4344
"peerDependenciesMeta": {
4445
"express": {

packages/express/src/generators/application/application.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ describe('app', () => {
195195
expect(readJson(appTree, 'myapp/package.json')).toMatchInlineSnapshot(`
196196
{
197197
"dependencies": {
198-
"express": "^4.21.2",
198+
"express": "^5.1.0",
199199
},
200200
"name": "@proj/myapp",
201201
"nx": {

packages/express/src/generators/application/application.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { isUsingTsSolutionSetup } from '@nx/js/internal';
1515
import { applicationGenerator as nodeApplicationGenerator } from '@nx/node';
1616
import { tslibVersion } from '@nx/node/src/utils/versions';
1717
import { join } from 'path';
18+
import { assertSupportedExpressVersion } from '../../utils/assert-supported-express-version';
1819
import { nxVersion } from '../../utils/versions';
1920
import { initGenerator } from '../init/init';
2021
import type { Schema } from './schema';
@@ -76,6 +77,8 @@ export async function applicationGenerator(tree: Tree, schema: Schema) {
7677
}
7778

7879
export async function applicationGeneratorInternal(tree: Tree, schema: Schema) {
80+
assertSupportedExpressVersion(tree);
81+
7982
const options = await normalizeOptions(tree, schema);
8083

8184
const tasks: GeneratorCallback[] = [];
@@ -92,7 +95,7 @@ export async function applicationGeneratorInternal(tree: Tree, schema: Schema) {
9295
addTypes(tree, options);
9396

9497
if (!options.skipPackageJson) {
95-
tasks.push(ensureDependencies(tree));
98+
tasks.push(ensureDependencies(tree, options));
9699
}
97100

98101
if (!options.skipFormat) {
@@ -132,10 +135,15 @@ async function normalizeOptions(
132135
};
133136
}
134137

135-
function ensureDependencies(tree: Tree): GeneratorCallback {
138+
function ensureDependencies(
139+
tree: Tree,
140+
options: NormalizedSchema
141+
): GeneratorCallback {
136142
return addDependenciesToPackageJson(
137143
tree,
138144
{ tslib: tslibVersion },
139-
{ '@nx/express': nxVersion }
145+
{ '@nx/express': nxVersion },
146+
undefined,
147+
options.keepExistingVersions ?? true
140148
);
141149
}

packages/express/src/generators/application/schema.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ export interface Schema {
1818
setParserOptionsProject?: boolean;
1919
addPlugin?: boolean;
2020
useProjectJson?: boolean;
21+
keepExistingVersions?: boolean;
2122
}

packages/express/src/generators/application/schema.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@
7777
"useProjectJson": {
7878
"type": "boolean",
7979
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
80+
},
81+
"keepExistingVersions": {
82+
"type": "boolean",
83+
"x-priority": "internal",
84+
"description": "Keep existing dependencies versions",
85+
"default": true
8086
}
8187
},
8288
"required": ["directory"]

packages/express/src/generators/init/init.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,35 @@ import {
66
runTasksInSerial,
77
Tree,
88
} from '@nx/devkit';
9-
import { expressVersion, nxVersion } from '../../utils/versions';
9+
import { assertSupportedExpressVersion } from '../../utils/assert-supported-express-version';
10+
import { nxVersion, versions } from '../../utils/versions';
1011
import type { Schema } from './schema';
1112

1213
function updateDependencies(tree: Tree, schema: Schema) {
1314
const tasks: GeneratorCallback[] = [];
1415

1516
tasks.push(removeDependenciesFromPackageJson(tree, ['@nx/express'], []));
1617

18+
const pkgVersions = versions(tree);
1719
tasks.push(
1820
addDependenciesToPackageJson(
1921
tree,
20-
{ express: expressVersion },
21-
{ '@nx/express': nxVersion },
22+
{ express: pkgVersions.expressVersion },
23+
{
24+
'@nx/express': nxVersion,
25+
'@types/express': pkgVersions.expressTypingsVersion,
26+
},
2227
undefined,
23-
schema.keepExistingVersions
28+
schema.keepExistingVersions ?? true
2429
)
2530
);
2631

2732
return runTasksInSerial(...tasks);
2833
}
2934

3035
export async function initGenerator(tree: Tree, schema: Schema) {
36+
assertSupportedExpressVersion(tree);
37+
3138
let installTask: GeneratorCallback = () => {};
3239
if (!schema.skipPackageJson) {
3340
installTask = updateDependencies(tree, schema);

packages/express/src/generators/init/schema.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"type": "boolean",
2121
"x-priority": "internal",
2222
"description": "Keep existing dependencies versions",
23-
"default": false
23+
"default": true
2424
}
2525
},
2626
"required": []
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { assertGeneratorsEnforceVersionFloor } from '@nx/devkit/internal-testing-utils';
2+
import { join } from 'node:path';
3+
4+
describe('@nx/express generators enforce supported version floor', () => {
5+
assertGeneratorsEnforceVersionFloor({
6+
packageRoot: join(__dirname, '..', '..'),
7+
packageName: 'express',
8+
subFloorVersion: '~3.21.0',
9+
});
10+
});

0 commit comments

Comments
 (0)