feat(schematics): implement convert-to-workspace schematic
This commit is contained in:
parent
4da767ed82
commit
b3b49e17a2
66
e2e/schematics/convert-to-workspace.test.ts
Normal file
66
e2e/schematics/convert-to-workspace.test.ts
Normal file
@ -0,0 +1,66 @@
|
||||
import {checkFilesExists, cleanup, newApp, readFile, runCLI, runSchematic, updateFile} from '../utils';
|
||||
|
||||
describe('Nrwl Convert to Nx Workspace', () => {
|
||||
beforeEach(cleanup);
|
||||
|
||||
fit('should generate a workspace', () => {
|
||||
newApp('new proj --skip-install');
|
||||
|
||||
// update package.json
|
||||
const packageJson = JSON.parse(readFile('proj/package.json'));
|
||||
packageJson.description = "some description";
|
||||
packageJson.dependencies['@ngrx/store'] = "4.0.3";
|
||||
packageJson.devDependencies['@ngrx/router-store'] = "4.0.3";
|
||||
updateFile('proj/package.json', JSON.stringify(packageJson, null, 2));
|
||||
|
||||
// update tsconfig.json
|
||||
const tsconfigJson = JSON.parse(readFile('proj/tsconfig.json'));
|
||||
tsconfigJson.compilerOptions.paths = {
|
||||
'a': ['b']
|
||||
};
|
||||
updateFile('proj/tsconfig.json', JSON.stringify(tsconfigJson, null, 2));
|
||||
|
||||
|
||||
// run the command
|
||||
runSchematic('@nrwl/schematics:convert-to-workspace', { projectName: 'proj' });
|
||||
|
||||
// check that files have been moved!
|
||||
checkFilesExists('proj/apps/proj/src/main.ts', 'proj/apps/proj/src/app/app.module.ts');
|
||||
|
||||
// check that package.json got merged
|
||||
const updatedPackageJson = JSON.parse(readFile('proj/package.json'));
|
||||
expect(updatedPackageJson.description).toEqual('some description');
|
||||
expect(updatedPackageJson.dependencies['@ngrx/store']).toEqual('4.0.3');
|
||||
expect(updatedPackageJson.devDependencies['@ngrx/router-store']).toEqual('4.0.3');
|
||||
expect(updatedPackageJson.devDependencies['@nrwl/schematics']).toBeDefined();
|
||||
expect(updatedPackageJson.dependencies['@nrwl/nx']).toBeDefined();
|
||||
|
||||
// check if angular-cli.json get merged
|
||||
const updatedAngularCLIJson = JSON.parse(readFile('proj/.angular-cli.json'));
|
||||
expect(updatedAngularCLIJson.apps[0].root).toEqual('apps/proj/src');
|
||||
expect(updatedAngularCLIJson.apps[0].outDir).toEqual('dist/apps/proj');
|
||||
expect(updatedAngularCLIJson.apps[0].test).toEqual('../../../test.js');
|
||||
expect(updatedAngularCLIJson.apps[0].tsconfig).toEqual('../../../tsconfig.app.json');
|
||||
expect(updatedAngularCLIJson.apps[0].testTsconfig).toEqual('../../../tsconfig.spec.json');
|
||||
|
||||
// check if tsconfig.json get merged
|
||||
const updatedTsConfig = JSON.parse(readFile('proj/tsconfig.json'));
|
||||
expect(updatedTsConfig.compilerOptions.paths).toEqual({
|
||||
"a": ["b"],
|
||||
"*": [
|
||||
"*",
|
||||
"libs/*",
|
||||
"apps/*"
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
it('should build and test', () => {
|
||||
newApp('new proj');
|
||||
runSchematic('@nrwl/schematics:convert-to-workspace', { projectName: 'proj' });
|
||||
|
||||
expect(runCLI('build', { projectName: 'proj' })).toContain('{main} main.bundle.js');
|
||||
expect(runCLI('test --single-run', { projectName: 'proj' })).toContain('Executed 3 of 3 SUCCESS');
|
||||
});
|
||||
});
|
||||
|
||||
@ -140,7 +140,31 @@ import { MyLib } from 'mylib';
|
||||
And then run `ng build --app=myapp`, it will build `mylib` and include it in the app's bundle.
|
||||
|
||||
|
||||
#### Covert and Existing App into a Nx Workspace
|
||||
|
||||
If you have an existing CLI project, you can convert it into an Nx Workspace like this.
|
||||
|
||||
First, make sure you have `@nrwl/schematics` installed. Either run:
|
||||
|
||||
```
|
||||
yarn global add @nrwl/schematics
|
||||
```
|
||||
|
||||
Or run the following in the project dir:
|
||||
|
||||
```
|
||||
yarn add @nrwl/schematics
|
||||
```
|
||||
|
||||
Now, run:
|
||||
|
||||
```
|
||||
schematics @nrwl/schematics:convert-to-workspace
|
||||
```
|
||||
|
||||
* Your project files will be moved under:`apps/projectName`
|
||||
* Some files have moved to the root: tsconfigs, test.js, so all apps and libs share them.
|
||||
* `package.json` and `.angular-cli.json` will be updated
|
||||
|
||||
|
||||
### NgRx
|
||||
|
||||
@ -24,7 +24,7 @@ function addAppToAngularCliJson(options: Schema): Rule {
|
||||
return (host: Tree) => {
|
||||
const appConfig = {
|
||||
"name": options.name,
|
||||
"root": `apps/${options.name}/${options.sourceDir}`,
|
||||
"root": path.join('apps', options.name, options.sourceDir),
|
||||
"outDir": `dist/apps/${options.name}`,
|
||||
"assets": [
|
||||
"assets",
|
||||
|
||||
@ -2,6 +2,12 @@
|
||||
"name": "nx",
|
||||
"version": "0.1",
|
||||
"schematics": {
|
||||
"convert-to-workspace": {
|
||||
"factory": "./convert-to-workspace",
|
||||
"schema": "./convert-to-workspace/schema.json",
|
||||
"description": "Convert an existing CLI project into an Nx Workspace"
|
||||
},
|
||||
|
||||
"application": {
|
||||
"factory": "./workspace",
|
||||
"schema": "./workspace/schema.json",
|
||||
|
||||
165
packages/schematics/src/convert-to-workspace/index.ts
Normal file
165
packages/schematics/src/convert-to-workspace/index.ts
Normal file
@ -0,0 +1,165 @@
|
||||
import {
|
||||
apply, branchAndMerge, chain, externalSchematic, mergeWith, move, Rule, template, Tree,
|
||||
url,
|
||||
schematic
|
||||
} from '@angular-devkit/schematics';
|
||||
import {Schema} from './schema';
|
||||
import {names, toFileName} from '@nrwl/schematics';
|
||||
import * as path from 'path';
|
||||
import {nxVersion, schematicsVersion} from '../utility/lib-versions';
|
||||
import * as fs from 'fs';
|
||||
import {join} from 'path';
|
||||
|
||||
function updatePackageJson() {
|
||||
return (host: Tree) => {
|
||||
if (!host.exists('package.json')) {
|
||||
throw new Error('Cannot find package.json');
|
||||
}
|
||||
const packageJson = JSON.parse(host.read('package.json')!.toString('utf-8'));
|
||||
if (!packageJson.devDependencies) {
|
||||
packageJson.devDependencies = {};
|
||||
}
|
||||
if (!packageJson.dependencies) {
|
||||
packageJson.dependencies = {};
|
||||
}
|
||||
packageJson.dependencies['@nrwl/nx'] = nxVersion;
|
||||
packageJson.devDependencies['@nrwl/schematics'] = schematicsVersion;
|
||||
host.overwrite('package.json', JSON.stringify(packageJson, null, 2));
|
||||
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
function updateAngularCLIJson() {
|
||||
return (host: Tree) => {
|
||||
if (!host.exists('.angular-cli.json')) {
|
||||
throw new Error('Cannot find .angular-cli.json');
|
||||
}
|
||||
const angularCliJson = JSON.parse(host.read('.angular-cli.json')!.toString('utf-8'));
|
||||
if (angularCliJson.apps.length !== 1) {
|
||||
throw new Error('Can only convert projects with one app');
|
||||
}
|
||||
|
||||
angularCliJson.lint = [
|
||||
{
|
||||
"project": "./tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"project": "./tsconfig.spec.json"
|
||||
},
|
||||
{
|
||||
"project": "./tsconfig.e2e.json"
|
||||
}
|
||||
];
|
||||
|
||||
const app = angularCliJson.apps[0];
|
||||
app.root = path.join('apps', angularCliJson.project.name, app.root);
|
||||
app.outDir = path.join('dist', 'apps', angularCliJson.project.name);
|
||||
app.test = '../../../test.js';
|
||||
app.tsconfig = '../../../tsconfig.app.json';
|
||||
app.testTsconfig = '../../../tsconfig.spec.json';
|
||||
|
||||
host.overwrite('.angular-cli.json', JSON.stringify(angularCliJson, null, 2));
|
||||
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
function updateTsConfigsJson() {
|
||||
return (host: Tree) => {
|
||||
const tsconfigJson = JSON.parse(fs.readFileSync('tsconfig.json', 'utf-8'));
|
||||
if (! tsconfigJson.compilerOptions.paths) {
|
||||
tsconfigJson.compilerOptions.paths = {};
|
||||
}
|
||||
tsconfigJson.compilerOptions.baseUrl = '.';
|
||||
tsconfigJson.compilerOptions.paths['*'] = [
|
||||
"*",
|
||||
"libs/*",
|
||||
"apps/*"
|
||||
];
|
||||
fs.writeFileSync('tsconfig.json', JSON.stringify(tsconfigJson, null, 2));
|
||||
|
||||
const tsconfingAppJson = JSON.parse(fs.readFileSync('tsconfig.app.json', 'utf-8'));
|
||||
tsconfingAppJson['extends'] = './tsconfig.json';
|
||||
if (!tsconfingAppJson.exclude) {
|
||||
tsconfingAppJson.exclude = [];
|
||||
}
|
||||
tsconfingAppJson.exclude = dedup(tsconfingAppJson.exclude.concat([
|
||||
"**/*.spec.ts",
|
||||
"**/*.e2e-spec.ts",
|
||||
"node_modules",
|
||||
"tmp"
|
||||
]));
|
||||
fs.writeFileSync('tsconfig.app.json', JSON.stringify(tsconfingAppJson, null, 2));
|
||||
|
||||
const tsconfingSpecJson = JSON.parse(fs.readFileSync('tsconfig.spec.json', 'utf-8'));
|
||||
tsconfingSpecJson['extends'] = './tsconfig.json';
|
||||
if (!tsconfingSpecJson.exclude) {
|
||||
tsconfingSpecJson.exclude = [];
|
||||
}
|
||||
tsconfingSpecJson.files = [
|
||||
'test.js'
|
||||
];
|
||||
tsconfingSpecJson.exclude = dedup(tsconfingSpecJson.exclude.concat([
|
||||
"node_modules",
|
||||
"tmp"
|
||||
]));
|
||||
fs.writeFileSync('tsconfig.spec.json', JSON.stringify(tsconfingSpecJson, null, 2));
|
||||
|
||||
const tsconfingE2eJson = JSON.parse(fs.readFileSync('tsconfig.e2e.json', 'utf-8'));
|
||||
tsconfingE2eJson['extends'] = './tsconfig.json';
|
||||
if (!tsconfingE2eJson.exclude) {
|
||||
tsconfingE2eJson.exclude = [];
|
||||
}
|
||||
tsconfingE2eJson.exclude = dedup(tsconfingE2eJson.exclude.concat([
|
||||
"**/*.spec.ts",
|
||||
"node_modules",
|
||||
"tmp"
|
||||
]));
|
||||
fs.writeFileSync('tsconfig.e2e.json', JSON.stringify(tsconfingE2eJson, null, 2));
|
||||
|
||||
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
function moveFiles() {
|
||||
return (host: Tree) => {
|
||||
const angularCliJson = JSON.parse(host.read('.angular-cli.json')!.toString('utf-8'));
|
||||
const app = angularCliJson.apps[0];
|
||||
|
||||
fs.mkdirSync('apps');
|
||||
fs.mkdirSync('libs');
|
||||
fs.unlinkSync(path.join(app.root, app.test));
|
||||
fs.mkdirSync(path.join('apps', angularCliJson.project.name));
|
||||
fs.renameSync(path.join(app.root, app.tsconfig), 'tsconfig.app.json');
|
||||
fs.renameSync(path.join(app.root, app.testTsconfig), 'tsconfig.spec.json');
|
||||
fs.renameSync(path.join('e2e', 'tsconfig.e2e.json'), 'tsconfig.e2e.json');
|
||||
fs.renameSync(app.root, join('apps', angularCliJson.project.name, app.root));
|
||||
fs.renameSync('e2e', join('apps', angularCliJson.project.name, 'e2e'));
|
||||
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
function dedup(array: any[]): any[] {
|
||||
const res = [];
|
||||
array.forEach(a => {
|
||||
if (res.indexOf(a) === -1) {
|
||||
res.push(a);
|
||||
}
|
||||
});
|
||||
return res;
|
||||
}
|
||||
|
||||
export default function (options: Schema): Rule {
|
||||
return chain([
|
||||
moveFiles(),
|
||||
branchAndMerge(chain([
|
||||
mergeWith( apply(url('./files'), [])),
|
||||
])),
|
||||
updatePackageJson(),
|
||||
updateAngularCLIJson(),
|
||||
updateTsConfigsJson()
|
||||
]);
|
||||
}
|
||||
2
packages/schematics/src/convert-to-workspace/schema.d.ts
vendored
Normal file
2
packages/schematics/src/convert-to-workspace/schema.d.ts
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
export interface Schema {
|
||||
}
|
||||
11
packages/schematics/src/convert-to-workspace/schema.json
Normal file
11
packages/schematics/src/convert-to-workspace/schema.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"id": "convert-to-workspace",
|
||||
"title": "Convert to Nx workspace",
|
||||
"description": "NOTE: Does not work in the --dry-run mode",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
},
|
||||
"required": [
|
||||
]
|
||||
}
|
||||
@ -1,2 +1,4 @@
|
||||
export const angularJsVersion = "1.6.6";
|
||||
export const ngrxVersion = "4.0.3";
|
||||
export const nxVersion = "nrwl/nx-build";
|
||||
export const schematicsVersion = "nrwl/schematics-build";
|
||||
|
||||
0
packages/schematics/src/workspace/files/README.md → packages/schematics/src/workspace/files/__directory__/README.md
Executable file → Normal file
0
packages/schematics/src/workspace/files/README.md → packages/schematics/src/workspace/files/__directory__/README.md
Executable file → Normal file
@ -23,12 +23,12 @@
|
||||
"@angular/router": "^4.2.4",
|
||||
"core-js": "^2.4.1",
|
||||
"rxjs": "^5.4.2",
|
||||
"zone.js": "^0.8.14"
|
||||
"zone.js": "^0.8.14",
|
||||
"@nrwl/nx": "nrwl/nx-build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/cli": "<%= version %>",
|
||||
"@angular/compiler-cli": "^4.2.4",
|
||||
"@nrwl/nx": "nrwl/nx-build",
|
||||
"@nrwl/schematics": "nrwl/schematics-build",
|
||||
"@angular/language-service": "^4.2.4",<% if (!minimal) { %>
|
||||
"@types/jasmine": "~2.5.53",
|
||||
@ -0,0 +1,30 @@
|
||||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
||||
require('zone.js/dist/long-stack-trace-zone');
|
||||
require('zone.js/dist/proxy.js');
|
||||
require('zone.js/dist/sync-test');
|
||||
require('zone.js/dist/jasmine-patch');
|
||||
require('zone.js/dist/async-test');
|
||||
require('zone.js/dist/fake-async-test');
|
||||
const getTestBed = require('@angular/core/testing').getTestBed;
|
||||
const BrowserDynamicTestingModule = require('@angular/platform-browser-dynamic/testing').BrowserDynamicTestingModule;
|
||||
const platformBrowserDynamicTesting = require('@angular/platform-browser-dynamic/testing').platformBrowserDynamicTesting;
|
||||
|
||||
// Prevent Karma from running prematurely.
|
||||
__karma__.loaded = function () {};
|
||||
|
||||
// First, initialize the Angular testing environment.
|
||||
getTestBed().initTestEnvironment(
|
||||
BrowserDynamicTestingModule,
|
||||
platformBrowserDynamicTesting()
|
||||
);
|
||||
// Then we find all the tests.
|
||||
const contextApps = require.context('./apps', true, /\.spec\.ts$/);
|
||||
// And load the modules.
|
||||
contextApps.keys().map(contextApps);
|
||||
|
||||
const contextLibs = require.context('./libs', true, /\.spec\.ts$/);
|
||||
// And load the modules.
|
||||
contextLibs.keys().map(contextLibs);
|
||||
|
||||
// Finally, start Karma to run the tests.
|
||||
__karma__.start();
|
||||
@ -2,17 +2,11 @@
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/app",
|
||||
"module": "es2015",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"*": [
|
||||
"*",
|
||||
"libs/*",
|
||||
"apps/*"
|
||||
]
|
||||
}
|
||||
"module": "es2015"
|
||||
},
|
||||
"exclude": [
|
||||
"**/*.spec.ts",
|
||||
"**/*.e2e-spec.ts",
|
||||
"node_modules",
|
||||
"tmp"
|
||||
]
|
||||
@ -2,23 +2,16 @@
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/e2e",
|
||||
"baseUrl": "./",
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"types": [
|
||||
"jasmine",
|
||||
"jasminewd2",
|
||||
"node"
|
||||
],
|
||||
"paths": {
|
||||
"*": [
|
||||
"*",
|
||||
"libs/*",
|
||||
"apps/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"exclude": [
|
||||
"**/*.spec.ts",
|
||||
"node_modules",
|
||||
"tmp"
|
||||
]
|
||||
@ -2,20 +2,12 @@
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/spec",
|
||||
"baseUrl": "./",
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"types": [
|
||||
"jasmine",
|
||||
"node"
|
||||
],
|
||||
"paths": {
|
||||
"*": [
|
||||
"*",
|
||||
"libs/*",
|
||||
"apps/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"files": [
|
||||
"test.js"
|
||||
@ -13,8 +13,7 @@ export default function (options: Schema): Rule {
|
||||
|
||||
return chain([
|
||||
branchAndMerge(chain([
|
||||
mergeWith(templateSource),
|
||||
move(options.directory)
|
||||
mergeWith(templateSource)
|
||||
]))
|
||||
]);
|
||||
}
|
||||
|
||||
@ -2,4 +2,4 @@
|
||||
|
||||
./scripts/link.sh
|
||||
rm -rf tmp
|
||||
jest --maxWorkers=1 ./build/e2e
|
||||
jest --maxWorkers=1 ./build/e2e/schematics/convert-to-workspace.test.js
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user