Skip to content

Commit e90d275

Browse files
committed
feat(ng-add): add logic for project selection
Since defaultProject is deprecated, the project must be determined differently. Variants: - Use the defaultProject if given (for compatibility) - Use the first project if only one is available - Use the project defined by the --project arg. - Throw an error.
1 parent 0a28c48 commit e90d275

File tree

3 files changed

+71
-22
lines changed

3 files changed

+71
-22
lines changed

src/__snapshots__/ng-add.spec.ts.snap

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
exports[`ng-add generating files generates new files if starting from scratch 1`] = `
44
"{
55
\\"version\\": 1,
6-
\\"defaultProject\\": \\"THEPROJECT\\",
76
\\"projects\\": {
87
\\"THEPROJECT\\": {
98
\\"projectType\\": \\"application\\",
@@ -37,7 +36,6 @@ exports[`ng-add generating files generates new files if starting from scratch 1`
3736
exports[`ng-add generating files overrides existing files 1`] = `
3837
"{
3938
\\"version\\": 1,
40-
\\"defaultProject\\": \\"THEPROJECT\\",
4139
\\"projects\\": {
4240
\\"THEPROJECT\\": {
4341
\\"projectType\\": \\"application\\",

src/ng-add.spec.ts

Lines changed: 66 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -39,27 +39,77 @@ describe('ng-add', () => {
3939
});
4040
});
4141

42+
describe('project selection', () => {
43+
it('should select the default project when not explicitly given (for compatibility!)', async () => {
44+
const tree = Tree.empty();
45+
const angularJSON = generateAngularJson();
46+
47+
(angularJSON as any).defaultProject = PROJECT_NAME; // explicitly set default project
48+
tree.create('angular.json', JSON.stringify(angularJSON));
49+
50+
const resultTree = await ngAdd({ project: '' })(
51+
tree,
52+
{} as SchematicContext
53+
);
54+
55+
const resultConfig = readJSONFromTree(resultTree, 'angular.json');
56+
expect(resultConfig.projects[PROJECT_NAME].architect.deploy).toBeTruthy();
57+
expect(
58+
resultConfig.projects[OTHER_PROJECT_NAME].architect.deploy
59+
).toBeFalsy();
60+
});
61+
62+
it('should select the explicitly defined project', async () => {
63+
const tree = Tree.empty();
64+
const angularJSON = generateAngularJson();
65+
tree.create('angular.json', JSON.stringify(angularJSON));
66+
67+
const resultTree = await ngAdd({ project: OTHER_PROJECT_NAME })(
68+
tree,
69+
{} as SchematicContext
70+
);
71+
72+
const resultConfig = readJSONFromTree(resultTree, 'angular.json');
73+
expect(
74+
resultConfig.projects[OTHER_PROJECT_NAME].architect.deploy
75+
).toBeTruthy();
76+
expect(resultConfig.projects[PROJECT_NAME].architect.deploy).toBeFalsy();
77+
});
78+
79+
it('should select the first project if there is only one', async () => {
80+
const tree = Tree.empty();
81+
const angularJSON = generateAngularJson();
82+
delete (angularJSON as any).projects[PROJECT_NAME]; // delete one project so that one is left
83+
tree.create('angular.json', JSON.stringify(angularJSON));
84+
85+
const resultTree = await ngAdd({ project: '' })(
86+
tree,
87+
{} as SchematicContext
88+
);
89+
90+
const resultConfig = readJSONFromTree(resultTree, 'angular.json');
91+
expect(
92+
resultConfig.projects[OTHER_PROJECT_NAME].architect.deploy
93+
).toBeTruthy();
94+
});
95+
});
96+
4297
describe('error handling', () => {
43-
it('should fail if project not defined', async () => {
98+
it('should fail if there are multiple projects in workspace and project is not explicitly defined', async () => {
4499
const tree = Tree.empty();
45100
const angularJSON = generateAngularJson();
46-
delete angularJSON.defaultProject;
47101
tree.create('angular.json', JSON.stringify(angularJSON));
48102

49103
await expect(
50-
ngAdd({
51-
project: ''
52-
})(tree, {} as SchematicContext)
104+
ngAdd({ project: '' })(tree, {} as SchematicContext)
53105
).rejects.toThrowError(
54-
'No Angular project selected and no default project in the workspace'
106+
'There is more than one project in your workspace. Please select it manually by using the --project argument.'
55107
);
56108
});
57109

58110
it('should throw if angular.json not found', async () => {
59111
await expect(
60-
ngAdd({
61-
project: PROJECT_NAME
62-
})(Tree.empty(), {} as SchematicContext)
112+
ngAdd({ project: PROJECT_NAME })(Tree.empty(), {} as SchematicContext)
63113
).rejects.toThrowError('Unable to determine format for workspace path.');
64114
});
65115

@@ -68,9 +118,7 @@ describe('ng-add', () => {
68118
tree.create('angular.json', 'hi');
69119

70120
await expect(
71-
ngAdd({
72-
project: PROJECT_NAME
73-
})(tree, {} as SchematicContext)
121+
ngAdd({ project: PROJECT_NAME })(tree, {} as SchematicContext)
74122
).rejects.toThrowError('Invalid JSON character: "h" at 0:0.');
75123
});
76124

@@ -79,9 +127,7 @@ describe('ng-add', () => {
79127
tree.create('angular.json', JSON.stringify({ version: 1, projects: {} }));
80128

81129
await expect(
82-
ngAdd({
83-
project: PROJECT_NAME
84-
})(tree, {} as SchematicContext)
130+
ngAdd({ project: PROJECT_NAME })(tree, {} as SchematicContext)
85131
).rejects.toThrowError(
86132
'The specified Angular project is not defined in this workspace'
87133
);
@@ -98,9 +144,7 @@ describe('ng-add', () => {
98144
);
99145

100146
await expect(
101-
ngAdd({
102-
project: PROJECT_NAME
103-
})(tree, {} as SchematicContext)
147+
ngAdd({ project: PROJECT_NAME })(tree, {} as SchematicContext)
104148
).rejects.toThrowError(
105149
'Deploy requires an Angular project type of "application" in angular.json'
106150
);
@@ -131,10 +175,13 @@ function prettifyJSON(json: string) {
131175
return JSON.stringify(JSON.parse(json), null, 2);
132176
}
133177

178+
function readJSONFromTree(tree: Tree, file: string) {
179+
return JSON.parse(tree.read(file)!.toString());
180+
}
181+
134182
function generateAngularJson() {
135183
return {
136184
version: 1,
137-
defaultProject: PROJECT_NAME as string | undefined,
138185
projects: {
139186
[PROJECT_NAME]: {
140187
projectType: 'application',

src/ng-add.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@ export const ngAdd = (options: NgAddOptions) => async (
1818
const { workspace } = await workspaces.readWorkspace('/', host);
1919

2020
if (!options.project) {
21+
// TODO: defaultProject is deprecated as for Angular 14. Remove support here when officially removed from Angular.
2122
if (workspace.extensions.defaultProject) {
2223
options.project = workspace.extensions.defaultProject as string;
24+
} else if (workspace.projects.size === 1) {
25+
// If there is only one project, return that one.
26+
options.project = Array.from(workspace.projects.keys())[0];
2327
} else {
2428
throw new SchematicsException(
25-
'No Angular project selected and no default project in the workspace'
29+
'There is more than one project in your workspace. Please select it manually by using the --project argument.'
2630
);
2731
}
2832
}

0 commit comments

Comments
 (0)