Skip to content

Commit

Permalink
fix(core): read project name from package json if not set in project …
Browse files Browse the repository at this point in the history
…json
  • Loading branch information
AgentEnder committed Jun 11, 2024
1 parent 4a5eb23 commit bea9f46
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 3 deletions.
6 changes: 6 additions & 0 deletions packages/nx/migrations.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
}
100 changes: 100 additions & 0 deletions packages/nx/src/migrations/update-19-2-4/set-project-name.spec.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 43 additions & 0 deletions packages/nx/src/migrations/update-19-2-4/set-project-name.ts
Original file line number Diff line number Diff line change
@@ -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);
}
20 changes: 17 additions & 3 deletions packages/nx/src/plugins/project-json/build-nodes/project-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -15,6 +16,7 @@ export const ProjectJsonProjectsPlugin: NxPluginV2 = {
);

const project = buildProjectFromProjectJson(json, file);

return {
projects: {
[project.root]: project,
Expand All @@ -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;
}
}
1 change: 1 addition & 0 deletions packages/nx/src/utils/package-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from './package-manager';

export interface NxProjectPackageJsonConfiguration {
name?: string;
implicitDependencies?: string[];
tags?: string[];
namedInputs?: { [inputName: string]: (string | InputDefinition)[] };
Expand Down

0 comments on commit bea9f46

Please sign in to comment.