Skip to content

Commit 08a4891

Browse files
authored
feat(core): change the signature of createNodes to return a project root map instead of project name map (#20102)
1 parent c7d0d21 commit 08a4891

File tree

12 files changed

+88
-64
lines changed

12 files changed

+88
-64
lines changed

docs/generated/devkit/CreateNodesFunction.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Type alias: CreateNodesFunction<T\>
22

3-
Ƭ **CreateNodesFunction**<`T`\>: (`projectConfigurationFile`: `string`, `options`: `T` \| `undefined`, `context`: [`CreateNodesContext`](../../devkit/documents/CreateNodesContext)) => { `externalNodes?`: `Record`<`string`, [`ProjectGraphExternalNode`](../../devkit/documents/ProjectGraphExternalNode)\> ; `projects?`: `Record`<`string`, [`ProjectConfiguration`](../../devkit/documents/ProjectConfiguration)\> }
3+
Ƭ **CreateNodesFunction**<`T`\>: (`projectConfigurationFile`: `string`, `options`: `T` \| `undefined`, `context`: [`CreateNodesContext`](../../devkit/documents/CreateNodesContext)) => { `externalNodes?`: `Record`<`string`, [`ProjectGraphExternalNode`](../../devkit/documents/ProjectGraphExternalNode)\> ; `projects?`: `Record`<`string`, `Optional`<[`ProjectConfiguration`](../../devkit/documents/ProjectConfiguration), `"root"`\>\> }
44

55
#### Type parameters
66

@@ -27,7 +27,7 @@ Used for creating nodes for the [ProjectGraph](../../devkit/documents/ProjectGra
2727

2828
`Object`
2929

30-
| Name | Type |
31-
| :--------------- | :------------------------------------------------------------------------------------------------- |
32-
| `externalNodes?` | `Record`<`string`, [`ProjectGraphExternalNode`](../../devkit/documents/ProjectGraphExternalNode)\> |
33-
| `projects?` | `Record`<`string`, [`ProjectConfiguration`](../../devkit/documents/ProjectConfiguration)\> |
30+
| Name | Type | Description |
31+
| :--------------- | :---------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------- |
32+
| `externalNodes?` | `Record`<`string`, [`ProjectGraphExternalNode`](../../devkit/documents/ProjectGraphExternalNode)\> | A map of external node name -> external node. External nodes do not have a root, so the key is their name. |
33+
| `projects?` | `Record`<`string`, `Optional`<[`ProjectConfiguration`](../../devkit/documents/ProjectConfiguration), `"root"`\>\> | A map of project root -> project configuration |

docs/shared/recipes/plugins/project-graph-plugins.md

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,11 @@ export const createNodes: CreateNodes = [
6060
'**/project.json',
6161
(projectConfigurationFile: string, opts, context: CreateNodesContext) => {
6262
const projectConfiguration = readJson(projectConfigurationFile);
63-
const projectRoot = dirname(projectConfigurationFile);
64-
const projectName = projectConfiguration.name;
63+
const root = dirname(projectConfigurationFile);
6564

6665
return {
6766
projects: {
68-
[projectName]: {
69-
...projectConfiguration,
70-
root: projectRoot,
71-
},
67+
[root]: projectConfiguration,
7268
},
7369
};
7470
},
@@ -244,12 +240,10 @@ export const createNodes: CreateNodes<MyPluginOptions> = [
244240
'**/project.json',
245241
(fileName, opts, ctx) => {
246242
const root = dirname(fileName);
247-
const name = basename(fileName);
248243

249244
return {
250245
projects: {
251-
[name]: {
252-
root,
246+
[root]: {
253247
tags: opts.tagName ? [opts.tagName] : [],
254248
},
255249
},

e2e/plugin/src/nx-plugin.fixtures.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@ export const createNodes: CreateNodes<PluginOptions> = [
3737
3838
return {
3939
projects: {
40-
[name]: {
40+
[root]: {
4141
root,
42+
name,
4243
targets: {
4344
build: {
4445
executor: "nx:run-commands",

packages/nx/plugins/package-json-workspaces.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ describe('nx package.json workspaces plugin', () => {
4040
.toMatchInlineSnapshot(`
4141
{
4242
"projects": {
43-
"root": {
43+
".": {
4444
"name": "root",
4545
"projectType": "library",
4646
"root": ".",
@@ -68,7 +68,7 @@ describe('nx package.json workspaces plugin', () => {
6868
.toMatchInlineSnapshot(`
6969
{
7070
"projects": {
71-
"lib-a": {
71+
"packages/lib-a": {
7272
"name": "lib-a",
7373
"projectType": "library",
7474
"root": "packages/lib-a",
@@ -96,7 +96,7 @@ describe('nx package.json workspaces plugin', () => {
9696
.toMatchInlineSnapshot(`
9797
{
9898
"projects": {
99-
"lib-b": {
99+
"packages/lib-b": {
100100
"implicitDependencies": [
101101
"lib-a",
102102
],

packages/nx/plugins/package-json-workspaces.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,14 @@ export function getNxPackageJsonWorkspacesPlugin(root: string): NxPluginV2 {
3030

3131
export function createNodeFromPackageJson(pkgJsonPath: string, root: string) {
3232
const json: PackageJson = readJsonFile(join(root, pkgJsonPath));
33+
const project = buildProjectConfigurationFromPackageJson(
34+
json,
35+
pkgJsonPath,
36+
readNxJson(root)
37+
);
3338
return {
3439
projects: {
35-
[json.name]: buildProjectConfigurationFromPackageJson(
36-
json,
37-
pkgJsonPath,
38-
readNxJson(root)
39-
),
40+
[project.root]: project,
4041
},
4142
};
4243
}

packages/nx/src/adapter/angular-json.ts

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -56,48 +56,61 @@ function readAngularJson(angularCliWorkspaceRoot: string) {
5656
}
5757

5858
export function toNewFormat(w: any): ProjectsConfigurations {
59-
Object.values(w.projects || {}).forEach((projectConfig: any) => {
59+
if (!w.projects) {
60+
return w;
61+
}
62+
for (const name in w.projects ?? {}) {
63+
const projectConfig = w.projects[name];
6064
if (projectConfig.architect) {
6165
renamePropertyWithStableKeys(projectConfig, 'architect', 'targets');
6266
}
6367
if (projectConfig.schematics) {
6468
renamePropertyWithStableKeys(projectConfig, 'schematics', 'generators');
6569
}
70+
if (!projectConfig.name) {
71+
projectConfig.name = name;
72+
}
73+
6674
Object.values(projectConfig.targets || {}).forEach((target: any) => {
6775
if (target.builder !== undefined) {
6876
renamePropertyWithStableKeys(target, 'builder', 'executor');
6977
}
7078
});
71-
});
79+
}
80+
7281
if (w.schematics) {
7382
renamePropertyWithStableKeys(w, 'schematics', 'generators');
7483
}
7584
if (w.version !== 2) {
7685
w.version = 2;
7786
}
87+
7888
return w;
7989
}
8090

8191
export function toOldFormat(w: any) {
82-
Object.values(w.projects || {}).forEach((projectConfig: any) => {
83-
if (typeof projectConfig === 'string') {
84-
throw new Error(
85-
"'project.json' files are incompatible with version 1 workspace schemas."
86-
);
87-
}
88-
if (projectConfig.targets) {
89-
renamePropertyWithStableKeys(projectConfig, 'targets', 'architect');
90-
}
91-
if (projectConfig.generators) {
92-
renamePropertyWithStableKeys(projectConfig, 'generators', 'schematics');
93-
}
94-
delete projectConfig.name;
95-
Object.values(projectConfig.architect || {}).forEach((target: any) => {
96-
if (target.executor !== undefined) {
97-
renamePropertyWithStableKeys(target, 'executor', 'builder');
92+
if (w.projects) {
93+
for (const name in w.projects) {
94+
const projectConfig = w.projects[name];
95+
if (typeof projectConfig === 'string') {
96+
throw new Error(
97+
"'project.json' files are incompatible with version 1 workspace schemas."
98+
);
9899
}
99-
});
100-
});
100+
if (projectConfig.targets) {
101+
renamePropertyWithStableKeys(projectConfig, 'targets', 'architect');
102+
}
103+
if (projectConfig.generators) {
104+
renamePropertyWithStableKeys(projectConfig, 'generators', 'schematics');
105+
}
106+
delete projectConfig.name;
107+
Object.values(projectConfig.architect || {}).forEach((target: any) => {
108+
if (target.executor !== undefined) {
109+
renamePropertyWithStableKeys(target, 'executor', 'builder');
110+
}
111+
});
112+
}
113+
}
101114

102115
if (w.generators) {
103116
renamePropertyWithStableKeys(w, 'generators', 'schematics');

packages/nx/src/plugins/project-json/build-nodes/project-json.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ describe('nx project.json plugin', () => {
3939
.toMatchInlineSnapshot(`
4040
{
4141
"projects": {
42-
"root": {
42+
".": {
4343
"name": "root",
4444
"root": ".",
4545
"targets": {
@@ -53,7 +53,7 @@ describe('nx project.json plugin', () => {
5353
.toMatchInlineSnapshot(`
5454
{
5555
"projects": {
56-
"lib-a": {
56+
"packages/lib-a": {
5757
"name": "lib-a",
5858
"root": "packages/lib-a",
5959
"targets": {

packages/nx/src/plugins/project-json/build-nodes/project-json.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ export const CreateProjectJsonProjectsPlugin: NxPluginV2 = {
99
name: 'nx-core-build-project-json-nodes',
1010
createNodes: [
1111
'{project.json,**/project.json}',
12-
(file, _, context) => {
13-
const root = context.workspaceRoot;
14-
const json = readJsonFile<ProjectConfiguration>(join(root, file));
12+
(file, _, { workspaceRoot }) => {
13+
const json = readJsonFile<ProjectConfiguration>(
14+
join(workspaceRoot, file)
15+
);
1516
const project = buildProjectFromProjectJson(json, file);
1617
return {
1718
projects: {
18-
[project.name]: project,
19+
[project.root]: project,
1920
},
2021
};
2122
},

packages/nx/src/project-graph/utils/project-configuration-utils.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,19 @@ export function buildProjectsConfigurationsFromProjectPathsAndPlugins(
114114
workspaceRoot: root,
115115
});
116116
for (const node in projectNodes) {
117-
projectNodes[node].name ??= node;
118-
mergeProjectConfigurationIntoRootMap(
119-
projectRootMap,
120-
projectNodes[node]
121-
);
117+
mergeProjectConfigurationIntoRootMap(projectRootMap, {
118+
// If root is specified in config, that will overwrite this.
119+
// Specifying it here though allows plugins to return something like
120+
// {
121+
// projects: {
122+
// [root]: { targets: buildTargetsFromFile(f) }
123+
// }
124+
// }
125+
// Otherwise, the root would have to be specified in the config as well
126+
// which would be a bit redundant.
127+
root: node,
128+
...projectNodes[node],
129+
});
122130
}
123131
Object.assign(externalNodes, pluginExternalNodes);
124132
}

packages/nx/src/utils/nx-plugin.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ import {
4040
} from '../adapter/angular-json';
4141
import { getNxPackageJsonWorkspacesPlugin } from '../../plugins/package-json-workspaces';
4242
import { CreateProjectJsonProjectsPlugin } from '../plugins/project-json/build-nodes/project-json';
43-
import { FileMapCache } from '../project-graph/nx-deps-cache';
4443
import { CreatePackageJsonProjectsNextToProjectJson } from '../plugins/project-json/build-nodes/package-json-next-to-project-json';
4544

4645
/**
@@ -60,7 +59,14 @@ export type CreateNodesFunction<T = unknown> = (
6059
options: T | undefined,
6160
context: CreateNodesContext
6261
) => {
63-
projects?: Record<string, ProjectConfiguration>;
62+
/**
63+
* A map of project root -> project configuration
64+
*/
65+
projects?: Record<string, Optional<ProjectConfiguration, 'root'>>;
66+
67+
/**
68+
* A map of external node name -> external node. External nodes do not have a root, so the key is their name.
69+
*/
6470
externalNodes?: Record<string, ProjectGraphExternalNode>;
6571
};
6672

@@ -311,12 +317,12 @@ function ensurePluginIsV2(plugin: NxPlugin): NxPluginV2 {
311317
createNodes: [
312318
`*/**/${combineGlobPatterns(plugin.projectFilePatterns)}`,
313319
(configFilePath) => {
314-
const name = toProjectName(configFilePath);
320+
const root = dirname(configFilePath);
315321
return {
316322
projects: {
317-
[name]: {
318-
name,
319-
root: dirname(configFilePath),
323+
[root]: {
324+
name: toProjectName(configFilePath),
325+
root,
320326
targets: plugin.registerProjectTargets?.(configFilePath),
321327
},
322328
},
@@ -535,3 +541,5 @@ function getDefaultPluginsSync(root: string): LoadedNxPlugin[] {
535541
plugin: p,
536542
}));
537543
}
544+
545+
type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;

0 commit comments

Comments
 (0)