fix(core): read project name from package json if not set in project json (#26386)
<!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> ## Current Behavior If `project.json` exists without a name, we infer one based on the root path. This can be confusing when there exists a `package.json` alongside it that contains a name which doesn't match our inferred name. ## Expected Behavior If `project.json` and `package.json` both exist, the name from `package.json` will be used if `project.json` contains no name. ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #26347
This commit is contained in:
parent
471f82c991
commit
5d56e21163
@ -83,6 +83,12 @@
|
||||
"version": "19.2.2-beta.0",
|
||||
"description": "Updates the nx wrapper.",
|
||||
"implementation": "./src/migrations/update-17-3-0/update-nxw"
|
||||
},
|
||||
"19-2-4-set-project-name": {
|
||||
"version": "19.2.4-beta.0",
|
||||
"description": "Set project name in nx.json explicitly",
|
||||
"implementation": "./src/migrations/update-19-2-4/set-project-name",
|
||||
"x-repair-skip": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,100 @@
|
||||
import { createTreeWithEmptyWorkspace } from '../../generators/testing-utils/create-tree-with-empty-workspace';
|
||||
import { readJson } from '../../generators/utils/json';
|
||||
import migrate from './set-project-name';
|
||||
|
||||
describe('set project name', () => {
|
||||
it('should not update packageJson projects', async () => {
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
tree.write(
|
||||
'libs/proj/package.json',
|
||||
JSON.stringify({
|
||||
name: '@scoped/package',
|
||||
})
|
||||
);
|
||||
await migrate(tree);
|
||||
expect(tree.exists('libs/proj/project.json')).toBe(false);
|
||||
});
|
||||
|
||||
it('should not update projectJson if name specified', async () => {
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
tree.write(
|
||||
'libs/proj/project.json',
|
||||
JSON.stringify({
|
||||
name: 'foo',
|
||||
})
|
||||
);
|
||||
await migrate(tree);
|
||||
const project = readJson(tree, 'libs/proj/project.json');
|
||||
expect(project.name).toBe('foo');
|
||||
});
|
||||
|
||||
it('should not update projectJson if name is not specified but no sibling package json', async () => {
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
tree.write('libs/proj/project.json', JSON.stringify({}));
|
||||
await migrate(tree);
|
||||
const project = readJson(tree, 'libs/proj/project.json');
|
||||
expect(project.name).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('should not update projectJson if name is identical to package name', async () => {
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
tree.write(
|
||||
'libs/proj/package.json',
|
||||
JSON.stringify({
|
||||
name: 'proj',
|
||||
})
|
||||
);
|
||||
tree.write('libs/proj/project.json', JSON.stringify({}));
|
||||
await migrate(tree);
|
||||
const project = readJson(tree, 'libs/proj/project.json');
|
||||
expect(project.name).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('should not update projectJson if name is identical to name in nx field', async () => {
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
tree.write(
|
||||
'libs/proj/package.json',
|
||||
JSON.stringify({
|
||||
name: '@scoped/proj',
|
||||
nx: {
|
||||
name: 'proj',
|
||||
},
|
||||
})
|
||||
);
|
||||
tree.write('libs/proj/project.json', JSON.stringify({}));
|
||||
await migrate(tree);
|
||||
const project = readJson(tree, 'libs/proj/project.json');
|
||||
expect(project.name).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('should update projectJson if name is not specified and package name is different', async () => {
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
tree.write(
|
||||
'libs/proj/package.json',
|
||||
JSON.stringify({
|
||||
name: '@scoped/proj',
|
||||
})
|
||||
);
|
||||
tree.write('libs/proj/project.json', JSON.stringify({}));
|
||||
await migrate(tree);
|
||||
const project = readJson(tree, 'libs/proj/project.json');
|
||||
expect(project.name).toBe('proj');
|
||||
});
|
||||
|
||||
it('should update projectJson if name is not specified and name in nx field is different', async () => {
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
tree.write(
|
||||
'libs/foo/package.json',
|
||||
JSON.stringify({
|
||||
name: '@scoped/proj',
|
||||
nx: {
|
||||
name: 'proj',
|
||||
},
|
||||
})
|
||||
);
|
||||
tree.write('libs/foo/project.json', JSON.stringify({}));
|
||||
await migrate(tree);
|
||||
const project = readJson(tree, 'libs/foo/project.json');
|
||||
expect(project.name).toBe('foo');
|
||||
});
|
||||
});
|
||||
43
packages/nx/src/migrations/update-19-2-4/set-project-name.ts
Normal file
43
packages/nx/src/migrations/update-19-2-4/set-project-name.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import { toProjectName } from '../../config/to-project-name';
|
||||
import { ProjectConfiguration } from '../../config/workspace-json-project-json';
|
||||
import { Tree } from '../../generators/tree';
|
||||
import { formatChangedFilesWithPrettierIfAvailable } from '../../generators/internal-utils/format-changed-files-with-prettier-if-available';
|
||||
import { readJson, writeJson } from '../../generators/utils/json';
|
||||
import { getProjects } from '../../generators/utils/project-configuration';
|
||||
import type { PackageJson } from '../../utils/package-json';
|
||||
|
||||
export default async function setProjectName(tree: Tree) {
|
||||
// We are explicitly looking for project.json files here, so getProjects is fine.
|
||||
const projects = getProjects(tree);
|
||||
|
||||
for (const { root } of projects.values()) {
|
||||
const projectJsonPath = `${root}/project.json`;
|
||||
const packageJsonPath = `${root}/package.json`;
|
||||
|
||||
// If either of these files doesn't exist, theres no behavioral difference
|
||||
if (!tree.exists(projectJsonPath) || !tree.exists(packageJsonPath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const projectJson: ProjectConfiguration = readJson(tree, projectJsonPath);
|
||||
|
||||
// In Nx 19.1+, the way the project name is inferred is different.
|
||||
// For existing projects, if the name is not set, we can inline it
|
||||
// based on the existing logic. This makes sure folks aren't caught
|
||||
// off guard by the new behavior.
|
||||
if (!projectJson.name) {
|
||||
const siblingPackageJson = readJson<PackageJson>(tree, packageJsonPath);
|
||||
|
||||
const newName = siblingPackageJson.nx?.name ?? siblingPackageJson.name;
|
||||
|
||||
const oldName = toProjectName(projectJsonPath);
|
||||
|
||||
if (newName && oldName !== newName) {
|
||||
projectJson.name = oldName;
|
||||
writeJson(tree, projectJsonPath, projectJson);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await formatChangedFilesWithPrettierIfAvailable(tree);
|
||||
}
|
||||
@ -4,6 +4,7 @@ import { ProjectConfiguration } from '../../../config/workspace-json-project-jso
|
||||
import { toProjectName } from '../../../config/to-project-name';
|
||||
import { readJsonFile } from '../../../utils/fileutils';
|
||||
import { NxPluginV2 } from '../../../project-graph/plugins';
|
||||
import { PackageJson } from '../../../utils/package-json';
|
||||
|
||||
export const ProjectJsonProjectsPlugin: NxPluginV2 = {
|
||||
name: 'nx/core/project-json',
|
||||
@ -15,6 +16,7 @@ export const ProjectJsonProjectsPlugin: NxPluginV2 = {
|
||||
);
|
||||
|
||||
const project = buildProjectFromProjectJson(json, file);
|
||||
|
||||
return {
|
||||
projects: {
|
||||
[project.root]: project,
|
||||
@ -30,9 +32,21 @@ export function buildProjectFromProjectJson(
|
||||
json: Partial<ProjectConfiguration>,
|
||||
path: string
|
||||
): ProjectConfiguration {
|
||||
const packageJsonPath = join(dirname(path), 'package.json');
|
||||
const { name, root, ...rest } = json;
|
||||
return {
|
||||
name: toProjectName(path),
|
||||
root: dirname(path),
|
||||
...json,
|
||||
name:
|
||||
name ?? readNameFromPackageJson(packageJsonPath) ?? toProjectName(path),
|
||||
root: root ?? dirname(path),
|
||||
...rest,
|
||||
};
|
||||
}
|
||||
|
||||
export function readNameFromPackageJson(path: string): string {
|
||||
try {
|
||||
const json = readJsonFile<PackageJson>(path);
|
||||
return json.nx?.name ?? json.name;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import {
|
||||
} from './package-manager';
|
||||
|
||||
export interface NxProjectPackageJsonConfiguration {
|
||||
name?: string;
|
||||
implicitDependencies?: string[];
|
||||
tags?: string[];
|
||||
namedInputs?: { [inputName: string]: (string | InputDefinition)[] };
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user