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): fix moving projects with standalone configuration #6521

Merged
merged 1 commit into from Jul 29, 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 20 additions & 0 deletions docs/angular/api-nx-devkit/index.md
Expand Up @@ -72,6 +72,7 @@
- [getWorkspaceLayout](../../angular/nx-devkit/index#getworkspacelayout)
- [getWorkspacePath](../../angular/nx-devkit/index#getworkspacepath)
- [installPackagesTask](../../angular/nx-devkit/index#installpackagestask)
- [isStandaloneProject](../../angular/nx-devkit/index#isstandaloneproject)
- [joinPathFragments](../../angular/nx-devkit/index#joinpathfragments)
- [moveFilesToNewDirectory](../../angular/nx-devkit/index#movefilestonewdirectory)
- [names](../../angular/nx-devkit/index#names)
Expand Down Expand Up @@ -886,6 +887,25 @@ Runs `npm install` or `yarn install`. It will skip running the install if

---

### isStandaloneProject

▸ **isStandaloneProject**(`host`, `project`): `boolean`

Returns if a project has a standalone configuration (project.json).

#### Parameters

| Name | Type | Description |
| :-------- | :------------------------------------------- | :------------------- |
| `host` | [`Tree`](../../angular/nx-devkit/index#tree) | the file system tree |
| `project` | `string` | the project name |

#### Returns

`boolean`

---

### joinPathFragments

▸ **joinPathFragments**(...`fragments`): `string`
Expand Down
20 changes: 20 additions & 0 deletions docs/node/api-nx-devkit/index.md
Expand Up @@ -72,6 +72,7 @@
- [getWorkspaceLayout](../../node/nx-devkit/index#getworkspacelayout)
- [getWorkspacePath](../../node/nx-devkit/index#getworkspacepath)
- [installPackagesTask](../../node/nx-devkit/index#installpackagestask)
- [isStandaloneProject](../../node/nx-devkit/index#isstandaloneproject)
- [joinPathFragments](../../node/nx-devkit/index#joinpathfragments)
- [moveFilesToNewDirectory](../../node/nx-devkit/index#movefilestonewdirectory)
- [names](../../node/nx-devkit/index#names)
Expand Down Expand Up @@ -886,6 +887,25 @@ Runs `npm install` or `yarn install`. It will skip running the install if

---

### isStandaloneProject

▸ **isStandaloneProject**(`host`, `project`): `boolean`

Returns if a project has a standalone configuration (project.json).

#### Parameters

| Name | Type | Description |
| :-------- | :---------------------------------------- | :------------------- |
| `host` | [`Tree`](../../node/nx-devkit/index#tree) | the file system tree |
| `project` | `string` | the project name |

#### Returns

`boolean`

---

### joinPathFragments

▸ **joinPathFragments**(...`fragments`): `string`
Expand Down
20 changes: 20 additions & 0 deletions docs/react/api-nx-devkit/index.md
Expand Up @@ -72,6 +72,7 @@
- [getWorkspaceLayout](../../react/nx-devkit/index#getworkspacelayout)
- [getWorkspacePath](../../react/nx-devkit/index#getworkspacepath)
- [installPackagesTask](../../react/nx-devkit/index#installpackagestask)
- [isStandaloneProject](../../react/nx-devkit/index#isstandaloneproject)
- [joinPathFragments](../../react/nx-devkit/index#joinpathfragments)
- [moveFilesToNewDirectory](../../react/nx-devkit/index#movefilestonewdirectory)
- [names](../../react/nx-devkit/index#names)
Expand Down Expand Up @@ -886,6 +887,25 @@ Runs `npm install` or `yarn install`. It will skip running the install if

---

### isStandaloneProject

▸ **isStandaloneProject**(`host`, `project`): `boolean`

Returns if a project has a standalone configuration (project.json).

#### Parameters

| Name | Type | Description |
| :-------- | :----------------------------------------- | :------------------- |
| `host` | [`Tree`](../../react/nx-devkit/index#tree) | the file system tree |
| `project` | `string` | the project name |

#### Returns

`boolean`

---

### joinPathFragments

▸ **joinPathFragments**(...`fragments`): `string`
Expand Down
1 change: 1 addition & 0 deletions packages/devkit/index.ts
Expand Up @@ -41,6 +41,7 @@ export {
readWorkspaceConfiguration,
updateWorkspaceConfiguration,
getProjects,
isStandaloneProject,
} from './src/generators/project-configuration';
export { toJS } from './src/generators/to-js';
export { updateTsConfigsToJs } from './src/generators/update-ts-configs-to-js';
Expand Down
16 changes: 16 additions & 0 deletions packages/devkit/src/generators/project-configuration.ts
Expand Up @@ -205,6 +205,22 @@ export function readProjectConfiguration(
return getProjectConfiguration(host, projectName, workspace, nxJson);
}

/**
* Returns if a project has a standalone configuration (project.json).
*
* @param host - the file system tree
* @param project - the project name
*/
export function isStandaloneProject(host: Tree, project: string): boolean {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we remove this and use getWorkspaceLayout(host).standaloneAsDefault instead?

const rawWorkspace = readJson<RawWorkspaceJsonConfiguration>(
host,
getWorkspacePath(host)
);
const projectConfig = rawWorkspace.projects?.[project];

return typeof projectConfig === 'string';
}

function getProjectConfiguration(
host: Tree,
projectName: string,
Expand Down
Expand Up @@ -188,4 +188,36 @@ describe('moveProjectConfiguration', () => {
expect(actualProject.implicitDependencies).toEqual(['my-other-lib']);
expect(readJson(tree, 'nx.json').projects['my-source']).not.toBeDefined();
});

it('should support moving a standalone project', () => {
const projectName = 'standalone';
const newProjectName = 'parent-standalone';
addProjectConfiguration(
tree,
projectName,
{
projectType: 'library',
root: 'libs/standalone',
targets: {},
},
true
);
const moveSchema: NormalizedSchema = {
projectName: 'standalone',
destination: 'parent/standalone',
importPath: '@proj/parent-standalone',
newProjectName,
relativeToRootDestination: 'libs/parent/standalone',
updateImportPath: true,
};

moveProjectConfiguration(tree, moveSchema, projectConfig);

expect(() => {
readProjectConfiguration(tree, projectName);
}).toThrow();
const ws = readJson(tree, 'workspace.json');
expect(typeof ws.projects[newProjectName]).toBe('string');
expect(readProjectConfiguration(tree, newProjectName)).toBeDefined();
});
});
@@ -1,5 +1,6 @@
import {
addProjectConfiguration,
isStandaloneProject,
NxJsonProjectConfiguration,
ProjectConfiguration,
removeProjectConfiguration,
Expand All @@ -12,6 +13,7 @@ export function moveProjectConfiguration(
schema: NormalizedSchema,
projectConfig: ProjectConfiguration & NxJsonProjectConfiguration
) {
const isStandalone = isStandaloneProject(tree, schema.projectName);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use getWorkspaceLayout(host).standaloneAsDefault so we don't have to add the new function?

It should work in this case because the current move logic already moves the project.json file appropriately.

From what I saw, this could also be solved somewhat hackily by moving addProjectConfiguration after removeProjectConfiguration. But I think reading whether it should be standalone or not and then explicitly saying to add a standalone is a better option.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That wouldn't be right for a couple of reasons:

  • getWorkspaceLayout(host).standaloneAsDefault will only be true if all projects in the workspace are configured as standalone, you'd expect that to normally be the case, either all or none, but that's an assumption, not a fact. Even our generator to convert projects into standalone config offers the ability to specify a project, it's not mandatory to convert the whole workspace.
  • It can't be solved by having addProjectConfiguration before removeProjectConfiguration, because there are cases where the project name for the destination is the same as the old destination (e.g. moving domain-project to domain/project, both results in the name domain-project). A couple of issues have been created because of that, and I previously worked on solving those. In that scenario, if you try to add the project first, you get an error because it already exists.

The need here is to know if the project being moved is configured as standalone or not, that doesn't match what getWorkspaceLayout(host).standaloneAsDefault returns (whether all projects in the workspace are configured as standalone).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah okay, I see

const projectString = JSON.stringify(projectConfig);
const newProjectString = projectString.replace(
new RegExp(projectConfig.root, 'g'),
Expand All @@ -25,5 +27,10 @@ export function moveProjectConfiguration(
removeProjectConfiguration(tree, schema.projectName);

// Create a new project with the root replaced
addProjectConfiguration(tree, schema.newProjectName, newProject);
addProjectConfiguration(
tree,
schema.newProjectName,
newProject,
isStandalone
);
}