diff --git a/packages/angular/cli/lib/config/workspace-schema.json b/packages/angular/cli/lib/config/workspace-schema.json index 7edd9da60eb6..4154e858ba53 100644 --- a/packages/angular/cli/lib/config/workspace-schema.json +++ b/packages/angular/cli/lib/config/workspace-schema.json @@ -22,7 +22,8 @@ }, "defaultProject": { "type": "string", - "description": "Default project name used in commands." + "description": "Default project name used in commands.", + "x-deprecated": "The project to use will be determined from the current working directory." }, "projects": { "type": "object", diff --git a/packages/angular/cli/src/command-builder/architect-command-module.ts b/packages/angular/cli/src/command-builder/architect-command-module.ts index e51fe0cb6ff5..0678abf2a564 100644 --- a/packages/angular/cli/src/command-builder/architect-command-module.ts +++ b/packages/angular/cli/src/command-builder/architect-command-module.ts @@ -128,14 +128,14 @@ export abstract class ArchitectCommandModule // For multi target commands, we always list all projects that have the target. return allProjectsForTargetName; } else { + if (allProjectsForTargetName.length === 1) { + return allProjectsForTargetName; + } + const maybeProject = getProjectByCwd(workspace); if (maybeProject && allProjectsForTargetName.includes(maybeProject)) { return [maybeProject]; } - - if (allProjectsForTargetName.length === 1) { - return allProjectsForTargetName; - } } return undefined; diff --git a/packages/angular/cli/src/command-builder/schematics-command-module.ts b/packages/angular/cli/src/command-builder/schematics-command-module.ts index 80b190dfa0fe..d72b5b265dad 100644 --- a/packages/angular/cli/src/command-builder/schematics-command-module.ts +++ b/packages/angular/cli/src/command-builder/schematics-command-module.ts @@ -333,6 +333,7 @@ export abstract class SchematicsCommandModule return 0; } + private defaultProjectDeprecationWarningShown = false; private getProjectName(): string | undefined { const { workspace, logger } = this.context; if (!workspace) { @@ -354,6 +355,15 @@ export abstract class SchematicsCommandModule const defaultProjectName = workspace.extensions['defaultProject']; if (typeof defaultProjectName === 'string' && defaultProjectName) { + if (!this.defaultProjectDeprecationWarningShown) { + logger.warn(tags.oneLine` + DEPRECATED: The 'defaultProject' workspace option has been deprecated. + The project to use will be determined from the current working directory. + `); + + this.defaultProjectDeprecationWarningShown = true; + } + return defaultProjectName; } } diff --git a/packages/angular/cli/src/commands/add/long-description.md b/packages/angular/cli/src/commands/add/long-description.md index 09cd2e239d76..347b3a5971aa 100644 --- a/packages/angular/cli/src/commands/add/long-description.md +++ b/packages/angular/cli/src/commands/add/long-description.md @@ -1,10 +1,7 @@ Adds the npm package for a published library to your workspace, and configures -the project in the current working directory (or the default project if you are -not in a project directory) to use that library, as specified by the library's schematic. +the project in the current working directory to use that library, as specified by the library's schematic. For example, adding `@angular/pwa` configures your project for PWA support: ```bash ng add @angular/pwa ``` - -The default project is the value of `defaultProject` in `angular.json`. diff --git a/packages/angular/cli/src/utilities/config.ts b/packages/angular/cli/src/utilities/config.ts index 345edbf80af7..d41a0e8c4df7 100644 --- a/packages/angular/cli/src/utilities/config.ts +++ b/packages/angular/cli/src/utilities/config.ts @@ -263,6 +263,7 @@ function findProjectByPath(workspace: AngularWorkspace, location: string): strin return projects[0][1]; } +let defaultProjectDeprecationWarningShown = false; export function getProjectByCwd(workspace: AngularWorkspace): string | null { if (workspace.projects.size === 1) { // If there is only one project, return that one. @@ -277,6 +278,15 @@ export function getProjectByCwd(workspace: AngularWorkspace): string | null { const defaultProject = workspace.extensions['defaultProject']; if (defaultProject && typeof defaultProject === 'string') { // If there is a default project name, return it. + if (!defaultProjectDeprecationWarningShown) { + console.warn( + `DEPRECATED: The 'defaultProject' workspace option has been deprecated. ` + + `The project to use will be determined from the current working directory.`, + ); + + defaultProjectDeprecationWarningShown = true; + } + return defaultProject; } diff --git a/packages/schematics/angular/application/index.ts b/packages/schematics/angular/application/index.ts index b78dab4d8b3d..98664df5c7f0 100644 --- a/packages/schematics/angular/application/index.ts +++ b/packages/schematics/angular/application/index.ts @@ -231,10 +231,6 @@ function addAppToWorkspaceFile( }; return updateWorkspace((workspace) => { - if (workspace.projects.size === 0) { - workspace.extensions.defaultProject = options.name; - } - workspace.projects.add({ name: options.name, ...project, diff --git a/packages/schematics/angular/application/index_spec.ts b/packages/schematics/angular/application/index_spec.ts index 3c9e090c80ff..458f106d1d8f 100644 --- a/packages/schematics/angular/application/index_spec.ts +++ b/packages/schematics/angular/application/index_spec.ts @@ -80,7 +80,6 @@ describe('Application Schematic', () => { .toPromise(); const workspace = JSON.parse(tree.readContent('/angular.json')); expect(workspace.projects.foo).toBeDefined(); - expect(workspace.defaultProject).toBe('foo'); }); it('should set the prefix to app if none is set', async () => { diff --git a/packages/schematics/angular/library/index.ts b/packages/schematics/angular/library/index.ts index 6ba800c09cca..13b2bc9c1c11 100644 --- a/packages/schematics/angular/library/index.ts +++ b/packages/schematics/angular/library/index.ts @@ -82,10 +82,6 @@ function addLibToWorkspaceFile( projectName: string, ): Rule { return updateWorkspace((workspace) => { - if (workspace.projects.size === 0) { - workspace.extensions.defaultProject = projectName; - } - workspace.projects.add({ name: projectName, root: projectRoot, diff --git a/packages/schematics/angular/library/index_spec.ts b/packages/schematics/angular/library/index_spec.ts index 0ae0e9a55f30..9642e82731ef 100644 --- a/packages/schematics/angular/library/index_spec.ts +++ b/packages/schematics/angular/library/index_spec.ts @@ -131,7 +131,6 @@ describe('Library Schematic', () => { const workspace = getJsonFileContent(tree, '/angular.json'); expect(workspace.projects.foo).toBeDefined(); - expect(workspace.defaultProject).toBe('foo'); }); it('should set the prefix to lib if none is set', async () => { diff --git a/packages/schematics/angular/migrations/migration-collection.json b/packages/schematics/angular/migrations/migration-collection.json index e0ef67b80b39..747cfc8c74d8 100644 --- a/packages/schematics/angular/migrations/migration-collection.json +++ b/packages/schematics/angular/migrations/migration-collection.json @@ -14,6 +14,11 @@ "version": "14.0.0", "factory": "./update-14/remove-show-circular-dependencies-option", "description": "Remove 'showCircularDependencies' option from browser and server builders." + }, + "remove-default-project-option": { + "version": "14.0.0", + "factory": "./update-14/remove-default-project-option", + "description": "Remove 'defaultProject' option from workspace configuration. The project to use will be determined from the current working directory." } } } diff --git a/packages/schematics/angular/migrations/update-14/remove-default-project-option.ts b/packages/schematics/angular/migrations/update-14/remove-default-project-option.ts new file mode 100644 index 000000000000..2a7c04475e17 --- /dev/null +++ b/packages/schematics/angular/migrations/update-14/remove-default-project-option.ts @@ -0,0 +1,17 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import { Rule } from '@angular-devkit/schematics'; +import { updateWorkspace } from '../../utility/workspace'; + +/** Migration to remove 'defaultProject' option from angular.json. */ +export default function (): Rule { + return updateWorkspace((workspace) => { + delete workspace.extensions['defaultProject']; + }); +} diff --git a/packages/schematics/angular/migrations/update-14/remove-default-project-option_spec.ts b/packages/schematics/angular/migrations/update-14/remove-default-project-option_spec.ts new file mode 100644 index 000000000000..7b6eef0c4b30 --- /dev/null +++ b/packages/schematics/angular/migrations/update-14/remove-default-project-option_spec.ts @@ -0,0 +1,51 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import { EmptyTree } from '@angular-devkit/schematics'; +import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; +import { WorkspaceSchema } from '../../utility/workspace-models'; + +describe(`Migration to remove 'defaultProject' option.`, () => { + const schematicName = 'remove-default-project-option'; + const schematicRunner = new SchematicTestRunner( + 'migrations', + require.resolve('../migration-collection.json'), + ); + + let tree: UnitTestTree; + beforeEach(() => { + tree = new UnitTestTree(new EmptyTree()); + }); + + it(`should remove 'defaultProject'`, async () => { + const angularConfig: WorkspaceSchema = { + version: 1, + projects: {}, + defaultProject: 'foo', + }; + + tree.create('/angular.json', JSON.stringify(angularConfig, undefined, 2)); + const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise(); + const { defaultProject } = JSON.parse(newTree.readContent('/angular.json')); + + expect(defaultProject).toBeUndefined(); + }); + + it(`should not error when 'defaultProject' is not defined`, async () => { + const angularConfig: WorkspaceSchema = { + version: 1, + projects: {}, + }; + + tree.create('/angular.json', JSON.stringify(angularConfig, undefined, 2)); + const newTree = await schematicRunner.runSchematicAsync(schematicName, {}, tree).toPromise(); + const { defaultProject } = JSON.parse(newTree.readContent('/angular.json')); + + expect(defaultProject).toBeUndefined(); + }); +}); diff --git a/tests/legacy-cli/e2e/tests/misc/multiple-targets.ts b/tests/legacy-cli/e2e/tests/misc/multiple-targets.ts index 5ac349343166..7ff7e32087e0 100644 --- a/tests/legacy-cli/e2e/tests/misc/multiple-targets.ts +++ b/tests/legacy-cli/e2e/tests/misc/multiple-targets.ts @@ -5,10 +5,6 @@ import { updateJsonFile } from '../../utils/project'; export default async function () { await ng('generate', 'app', 'secondary-app'); - await updateJsonFile('angular.json', workspaceJson => { - workspaceJson.defaultProject = undefined; - }); - await ng('build', 'secondary-app', '--configuration=development'); expectFileToExist('dist/secondary-app/index.html');