feat(core): provide a hint when project.json has empty targets (#22028)

This commit is contained in:
Jack Hsu 2024-02-29 00:12:49 -05:00 committed by GitHub
parent 56c34cf429
commit c523d52414
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 102 additions and 4 deletions

View File

@ -62,6 +62,7 @@ exports[`app generated files content - as-provided general application should co
"$schema": "../node_modules/nx/schemas/project-schema.json", "$schema": "../node_modules/nx/schemas/project-schema.json",
"projectType": "application", "projectType": "application",
"sourceRoot": "my-app/src", "sourceRoot": "my-app/src",
"// targets": "to see all targets run: nx show project my-app --web",
"targets": {} "targets": {}
} }
" "

View File

@ -21,7 +21,6 @@ const projectConfiguration: ProjectConfiguration = {
name: 'test', name: 'test',
root: 'libs/test', root: 'libs/test',
sourceRoot: 'libs/test/src', sourceRoot: 'libs/test/src',
targets: {},
}; };
describe('project configuration', () => { describe('project configuration', () => {
@ -32,7 +31,32 @@ describe('project configuration', () => {
}); });
it('should create project.json file when adding a project if standalone is true', () => { it('should create project.json file when adding a project if standalone is true', () => {
addProjectConfiguration(tree, 'test', projectConfiguration); addProjectConfiguration(tree, 'test', {
...projectConfiguration,
targets: {
test: {},
},
});
expect(readProjectConfiguration(tree, 'test')).toMatchInlineSnapshot(`
{
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"name": "test",
"root": "libs/test",
"sourceRoot": "libs/test/src",
"targets": {
"test": {},
},
}
`);
expect(tree.exists('libs/test/project.json')).toBeTruthy();
});
it('should add a comment to show project details when targets are missing', () => {
addProjectConfiguration(tree, 'test', {
...projectConfiguration,
targets: {},
});
expect(readProjectConfiguration(tree, 'test')).toMatchInlineSnapshot(` expect(readProjectConfiguration(tree, 'test')).toMatchInlineSnapshot(`
{ {
@ -43,7 +67,54 @@ describe('project configuration', () => {
"targets": {}, "targets": {},
} }
`); `);
expect(tree.exists('libs/test/project.json')).toBeTruthy();
expect(tree.read('libs/test/project.json', 'utf-8')).toMatchInlineSnapshot(`
"{
"name": "test",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/test/src",
"// targets": "to see all targets run: nx show project test --web",
"targets": {}
}
"
`);
// Adding a target removes the "// targets" comment.
updateProjectConfiguration(tree, 'test', {
...projectConfiguration,
targets: {
test: {},
},
});
expect(tree.read('libs/test/project.json', 'utf-8')).toMatchInlineSnapshot(`
"{
"name": "test",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/test/src",
"targets": {
"test": {}
}
}
"
`);
// Emptying out targets add "// targets" comment back.
updateProjectConfiguration(tree, 'test', {
...projectConfiguration,
targets: {},
});
expect(tree.read('libs/test/project.json', 'utf-8')).toMatchInlineSnapshot(`
"{
"name": "test",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/test/src",
"// targets": "to see all targets run: nx show project test --web",
"targets": {}
}
"
`);
}); });
it('should update project.json file when updating a project', () => { it('should update project.json file when updating a project', () => {

View File

@ -64,6 +64,9 @@ export function addProjectConfiguration(
} }
delete (projectConfiguration as any).$schema; delete (projectConfiguration as any).$schema;
handleEmptyTargets(projectName, projectConfiguration);
writeJson(tree, projectConfigFile, { writeJson(tree, projectConfigFile, {
name: projectName, name: projectName,
$schema: getRelativeProjectJsonSchemaPath(tree, projectConfiguration), $schema: getRelativeProjectJsonSchemaPath(tree, projectConfiguration),
@ -94,6 +97,7 @@ export function updateProjectConfiguration(
`Cannot update Project ${projectName} at ${projectConfiguration.root}. It either doesn't exist yet, or may not use project.json for configuration. Use \`addProjectConfiguration()\` instead if you want to create a new project.` `Cannot update Project ${projectName} at ${projectConfiguration.root}. It either doesn't exist yet, or may not use project.json for configuration. Use \`addProjectConfiguration()\` instead if you want to create a new project.`
); );
} }
handleEmptyTargets(projectName, projectConfiguration);
writeJson(tree, projectConfigFile, { writeJson(tree, projectConfigFile, {
name: projectConfiguration.name ?? projectName, name: projectConfiguration.name ?? projectName,
$schema: getRelativeProjectJsonSchemaPath(tree, projectConfiguration), $schema: getRelativeProjectJsonSchemaPath(tree, projectConfiguration),
@ -192,7 +196,7 @@ function readAndCombineAllProjectConfigurations(tree: Tree): {
'**/project.json', '**/project.json',
'project.json', 'project.json',
...getGlobPatternsFromPackageManagerWorkspaces(tree.root, (p) => ...getGlobPatternsFromPackageManagerWorkspaces(tree.root, (p) =>
readJson(tree, p) readJson(tree, p, { expectComments: true })
), ),
]; ];
const projectGlobPatterns = configurationGlobs([ const projectGlobPatterns = configurationGlobs([
@ -328,3 +332,22 @@ function toNewFormat(w: any): ProjectsConfigurations {
} }
return w; return w;
} }
function handleEmptyTargets(
projectName: string,
projectConfiguration: ProjectConfiguration
): void {
if (
projectConfiguration.targets &&
!Object.keys(projectConfiguration.targets).length
) {
// Re-order `targets` to appear after the `// target` comment.
delete projectConfiguration.targets;
projectConfiguration[
'// targets'
] = `to see all targets run: nx show project ${projectName} --web`;
projectConfiguration.targets = {};
} else {
delete projectConfiguration['// targets'];
}
}

View File

@ -303,6 +303,9 @@ export function readProjectConfigurationsFromRootMap(
const errors: Map<string, string[]> = new Map(); const errors: Map<string, string[]> = new Map();
for (const [root, configuration] of projectRootMap.entries()) { for (const [root, configuration] of projectRootMap.entries()) {
// We're setting `// targets` as a comment `targets` is empty due to Project Crystal.
// Strip it before returning configuration for usage.
if (configuration['// targets']) delete configuration['// targets'];
if (!configuration.name) { if (!configuration.name) {
try { try {
const { name } = readJsonFile(join(root, 'package.json')); const { name } = readJsonFile(join(root, 'package.json'));