From 83288bc64f278a64c01f64e7667f3f0d3a6ebc74 Mon Sep 17 00:00:00 2001 From: Craigory Coppola Date: Fri, 17 Oct 2025 09:53:43 -0400 Subject: [PATCH 1/2] fix(core): avoid changing existing project name if a project.json file is added to a project --- .../generators/utils/project-configuration.ts | 17 ++++++++++++++++- .../nx/src/plugins/package-json/create-nodes.ts | 2 +- .../project-json/build-nodes/project-json.ts | 15 +-------------- .../utils/project-configuration-utils.ts | 12 ++++++++++++ 4 files changed, 30 insertions(+), 16 deletions(-) diff --git a/packages/nx/src/generators/utils/project-configuration.ts b/packages/nx/src/generators/utils/project-configuration.ts index 08742cad0c3e34..c3f7bc131cc93e 100644 --- a/packages/nx/src/generators/utils/project-configuration.ts +++ b/packages/nx/src/generators/utils/project-configuration.ts @@ -279,6 +279,20 @@ function readAndCombineAllProjectConfigurations(tree: Tree): { if (basename(projectFile) === 'project.json') { const json = readJson(tree, projectFile); const config = buildProjectFromProjectJson(json, projectFile); + if (!config.name) { + try { + const packageJson = readJson( + tree, + joinPathFragments(config.root, 'package.json') + ); + if (packageJson.name) { + config.name = packageJson.name; + } + } catch { + // Maybe no package json, is ok. + } + config.name ??= toProjectName(projectFile); + } mergeProjectConfigurationIntoRootMap( rootMap, config, @@ -286,7 +300,8 @@ function readAndCombineAllProjectConfigurations(tree: Tree): { undefined, true ); - } else if (basename(projectFile) === 'package.json') { + } + if (basename(projectFile) === 'package.json') { const packageJson = readJson(tree, projectFile); // We don't want to have all of the extra inferred stuff in here, as diff --git a/packages/nx/src/plugins/package-json/create-nodes.ts b/packages/nx/src/plugins/package-json/create-nodes.ts index 29b1b23940e23d..11bf26a8152784 100644 --- a/packages/nx/src/plugins/package-json/create-nodes.ts +++ b/packages/nx/src/plugins/package-json/create-nodes.ts @@ -202,7 +202,7 @@ export function buildProjectConfigurationFromPackageJson( } } - if (!packageJson.name && projectRoot === '.') { + if (!packageJson.name && projectRoot === '.' && !packageJson.nx?.name) { throw new Error( 'Nx requires the root package.json to specify a name if it is being used as an Nx project.' ); diff --git a/packages/nx/src/plugins/project-json/build-nodes/project-json.ts b/packages/nx/src/plugins/project-json/build-nodes/project-json.ts index 43512d064b40ee..86229749fed4e9 100644 --- a/packages/nx/src/plugins/project-json/build-nodes/project-json.ts +++ b/packages/nx/src/plugins/project-json/build-nodes/project-json.ts @@ -1,13 +1,11 @@ import { dirname, join } from 'node:path'; import { ProjectConfiguration } from '../../../config/workspace-json-project-json'; -import { toProjectName } from '../../../config/to-project-name'; import { readJsonFile } from '../../../utils/fileutils'; import { createNodesFromFiles, NxPluginV2, } from '../../../project-graph/plugins'; -import { PackageJson } from '../../../utils/package-json'; export const ProjectJsonProjectsPlugin: NxPluginV2 = { name: 'nx/core/project-json', @@ -42,21 +40,10 @@ export function buildProjectFromProjectJson( json: Partial, path: string ): ProjectConfiguration { - const packageJsonPath = join(dirname(path), 'package.json'); const { name, root, ...rest } = json; return { - name: - name ?? readNameFromPackageJson(packageJsonPath) ?? toProjectName(path), + name, root: root ?? dirname(path), ...rest, }; } - -export function readNameFromPackageJson(path: string): string { - try { - const json = readJsonFile(path); - return json.nx?.name ?? json.name; - } catch { - return undefined; - } -} diff --git a/packages/nx/src/project-graph/utils/project-configuration-utils.ts b/packages/nx/src/project-graph/utils/project-configuration-utils.ts index ba1460ec80071b..cbda398a13a276 100644 --- a/packages/nx/src/project-graph/utils/project-configuration-utils.ts +++ b/packages/nx/src/project-graph/utils/project-configuration-utils.ts @@ -13,6 +13,7 @@ import { workspaceRoot } from '../../utils/workspace-root'; import { minimatch } from 'minimatch'; import { join } from 'path'; import { performance } from 'perf_hooks'; +import { existsSync } from 'node:fs'; import { LoadedNxPlugin } from '../plugins/loaded-nx-plugin'; import { @@ -37,6 +38,7 @@ import { getExecutorInformation, parseExecutor, } from '../../command-line/run/executor-utils'; +import { toProjectName } from '../../config/to-project-name'; export type SourceInformation = [file: string | null, plugin: string]; export type ConfigurationSourceMaps = Record< @@ -668,6 +670,16 @@ function validateAndNormalizeProjectRootMap( // Strip it before returning configuration for usage. if (project['// targets']) delete project['// targets']; + // We initially did this in the project.json plugin, but + // that resulted in project.json files without names causing + // the resulting project to change names from earlier plugins... + if ( + !project.name && + existsSync(join(workspaceRoot, project.root, 'project.json')) + ) { + project.name = toProjectName(join(root, 'project.json')); + } + try { validateProject(project, projects); projects[project.name] = project; From 0b50837381a8eb12479b2951fae09366bcf0cfbf Mon Sep 17 00:00:00 2001 From: Craigory Coppola Date: Fri, 17 Oct 2025 18:04:06 -0400 Subject: [PATCH 2/2] chore(angular): fixup misc inconsistency change uncovered in unit test --- .../ng-add/migrators/projects/e2e.migrator.spec.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/angular/src/generators/ng-add/migrators/projects/e2e.migrator.spec.ts b/packages/angular/src/generators/ng-add/migrators/projects/e2e.migrator.spec.ts index 4dc44c70c623ac..7e38494fcd0270 100644 --- a/packages/angular/src/generators/ng-add/migrators/projects/e2e.migrator.spec.ts +++ b/packages/angular/src/generators/ng-add/migrators/projects/e2e.migrator.spec.ts @@ -43,7 +43,9 @@ describe('e2e migrator', () => { config: ProjectConfiguration ): MigrationProjectConfiguration { config.projectType = 'application'; - writeJson(tree, `apps/${name}/project.json`, config); + config.name ??= name; + + writeJson(tree, `${config.root}/project.json`, config); tree.write(`${config.root}/README.md`, ''); tree.write(`${config.sourceRoot}/main.ts`, ''); @@ -62,9 +64,6 @@ describe('e2e migrator', () => { logger?: Logger ): void { migrator = new E2eMigrator(tree, {}, project, lintTargetName, logger); - // the app migrator does this before invoking e2e migrator, it's an implementation - // detail for now until the e2e migrator is split into builder migrators - project.config.root = 'apps/app1'; } beforeEach(() => {