Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(misc): handle moving to a subfolder which results in the same project name and normalize import path #6507

Merged
merged 1 commit into from
Jul 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/angular/api-angular/generators/move.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ Type: `string`

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

### skipFormat

Alias(es): skip-format

Default: `false`

Type: `boolean`

Skip formatting files.

### updateImportPath

Default: `true`
Expand Down
10 changes: 10 additions & 0 deletions docs/node/api-angular/generators/move.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ Type: `string`

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

### skipFormat

Alias(es): skip-format

Default: `false`

Type: `boolean`

Skip formatting files.

### updateImportPath

Default: `true`
Expand Down
10 changes: 10 additions & 0 deletions docs/react/api-angular/generators/move.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ Type: `string`

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

### skipFormat

Alias(es): skip-format

Default: `false`

Type: `boolean`

Skip formatting files.

### updateImportPath

Default: `true`
Expand Down
14 changes: 7 additions & 7 deletions e2e/workspace/src/workspace-aux-commands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,7 @@ describe('Move Angular Project', () => {
const lib2FilePath = `libs/${lib2}/src/lib/${lib2}.module.ts`;
const lib2File = readFile(lib2FilePath);
expect(lib2File).toContain(
`import { ${newModule} } from '@${proj}/shared/${lib1}';`
`import { ${newModule} } from '@${proj}/shared-${lib1}';`
);
expect(lib2File).toContain(`extends ${newModule}`);
});
Expand Down Expand Up @@ -834,7 +834,7 @@ describe('Move Project', () => {
rootTsConfig.compilerOptions.paths[`@${proj}/${lib1}/data-access`]
).toBeUndefined();
expect(
rootTsConfig.compilerOptions.paths[`@${proj}/shared/${lib1}/data-access`]
rootTsConfig.compilerOptions.paths[`@${proj}/shared-${lib1}-data-access`]
).toEqual([`libs/shared/${lib1}/data-access/src/index.ts`]);

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

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

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

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

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

nxJson = readJson('nx.json');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,30 @@ import { UnitTestRunner } from '../../../utils/test-runners';
describe('updateModuleName Rule', () => {
let tree: Tree;

beforeEach(() => {
tree = createTreeWithEmptyWorkspace();
});

it('should handle nesting resulting in the same project name', async () => {
const updatedModulePath = '/libs/my/first/src/lib/my-first.module.ts';
await libraryGenerator(tree, {
name: 'my-first',
simpleModuleName: true,
});
const schema: Schema = {
projectName: 'my-first',
destination: 'my/first',
updateImportPath: true,
};
await moveGenerator(tree, schema);

updateModuleName(tree, { ...schema, destination: 'my/first' });

expect(tree.exists(updatedModulePath)).toBe(true);
const moduleFile = tree.read(updatedModulePath).toString('utf-8');
expect(moduleFile).toContain(`export class MyFirstModule { }`);
});

describe('move to subfolder', () => {
const updatedModulePath =
'/libs/shared/my-first/src/lib/shared-my-first.module.ts';
Expand All @@ -25,8 +49,6 @@ describe('updateModuleName Rule', () => {
};

beforeEach(async () => {
tree = createTreeWithEmptyWorkspace();

await libraryGenerator(tree, {
name: 'my-first',
buildable: false,
Expand Down Expand Up @@ -86,7 +108,7 @@ describe('updateModuleName Rule', () => {
});

it('should rename the module files and update the module name', async () => {
await updateModuleName(tree, schema);
updateModuleName(tree, schema);

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

it('should update any references to the module', async () => {
await updateModuleName(tree, schema);
updateModuleName(tree, schema);

const importerFile = tree.read(secondModulePath).toString('utf-8');
expect(importerFile).toContain(
`import { SharedMyFirstModule } from '@proj/shared/my-first';`
`import { SharedMyFirstModule } from '@proj/shared-my-first';`
);
expect(importerFile).toContain(
`export class MySecondModule extends SharedMyFirstModule {}`
);
});

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

const indexFile = tree.read(indexPath).toString('utf-8');
expect(indexFile).toContain(
`export * from './lib/shared-my-first.module';`
);
});
});

describe('rename', () => {
const schema: Schema = {
projectName: 'my-source',
Expand All @@ -142,8 +165,6 @@ describe('updateModuleName Rule', () => {
const importerPath = '/libs/my-importer/src/lib/my-importing-file.ts';

beforeEach(async () => {
tree = createTreeWithEmptyWorkspace();

// fake a mid-move tree:
await libraryGenerator(tree, {
name: 'my-destination',
Expand Down Expand Up @@ -211,7 +232,7 @@ describe('updateModuleName Rule', () => {
});

it('should rename the module files and update the module name', async () => {
await updateModuleName(tree, schema);
updateModuleName(tree, schema);

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

it('should update any references to the module', async () => {
await updateModuleName(tree, schema);
updateModuleName(tree, schema);

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

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

const indexFile = tree.read(indexPath).toString('utf-8');
expect(indexFile).toContain(
Expand Down
17 changes: 11 additions & 6 deletions packages/angular/src/generators/move/lib/update-module-name.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { getNewProjectName } from '@nrwl/workspace/src/generators/move/lib/utils';
import { join } from 'path';
import { Schema } from '../schema';

/**
* Updates the Angular module name (including the spec file and index.ts)
*
Expand All @@ -16,18 +17,18 @@ import { Schema } from '../schema';
*
* @param schema The options provided to the schematic
*/
export async function updateModuleName(
export function updateModuleName(
tree: Tree,
{ projectName, destination }: Schema
) {
): void {
const newProjectName = getNewProjectName(destination);

const project = readProjectConfiguration(tree, newProjectName);

if (project.projectType === 'application') {
// Expect the module to be something like 'app.module.ts' regardless of the folder name,
// Therefore, nothing to do.
return tree;
return;
}

const moduleName = {
Expand All @@ -53,7 +54,11 @@ export async function updateModuleName(
from: `${project.sourceRoot}/lib/${moduleFile.from}.spec.ts`,
to: `${project.sourceRoot}/lib/${moduleFile.to}.spec.ts`,
},
];
].filter((rename) => rename.from !== rename.to);

if (filesToRename.length === 0) {
return;
}

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

// Update any files which import the module

for (const [name, definition] of getProjects(tree)) {
for (const [, definition] of getProjects(tree)) {
visitNotIgnoredFiles(tree, definition.root, (file) => {
// skip files that were already modified

Expand All @@ -97,6 +101,7 @@ export async function updateModuleName(
});
}
}

function updateFileContent(
tree: Tree,
replacements: { regex: RegExp; replaceWith: string }[],
Expand Down
28 changes: 28 additions & 0 deletions packages/angular/src/generators/move/move.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Tree } from '@nrwl/devkit';
import * as devkit from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { angularMoveGenerator } from './move';
import libraryGenerator from '../library/library';
Expand All @@ -21,6 +22,8 @@ describe('@nrwl/angular:move', () => {
skipFormat: false,
unitTestRunner: UnitTestRunner.Jest,
});

jest.clearAllMocks();
});

it('should move a project', async () => {
Expand All @@ -34,4 +37,29 @@ describe('@nrwl/angular:move', () => {
true
);
});

it('should format files', async () => {
jest.spyOn(devkit, 'formatFiles');

await angularMoveGenerator(tree, {
projectName: 'mylib',
destination: 'mynewlib',
updateImportPath: true,
});

expect(devkit.formatFiles).toHaveBeenCalled();
});

it('should not format files when --skipFormat=true', async () => {
jest.spyOn(devkit, 'formatFiles');

await angularMoveGenerator(tree, {
projectName: 'mylib',
destination: 'mynewlib',
updateImportPath: true,
skipFormat: true,
});

expect(devkit.formatFiles).not.toHaveBeenCalled();
});
});
14 changes: 10 additions & 4 deletions packages/angular/src/generators/move/move.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { convertNxGenerator, Tree } from '@nrwl/devkit';
import { convertNxGenerator, formatFiles, Tree } from '@nrwl/devkit';
import { moveGenerator } from '@nrwl/workspace';
import { updateModuleName } from './lib/update-module-name';
import { Schema } from './schema';
Expand All @@ -10,10 +10,16 @@ import { Schema } from './schema';
* to the workspace, so it can't use the same tricks as the `@nrwl/workspace` rules
* to get the before and after names and paths.
*/
export async function angularMoveGenerator(
tree: Tree,
schema: Schema
): Promise<void> {
await moveGenerator(tree, { ...schema, skipFormat: true });
updateModuleName(tree, schema);

export async function angularMoveGenerator(tree: Tree, schema: Schema) {
await moveGenerator(tree, schema);
await updateModuleName(tree, schema);
if (!schema.skipFormat) {
await formatFiles(tree);
}
}

export const angularMoveSchematic = convertNxGenerator(angularMoveGenerator);
3 changes: 2 additions & 1 deletion packages/angular/src/generators/move/schema.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export interface Schema {
projectName: string;
destination: string;
importPath?: string;
updateImportPath: boolean;
importPath?: string;
skipFormat?: boolean;
}
6 changes: 6 additions & 0 deletions packages/angular/src/generators/move/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@
"type": "boolean",
"description": "Update the import path to reflect the new location.",
"default": true
},
"skipFormat": {
"type": "boolean",
"aliases": ["skip-format"],
"description": "Skip formatting files.",
"default": false
}
},
"required": ["projectName", "destination"]
Expand Down
Loading