-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core): add convert-to-monorepo generator to convert from standal…
…one projects (#18245)
- Loading branch information
Showing
20 changed files
with
637 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
27 changes: 27 additions & 0 deletions
27
docs/generated/packages/workspace/generators/convert-to-monorepo.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"name": "convert-to-monorepo", | ||
"factory": "./src/generators/convert-to-monorepo/convert-to-monorepo", | ||
"schema": { | ||
"$schema": "http://json-schema.org/schema", | ||
"$id": "NxWorkspaceConvertToMonorepo", | ||
"cli": "nx", | ||
"title": "Nx Convert to Monorepo", | ||
"description": "Convert an Nx project to a monorepo.", | ||
"type": "object", | ||
"examples": [ | ||
{ | ||
"command": "nx g @nx/workspace:monorepo", | ||
"description": "Convert an Nx standalone project to a monorepo." | ||
} | ||
], | ||
"properties": {}, | ||
"required": [], | ||
"presets": [] | ||
}, | ||
"description": "Convert a Nx project to a monorepo.", | ||
"implementation": "/packages/workspace/src/generators/convert-to-monorepo/convert-to-monorepo.ts", | ||
"aliases": [], | ||
"hidden": false, | ||
"path": "/packages/workspace/src/generators/convert-to-monorepo/schema.json", | ||
"type": "generator" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
146 changes: 146 additions & 0 deletions
146
packages/workspace/src/generators/convert-to-monorepo/convert-to-monorepo.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
import { readJson, readProjectConfiguration, Tree } from '@nx/devkit'; | ||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; | ||
import { monorepoGenerator } from './convert-to-monorepo'; | ||
|
||
// nx-ignore-next-line | ||
const { libraryGenerator } = require('@nx/js'); | ||
// nx-ignore-next-line | ||
const { applicationGenerator: reactAppGenerator } = require('@nx/react'); | ||
// nx-ignore-next-line | ||
const { applicationGenerator: nextAppGenerator } = require('@nx/next'); | ||
|
||
describe('monorepo generator', () => { | ||
let tree: Tree; | ||
beforeEach(() => { | ||
tree = createTreeWithEmptyWorkspace(); | ||
}); | ||
|
||
it('should convert root JS lib', async () => { | ||
// Files that should not move | ||
tree.write('.gitignore', ''); | ||
tree.write('README.md', ''); | ||
tree.write('tools/scripts/custom_script.sh', ''); | ||
|
||
await libraryGenerator(tree, { name: 'my-lib', rootProject: true }); | ||
await libraryGenerator(tree, { name: 'other-lib' }); | ||
|
||
await monorepoGenerator(tree, { | ||
appsDir: 'apps', | ||
libsDir: 'packages', | ||
}); | ||
|
||
expect(readJson(tree, 'packages/my-lib/project.json')).toMatchObject({ | ||
sourceRoot: 'packages/my-lib/src', | ||
targets: { | ||
build: { | ||
executor: '@nx/js:tsc', | ||
options: { | ||
main: 'packages/my-lib/src/index.ts', | ||
tsConfig: 'packages/my-lib/tsconfig.lib.json', | ||
}, | ||
}, | ||
}, | ||
}); | ||
expect(readJson(tree, 'packages/other-lib/project.json')).toMatchObject({ | ||
sourceRoot: 'packages/other-lib/src', | ||
}); | ||
|
||
// Did not move files that don't belong to root project | ||
expect(tree.exists('.gitignore')).toBeTruthy(); | ||
expect(tree.exists('README.md')).toBeTruthy(); | ||
expect(tree.exists('tools/scripts/custom_script.sh')).toBeTruthy(); | ||
|
||
// Extracted base config files | ||
expect(tree.exists('tsconfig.base.json')).toBeTruthy(); | ||
}); | ||
|
||
it('should convert root React app (Vite, Vitest)', async () => { | ||
await reactAppGenerator(tree, { | ||
name: 'demo', | ||
style: 'css', | ||
bundler: 'vite', | ||
unitTestRunner: 'vitest', | ||
e2eTestRunner: 'none', | ||
linter: 'eslint', | ||
rootProject: true, | ||
}); | ||
|
||
await monorepoGenerator(tree, {}); | ||
|
||
expect(readJson(tree, 'apps/demo/project.json')).toMatchObject({ | ||
sourceRoot: 'apps/demo/src', | ||
}); | ||
|
||
// Extracted base config files | ||
expect(tree.exists('tsconfig.base.json')).toBeTruthy(); | ||
expect(tree.exists('.eslintrc.base.json')).toBeTruthy(); | ||
}); | ||
|
||
it('should convert root React app (Webpack, Jest)', async () => { | ||
await reactAppGenerator(tree, { | ||
name: 'demo', | ||
style: 'css', | ||
bundler: 'webpack', | ||
unitTestRunner: 'jest', | ||
e2eTestRunner: 'none', | ||
linter: 'eslint', | ||
rootProject: true, | ||
}); | ||
|
||
await monorepoGenerator(tree, {}); | ||
|
||
expect(readJson(tree, 'apps/demo/project.json')).toMatchObject({ | ||
sourceRoot: 'apps/demo/src', | ||
targets: { | ||
build: { | ||
executor: '@nx/webpack:webpack', | ||
options: { | ||
main: 'apps/demo/src/main.tsx', | ||
tsConfig: 'apps/demo/tsconfig.app.json', | ||
webpackConfig: 'apps/demo/webpack.config.js', | ||
}, | ||
}, | ||
test: { | ||
executor: '@nx/jest:jest', | ||
options: { | ||
jestConfig: 'apps/demo/jest.config.app.ts', | ||
}, | ||
}, | ||
}, | ||
}); | ||
|
||
// Extracted base config files | ||
expect(tree.exists('tsconfig.base.json')).toBeTruthy(); | ||
expect(tree.exists('.eslintrc.base.json')).toBeTruthy(); | ||
expect(tree.exists('jest.config.ts')).toBeTruthy(); | ||
}); | ||
|
||
it('should convert root Next.js app with existing libraries', async () => { | ||
await nextAppGenerator(tree, { | ||
name: 'demo', | ||
style: 'css', | ||
unitTestRunner: 'jest', | ||
e2eTestRunner: 'none', | ||
appDir: true, | ||
linter: 'eslint', | ||
rootProject: true, | ||
}); | ||
await libraryGenerator(tree, { name: 'util' }); | ||
|
||
await monorepoGenerator(tree, {}); | ||
|
||
expect(readJson(tree, 'apps/demo/project.json')).toMatchObject({ | ||
sourceRoot: 'apps/demo', | ||
}); | ||
expect(tree.read('apps/demo/app/page.tsx', 'utf-8')).toContain('demo'); | ||
expect(readJson(tree, 'libs/util/project.json')).toMatchObject({ | ||
sourceRoot: 'libs/util/src', | ||
}); | ||
expect(tree.read('libs/util/src/lib/util.ts', 'utf-8')).toContain('util'); | ||
|
||
// Extracted base config files | ||
expect(tree.exists('tsconfig.base.json')).toBeTruthy(); | ||
expect(tree.exists('.eslintrc.base.json')).toBeTruthy(); | ||
expect(tree.exists('jest.config.ts')).toBeTruthy(); | ||
}); | ||
}); |
50 changes: 50 additions & 0 deletions
50
packages/workspace/src/generators/convert-to-monorepo/convert-to-monorepo.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { | ||
convertNxGenerator, | ||
getProjects, | ||
joinPathFragments, | ||
ProjectConfiguration, | ||
readNxJson, | ||
Tree, | ||
updateNxJson, | ||
} from '@nx/devkit'; | ||
import { moveGenerator } from '../move/move'; | ||
|
||
export async function monorepoGenerator(tree: Tree, options: {}) { | ||
const projects = getProjects(tree); | ||
|
||
const nxJson = readNxJson(tree); | ||
updateNxJson(tree, nxJson); | ||
|
||
let rootProject: ProjectConfiguration; | ||
const projectsToMove: ProjectConfiguration[] = []; | ||
|
||
// Need to determine libs vs packages directory base on the type of root project. | ||
for (const [, project] of projects) { | ||
if (project.root === '.') rootProject = project; | ||
projectsToMove.push(project); | ||
} | ||
|
||
// Currently, Nx only handles apps+libs or packages. You cannot mix and match them. | ||
// If the standalone project is an app (React, Angular, etc), then use apps+libs. | ||
// Otherwise, for TS standalone (lib), use packages. | ||
const isRootProjectApp = rootProject.projectType === 'application'; | ||
const appsDir = isRootProjectApp ? 'apps' : 'packages'; | ||
const libsDir = isRootProjectApp ? 'libs' : 'packages'; | ||
|
||
for (const project of projectsToMove) { | ||
await moveGenerator(tree, { | ||
projectName: project.name, | ||
newProjectName: project.name, | ||
destination: | ||
project.projectType === 'application' | ||
? joinPathFragments(appsDir, project.name) | ||
: joinPathFragments(libsDir, project.name), | ||
destinationRelativeToRoot: true, | ||
updateImportPath: project.projectType === 'library', | ||
}); | ||
} | ||
} | ||
|
||
export default monorepoGenerator; | ||
|
||
export const monorepoSchematic = convertNxGenerator(monorepoGenerator); |
16 changes: 16 additions & 0 deletions
16
packages/workspace/src/generators/convert-to-monorepo/schema.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"$schema": "http://json-schema.org/schema", | ||
"$id": "NxWorkspaceConvertToMonorepo", | ||
"cli": "nx", | ||
"title": "Nx Convert to Monorepo", | ||
"description": "Convert an Nx project to a monorepo.", | ||
"type": "object", | ||
"examples": [ | ||
{ | ||
"command": "nx g @nx/workspace:monorepo", | ||
"description": "Convert an Nx standalone project to a monorepo." | ||
} | ||
], | ||
"properties": {}, | ||
"required": [] | ||
} |
Oops, something went wrong.
dcefa4a
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
nx-dev – ./
nx-dev-nrwl.vercel.app
nx.dev
nx-dev-git-master-nrwl.vercel.app
nx-five.vercel.app