Skip to content

Commit

Permalink
fix(core): convert-to-monorepo support for root project without proje…
Browse files Browse the repository at this point in the history
…ct.json (#26507)

This PR fixes `convert-to-monorepo` generator, so it works after `nx
init` on a single project.

## Current Behavior

If you use :

```
npm create vite react-app -- --template=react-ts
cd react-app
npx nx init
```

Then, you'll get an error when running `nx g convert-to-monorepo`.

```
 NX   The following projects are defined in multiple locations:

- react-app:
  - .
  - packages/react-app

To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.

MultipleProjectsWithSameNameError: The following projects are defined in multiple locations:
- react-app:
  - .
  - packages/react-app
  - 
```

## Expected Behavior
The generator should work, and you can run commands successfully
afterwards (e.g. `nx serve react-app`).

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
  • Loading branch information
jaysoo authored Jun 12, 2024
1 parent 07fa8a6 commit c86de97
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import 'nx/src/internal-testing-utils/mock-project-graph';

import {
readJson,
readProjectConfiguration,
Tree,
updateJson,
} from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { monorepoGenerator } from './convert-to-monorepo';

describe('monorepo generator', () => {
let tree: Tree;
beforeEach(() => {
tree = createTreeWithEmptyWorkspace();
});

it('should convert a root package without a project.json', async () => {
updateJson(tree, 'package.json', (json) => {
json.name = 'demo';
// Make this a root project
json.nx = {};
return json;
});

await monorepoGenerator(tree, {});

expect(tree.exists('packages/demo/project.json')).toBeTruthy();
expect(readProjectConfiguration(tree, 'demo')).toMatchObject({
name: 'demo',
});
expect(readJson(tree, 'package.json').name).toBe('@demo/source');
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'nx/src/internal-testing-utils/mock-project-graph';

import { readJson, readProjectConfiguration, Tree } from '@nx/devkit';
import { readProjectConfiguration, Tree } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { monorepoGenerator } from './convert-to-monorepo';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import {
ProjectConfiguration,
readNxJson,
Tree,
updateJson,
updateNxJson,
writeJson,
} from '@nx/devkit';
import { moveGenerator } from '../move/move';

Expand Down Expand Up @@ -34,6 +36,19 @@ export async function monorepoGenerator(tree: Tree, options: {}) {
const appsDir = isRootProjectApp ? 'apps' : 'packages';
const libsDir = isRootProjectApp ? 'libs' : 'packages';

if (rootProject) {
// If project was created using `nx init` then it might not have project.json.
// Need to create one to avoid name conflicts with root package.json.
if (!tree.exists('project.json')) {
writeJson(tree, 'project.json', { name: rootProject.name });
}
updateJson(tree, 'package.json', (json) => {
// Avoid name conflicts once we move root project into its own folder.
json.name = `@${rootProject.name}/source`;
return json;
});
}

for (const project of projectsToMove) {
await moveGenerator(tree, {
projectName: project.name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@ export function moveProjectFiles(
const knownRootProjectFiles = [
// Config files
'project.json',
'tsconfig.json',
'tsconfig.app.json',
'tsconfig.lib.json',
'tsconfig.spec.json',
/^tsconfig(?!\.base\.json$)((\..+)?\.json$|json$)/,
'.babelrc',
'.eslintrc.json',
'eslint.config.js',
Expand Down

0 comments on commit c86de97

Please sign in to comment.