Skip to content

Commit 3f35418

Browse files
leosvelperezFrozenPandaz
authored andcommitted
fix(misc): handle moving to a subfolder which results in the same project name and normalize import path (#6507)
1 parent a7e76b6 commit 3f35418

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+587
-473
lines changed

docs/angular/api-angular/generators/move.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@ Type: `string`
5656

5757
The new import path to use in the `tsconfig.base.json`.
5858

59+
### skipFormat
60+
61+
Alias(es): skip-format
62+
63+
Default: `false`
64+
65+
Type: `boolean`
66+
67+
Skip formatting files.
68+
5969
### updateImportPath
6070

6171
Default: `true`

docs/node/api-angular/generators/move.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@ Type: `string`
5656

5757
The new import path to use in the `tsconfig.base.json`.
5858

59+
### skipFormat
60+
61+
Alias(es): skip-format
62+
63+
Default: `false`
64+
65+
Type: `boolean`
66+
67+
Skip formatting files.
68+
5969
### updateImportPath
6070

6171
Default: `true`

docs/react/api-angular/generators/move.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@ Type: `string`
5656

5757
The new import path to use in the `tsconfig.base.json`.
5858

59+
### skipFormat
60+
61+
Alias(es): skip-format
62+
63+
Default: `false`
64+
65+
Type: `boolean`
66+
67+
Skip formatting files.
68+
5969
### updateImportPath
6070

6171
Default: `true`

e2e/workspace/src/workspace-aux-commands.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,7 @@ describe('Move Angular Project', () => {
715715
const lib2FilePath = `libs/${lib2}/src/lib/${lib2}.module.ts`;
716716
const lib2File = readFile(lib2FilePath);
717717
expect(lib2File).toContain(
718-
`import { ${newModule} } from '@${proj}/shared/${lib1}';`
718+
`import { ${newModule} } from '@${proj}/shared-${lib1}';`
719719
);
720720
expect(lib2File).toContain(`extends ${newModule}`);
721721
});
@@ -834,7 +834,7 @@ describe('Move Project', () => {
834834
rootTsConfig.compilerOptions.paths[`@${proj}/${lib1}/data-access`]
835835
).toBeUndefined();
836836
expect(
837-
rootTsConfig.compilerOptions.paths[`@${proj}/shared/${lib1}/data-access`]
837+
rootTsConfig.compilerOptions.paths[`@${proj}/shared-${lib1}-data-access`]
838838
).toEqual([`libs/shared/${lib1}/data-access/src/index.ts`]);
839839

840840
expect(moveOutput).toContain(`UPDATE workspace.json`);
@@ -854,7 +854,7 @@ describe('Move Project', () => {
854854
const lib2FilePath = `libs/${lib2}/ui/src/lib/${lib2}-ui.ts`;
855855
const lib2File = readFile(lib2FilePath);
856856
expect(lib2File).toContain(
857-
`import { fromLibOne } from '@${proj}/shared/${lib1}/data-access';`
857+
`import { fromLibOne } from '@${proj}/shared-${lib1}-data-access';`
858858
);
859859
});
860860

@@ -970,7 +970,7 @@ describe('Move Project', () => {
970970
rootTsConfig.compilerOptions.paths[`@${proj}/${lib1}/data-access`]
971971
).toBeUndefined();
972972
expect(
973-
rootTsConfig.compilerOptions.paths[`@${proj}/shared/${lib1}/data-access`]
973+
rootTsConfig.compilerOptions.paths[`@${proj}/shared-${lib1}-data-access`]
974974
).toEqual([`libs/shared/${lib1}/data-access/src/index.ts`]);
975975

976976
expect(moveOutput).toContain(`UPDATE workspace.json`);
@@ -991,7 +991,7 @@ describe('Move Project', () => {
991991
const lib2FilePath = `libs/${lib2}/ui/src/lib/${lib2}-ui.ts`;
992992
const lib2File = readFile(lib2FilePath);
993993
expect(lib2File).toContain(
994-
`import { fromLibOne } from '@${proj}/shared/${lib1}/data-access';`
994+
`import { fromLibOne } from '@${proj}/shared-${lib1}-data-access';`
995995
);
996996
});
997997

@@ -1109,7 +1109,7 @@ describe('Move Project', () => {
11091109
rootTsConfig.compilerOptions.paths[`@${proj}/${lib1}/data-access`]
11101110
).toBeUndefined();
11111111
expect(
1112-
rootTsConfig.compilerOptions.paths[`@${proj}/shared/${lib1}/data-access`]
1112+
rootTsConfig.compilerOptions.paths[`@${proj}/shared-${lib1}-data-access`]
11131113
).toEqual([`packages/shared/${lib1}/data-access/src/index.ts`]);
11141114

11151115
expect(moveOutput).toContain(`UPDATE workspace.json`);
@@ -1129,7 +1129,7 @@ describe('Move Project', () => {
11291129
const lib2FilePath = `packages/${lib2}/ui/src/lib/${lib2}-ui.ts`;
11301130
const lib2File = readFile(lib2FilePath);
11311131
expect(lib2File).toContain(
1132-
`import { fromLibOne } from '@${proj}/shared/${lib1}/data-access';`
1132+
`import { fromLibOne } from '@${proj}/shared-${lib1}-data-access';`
11331133
);
11341134

11351135
nxJson = readJson('nx.json');

packages/angular/src/generators/move/lib/update-module-name.spec.ts

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,30 @@ import { UnitTestRunner } from '../../../utils/test-runners';
1010
describe('updateModuleName Rule', () => {
1111
let tree: Tree;
1212

13+
beforeEach(() => {
14+
tree = createTreeWithEmptyWorkspace();
15+
});
16+
17+
it('should handle nesting resulting in the same project name', async () => {
18+
const updatedModulePath = '/libs/my/first/src/lib/my-first.module.ts';
19+
await libraryGenerator(tree, {
20+
name: 'my-first',
21+
simpleModuleName: true,
22+
});
23+
const schema: Schema = {
24+
projectName: 'my-first',
25+
destination: 'my/first',
26+
updateImportPath: true,
27+
};
28+
await moveGenerator(tree, schema);
29+
30+
updateModuleName(tree, { ...schema, destination: 'my/first' });
31+
32+
expect(tree.exists(updatedModulePath)).toBe(true);
33+
const moduleFile = tree.read(updatedModulePath).toString('utf-8');
34+
expect(moduleFile).toContain(`export class MyFirstModule { }`);
35+
});
36+
1337
describe('move to subfolder', () => {
1438
const updatedModulePath =
1539
'/libs/shared/my-first/src/lib/shared-my-first.module.ts';
@@ -25,8 +49,6 @@ describe('updateModuleName Rule', () => {
2549
};
2650

2751
beforeEach(async () => {
28-
tree = createTreeWithEmptyWorkspace();
29-
3052
await libraryGenerator(tree, {
3153
name: 'my-first',
3254
buildable: false,
@@ -86,7 +108,7 @@ describe('updateModuleName Rule', () => {
86108
});
87109

88110
it('should rename the module files and update the module name', async () => {
89-
await updateModuleName(tree, schema);
111+
updateModuleName(tree, schema);
90112

91113
expect(tree.exists(updatedModulePath)).toBe(true);
92114
expect(tree.exists(updatedModuleSpecPath)).toBe(true);
@@ -108,26 +130,27 @@ describe('updateModuleName Rule', () => {
108130
});
109131

110132
it('should update any references to the module', async () => {
111-
await updateModuleName(tree, schema);
133+
updateModuleName(tree, schema);
112134

113135
const importerFile = tree.read(secondModulePath).toString('utf-8');
114136
expect(importerFile).toContain(
115-
`import { SharedMyFirstModule } from '@proj/shared/my-first';`
137+
`import { SharedMyFirstModule } from '@proj/shared-my-first';`
116138
);
117139
expect(importerFile).toContain(
118140
`export class MySecondModule extends SharedMyFirstModule {}`
119141
);
120142
});
121143

122144
it('should update the index.ts file which exports the module', async () => {
123-
await updateModuleName(tree, schema);
145+
updateModuleName(tree, schema);
124146

125147
const indexFile = tree.read(indexPath).toString('utf-8');
126148
expect(indexFile).toContain(
127149
`export * from './lib/shared-my-first.module';`
128150
);
129151
});
130152
});
153+
131154
describe('rename', () => {
132155
const schema: Schema = {
133156
projectName: 'my-source',
@@ -142,8 +165,6 @@ describe('updateModuleName Rule', () => {
142165
const importerPath = '/libs/my-importer/src/lib/my-importing-file.ts';
143166

144167
beforeEach(async () => {
145-
tree = createTreeWithEmptyWorkspace();
146-
147168
// fake a mid-move tree:
148169
await libraryGenerator(tree, {
149170
name: 'my-destination',
@@ -211,7 +232,7 @@ describe('updateModuleName Rule', () => {
211232
});
212233

213234
it('should rename the module files and update the module name', async () => {
214-
await updateModuleName(tree, schema);
235+
updateModuleName(tree, schema);
215236

216237
expect(tree.exists(modulePath)).toBe(true);
217238
expect(tree.exists(moduleSpecPath)).toBe(true);
@@ -233,7 +254,7 @@ describe('updateModuleName Rule', () => {
233254
});
234255

235256
it('should update any references to the module', async () => {
236-
await updateModuleName(tree, schema);
257+
updateModuleName(tree, schema);
237258

238259
const importerFile = tree.read(importerPath).toString('utf-8');
239260
expect(importerFile).toContain(
@@ -245,7 +266,7 @@ describe('updateModuleName Rule', () => {
245266
});
246267

247268
it('should update the index.ts file which exports the module', async () => {
248-
await updateModuleName(tree, schema);
269+
updateModuleName(tree, schema);
249270

250271
const indexFile = tree.read(indexPath).toString('utf-8');
251272
expect(indexFile).toContain(

packages/angular/src/generators/move/lib/update-module-name.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
import { getNewProjectName } from '@nrwl/workspace/src/generators/move/lib/utils';
99
import { join } from 'path';
1010
import { Schema } from '../schema';
11+
1112
/**
1213
* Updates the Angular module name (including the spec file and index.ts)
1314
*
@@ -16,18 +17,18 @@ import { Schema } from '../schema';
1617
*
1718
* @param schema The options provided to the schematic
1819
*/
19-
export async function updateModuleName(
20+
export function updateModuleName(
2021
tree: Tree,
2122
{ projectName, destination }: Schema
22-
) {
23+
): void {
2324
const newProjectName = getNewProjectName(destination);
2425

2526
const project = readProjectConfiguration(tree, newProjectName);
2627

2728
if (project.projectType === 'application') {
2829
// Expect the module to be something like 'app.module.ts' regardless of the folder name,
2930
// Therefore, nothing to do.
30-
return tree;
31+
return;
3132
}
3233

3334
const moduleName = {
@@ -53,7 +54,11 @@ export async function updateModuleName(
5354
from: `${project.sourceRoot}/lib/${moduleFile.from}.spec.ts`,
5455
to: `${project.sourceRoot}/lib/${moduleFile.to}.spec.ts`,
5556
},
56-
];
57+
].filter((rename) => rename.from !== rename.to);
58+
59+
if (filesToRename.length === 0) {
60+
return;
61+
}
5762

5863
const replacements = [
5964
{
@@ -84,8 +89,7 @@ export async function updateModuleName(
8489
const skipFiles = [...filesToRename.map((file) => file.to), indexFile];
8590

8691
// Update any files which import the module
87-
88-
for (const [name, definition] of getProjects(tree)) {
92+
for (const [, definition] of getProjects(tree)) {
8993
visitNotIgnoredFiles(tree, definition.root, (file) => {
9094
// skip files that were already modified
9195

@@ -97,6 +101,7 @@ export async function updateModuleName(
97101
});
98102
}
99103
}
104+
100105
function updateFileContent(
101106
tree: Tree,
102107
replacements: { regex: RegExp; replaceWith: string }[],

packages/angular/src/generators/move/move.spec.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Tree } from '@nrwl/devkit';
2+
import * as devkit from '@nrwl/devkit';
23
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
34
import { angularMoveGenerator } from './move';
45
import libraryGenerator from '../library/library';
@@ -21,6 +22,8 @@ describe('@nrwl/angular:move', () => {
2122
skipFormat: false,
2223
unitTestRunner: UnitTestRunner.Jest,
2324
});
25+
26+
jest.clearAllMocks();
2427
});
2528

2629
it('should move a project', async () => {
@@ -34,4 +37,29 @@ describe('@nrwl/angular:move', () => {
3437
true
3538
);
3639
});
40+
41+
it('should format files', async () => {
42+
jest.spyOn(devkit, 'formatFiles');
43+
44+
await angularMoveGenerator(tree, {
45+
projectName: 'mylib',
46+
destination: 'mynewlib',
47+
updateImportPath: true,
48+
});
49+
50+
expect(devkit.formatFiles).toHaveBeenCalled();
51+
});
52+
53+
it('should not format files when --skipFormat=true', async () => {
54+
jest.spyOn(devkit, 'formatFiles');
55+
56+
await angularMoveGenerator(tree, {
57+
projectName: 'mylib',
58+
destination: 'mynewlib',
59+
updateImportPath: true,
60+
skipFormat: true,
61+
});
62+
63+
expect(devkit.formatFiles).not.toHaveBeenCalled();
64+
});
3765
});
Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { convertNxGenerator, Tree } from '@nrwl/devkit';
1+
import { convertNxGenerator, formatFiles, Tree } from '@nrwl/devkit';
22
import { moveGenerator } from '@nrwl/workspace';
33
import { updateModuleName } from './lib/update-module-name';
44
import { Schema } from './schema';
@@ -10,10 +10,16 @@ import { Schema } from './schema';
1010
* to the workspace, so it can't use the same tricks as the `@nrwl/workspace` rules
1111
* to get the before and after names and paths.
1212
*/
13+
export async function angularMoveGenerator(
14+
tree: Tree,
15+
schema: Schema
16+
): Promise<void> {
17+
await moveGenerator(tree, { ...schema, skipFormat: true });
18+
updateModuleName(tree, schema);
1319

14-
export async function angularMoveGenerator(tree: Tree, schema: Schema) {
15-
await moveGenerator(tree, schema);
16-
await updateModuleName(tree, schema);
20+
if (!schema.skipFormat) {
21+
await formatFiles(tree);
22+
}
1723
}
1824

1925
export const angularMoveSchematic = convertNxGenerator(angularMoveGenerator);
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export interface Schema {
22
projectName: string;
33
destination: string;
4-
importPath?: string;
54
updateImportPath: boolean;
5+
importPath?: string;
6+
skipFormat?: boolean;
67
}

packages/angular/src/generators/move/schema.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@
3333
"type": "boolean",
3434
"description": "Update the import path to reflect the new location.",
3535
"default": true
36+
},
37+
"skipFormat": {
38+
"type": "boolean",
39+
"aliases": ["skip-format"],
40+
"description": "Skip formatting files.",
41+
"default": false
3642
}
3743
},
3844
"required": ["projectName", "destination"]

0 commit comments

Comments
 (0)