feat(schematics): change upgrade-module and downgrade-module schematics to work with CLI6

This commit is contained in:
Victor Savkin 2018-05-08 12:14:48 -04:00
parent 7c330163bd
commit af0c7acc4f
15 changed files with 437 additions and 458 deletions

View File

@ -1,6 +1,6 @@
import { newApp, newProject, runCLI, updateFile } from '../utils'; import { newApp, newProject, runCLI, updateFile } from '../utils';
xdescribe('DowngradeModule', () => { describe('DowngradeModule', () => {
it( it(
'should generate a downgradeModule setup', 'should generate a downgradeModule setup',
() => { () => {
@ -12,10 +12,12 @@ xdescribe('DowngradeModule', () => {
`window.angular.module('legacy', []);` `window.angular.module('legacy', []);`
); );
runCLI('generate downgrade-module legacy --angularJsImport=./legacy'); runCLI(
'generate downgrade-module legacy --angularJsImport=./legacy --project=myapp'
);
runCLI('build'); runCLI('build');
expect(runCLI('test --no-watch')).toContain('Executed 1 of 1 SUCCESS'); expect(runCLI('test --no-watch')).toContain('Executed 3 of 3 SUCCESS');
}, },
1000000 1000000
); );

View File

@ -1,7 +1,7 @@
import { newApp, newProject, runCLI, updateFile } from '../utils'; import { newApp, newProject, runCLI, updateFile } from '../utils';
xdescribe('Upgrade', () => { describe('Upgrade', () => {
it( fit(
'should generate an UpgradeModule setup', 'should generate an UpgradeModule setup',
() => { () => {
newProject(); newProject();
@ -28,7 +28,7 @@ xdescribe('Upgrade', () => {
runCLI( runCLI(
'generate upgrade-module legacy --angularJsImport=./legacy ' + 'generate upgrade-module legacy --angularJsImport=./legacy ' +
'--angularJsCmpSelector=rootLegacyCmp' '--angularJsCmpSelector=rootLegacyCmp --project=myapp'
); );
runCLI('build'); runCLI('build');

View File

@ -5,7 +5,7 @@ import { createApp, createEmptyWorkspace } from '../../utils/testing-utils';
import { getFileContent } from '@schematics/angular/utility/test'; import { getFileContent } from '@schematics/angular/utility/test';
import { readJsonInTree } from '../../utils/ast-utils'; import { readJsonInTree } from '../../utils/ast-utils';
xdescribe('downgrade-module', () => { describe('downgrade-module', () => {
const schematicRunner = new SchematicTestRunner( const schematicRunner = new SchematicTestRunner(
'@nrwl/schematics', '@nrwl/schematics',
path.join(__dirname, '../../collection.json') path.join(__dirname, '../../collection.json')
@ -23,7 +23,8 @@ xdescribe('downgrade-module', () => {
const tree = schematicRunner.runSchematic( const tree = schematicRunner.runSchematic(
'downgrade-module', 'downgrade-module',
{ {
name: 'legacy' name: 'legacy',
project: 'myapp'
}, },
appTree appTree
); );
@ -40,7 +41,8 @@ xdescribe('downgrade-module', () => {
const tree = schematicRunner.runSchematic( const tree = schematicRunner.runSchematic(
'downgrade-module', 'downgrade-module',
{ {
name: 'legacy' name: 'legacy',
project: 'myapp'
}, },
appTree appTree
); );
@ -64,7 +66,8 @@ xdescribe('downgrade-module', () => {
const tree = schematicRunner.runSchematic( const tree = schematicRunner.runSchematic(
'downgrade-module', 'downgrade-module',
{ {
name: 'legacy' name: 'legacy',
project: 'myapp'
}, },
appTree appTree
); );
@ -88,7 +91,8 @@ xdescribe('downgrade-module', () => {
'downgrade-module', 'downgrade-module',
{ {
name: 'legacy', name: 'legacy',
skipPackageJson: true skipPackageJson: true,
project: 'myapp'
}, },
appTree appTree
); );
@ -102,7 +106,8 @@ xdescribe('downgrade-module', () => {
'downgrade-module', 'downgrade-module',
{ {
name: 'legacy', name: 'legacy',
angularJsImport: 'legacy-app' angularJsImport: 'legacy-app',
project: 'myapp'
}, },
appTree appTree
); );

View File

@ -18,7 +18,7 @@ function updateMain(angularJsImport: string, options: Schema): Rule {
moduleSpec, moduleSpec,
bootstrapComponentClassName, bootstrapComponentClassName,
bootstrapComponentFileName bootstrapComponentFileName
} = readBootstrapInfo(host, options.app); } = readBootstrapInfo(host, options.project);
host.overwrite( host.overwrite(
mainPath, mainPath,
@ -27,7 +27,7 @@ function updateMain(angularJsImport: string, options: Schema): Rule {
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import * as angular from 'angular'; import * as angular from 'angular';
import { downgradeComponent, downgradeModule, setAngularLib } from '@angular/upgrade/static'; import { downgradeComponent, downgradeModule, setAngularJSGlobal } from '@angular/upgrade/static';
import { ${moduleClassName} } from '${moduleSpec}'; import { ${moduleClassName} } from '${moduleSpec}';
import { environment } from './environments/environment'; import { environment } from './environments/environment';
@ -35,7 +35,7 @@ import '${angularJsImport}';
import { ${bootstrapComponentClassName} } from '${bootstrapComponentFileName}'; import { ${bootstrapComponentClassName} } from '${bootstrapComponentFileName}';
export function bootstrapAngular(extra: StaticProvider[]): any { export function bootstrapAngular(extra: StaticProvider[]): any {
setAngularLib(angular); setAngularJSGlobal(angular);
if (environment.production) { if (environment.production) {
enableProdMode(); enableProdMode();
} }
@ -59,7 +59,7 @@ function rewriteBootstrapLogic(options: Schema): Rule {
return (host: Tree) => { return (host: Tree) => {
const { modulePath, moduleSource, moduleClassName } = readBootstrapInfo( const { modulePath, moduleSource, moduleClassName } = readBootstrapInfo(
host, host,
options.app options.project
); );
insert(host, modulePath, [ insert(host, modulePath, [
...addMethod(moduleSource, modulePath, { ...addMethod(moduleSource, modulePath, {
@ -78,7 +78,7 @@ function addEntryComponentsToModule(options: Schema): Rule {
modulePath, modulePath,
moduleSource, moduleSource,
bootstrapComponentClassName bootstrapComponentClassName
} = readBootstrapInfo(host, options.app); } = readBootstrapInfo(host, options.project);
insert( insert(
host, host,
modulePath, modulePath,

View File

@ -2,5 +2,5 @@ export interface Schema {
angularJsImport: string; angularJsImport: string;
name: string; name: string;
skipPackageJson: boolean; skipPackageJson: boolean;
app: string; project: string;
} }

View File

@ -4,13 +4,17 @@
"title": "Generates downgradeModule setup", "title": "Generates downgradeModule setup",
"type": "object", "type": "object",
"properties": { "properties": {
"app": { "project": {
"type": "string", "type": "string",
"description": "The name of the application" "description": "The name of the project"
}, },
"name": { "name": {
"type": "string", "type": "string",
"description": "The name of the main AngularJS module." "description": "The name of the main AngularJS module.",
"$default": {
"$source": "argv",
"index": 0
}
}, },
"angularJsImport": { "angularJsImport": {
"type": "string", "type": "string",
@ -23,6 +27,6 @@
} }
}, },
"required": [ "required": [
"name" "project"
] ]
} }

View File

@ -1,5 +1,5 @@
import {Directive, ElementRef, Injector} from '@angular/core'; import {Directive, ElementRef, Injector} from '@angular/core';
import {setAngularLib, UpgradeComponent, downgradeComponent, UpgradeModule} from '@angular/upgrade/static'; import {setAngularJSGlobal, UpgradeComponent, downgradeComponent, UpgradeModule} from '@angular/upgrade/static';
<% if (router) { %> <% if (router) { %>
import {Router} from '@angular/router'; import {Router} from '@angular/router';
import {setUpLocationSync} from '@angular/router/upgrade'; import {setUpLocationSync} from '@angular/router/upgrade';
@ -35,7 +35,7 @@ export const upgradedComponents = [];
// additional configuration invoked right before bootstrap // additional configuration invoked right before bootstrap
export function configure<%= className %>(i: Injector) { export function configure<%= className %>(i: Injector) {
setAngularLib(angular); setAngularJSGlobal(angular);
// Insert additional configuration here // Insert additional configuration here
<% if (router) { %> <% if (router) { %>
angular.module('downgraded').run(() => { angular.module('downgraded').run(() => {

View File

@ -34,7 +34,7 @@ function addImportsToModule(options: Schema): Rule {
return (host: Tree) => { return (host: Tree) => {
const { moduleClassName, modulePath, moduleSource } = readBootstrapInfo( const { moduleClassName, modulePath, moduleSource } = readBootstrapInfo(
host, host,
options.app options.project
); );
insert(host, modulePath, [ insert(host, modulePath, [
@ -71,7 +71,7 @@ function addNgDoBootstrapToModule(options: Schema): Rule {
return (host: Tree) => { return (host: Tree) => {
const { moduleClassName, modulePath, moduleSource } = readBootstrapInfo( const { moduleClassName, modulePath, moduleSource } = readBootstrapInfo(
host, host,
options.app options.project
); );
insert(host, modulePath, [ insert(host, modulePath, [
@ -102,7 +102,7 @@ function createFiles(angularJsImport: string, options: Schema): Rule {
moduleSpec, moduleSpec,
bootstrapComponentClassName, bootstrapComponentClassName,
bootstrapComponentFileName bootstrapComponentFileName
} = readBootstrapInfo(host, options.app); } = readBootstrapInfo(host, options.project);
const dir = path.dirname(mainPath); const dir = path.dirname(mainPath);
const templateSource = apply(url('./files'), [ const templateSource = apply(url('./files'), [

View File

@ -1,5 +1,5 @@
export interface Schema { export interface Schema {
app: string; project: string;
angularJsImport: string; angularJsImport: string;
angularJsCmpSelector: string; angularJsCmpSelector: string;
name: string; name: string;

View File

@ -4,13 +4,17 @@
"title": "Generates UpgradeModule setup", "title": "Generates UpgradeModule setup",
"type": "object", "type": "object",
"properties": { "properties": {
"app": { "project": {
"type": "string", "type": "string",
"description": "The name of the application" "description": "The name of the project"
}, },
"name": { "name": {
"type": "string", "type": "string",
"description": "The name of the main AngularJS module." "description": "The name of the main AngularJS module.",
"$default": {
"$source": "argv",
"index": 0
}
}, },
"angularJsImport": { "angularJsImport": {
"type": "string", "type": "string",
@ -32,6 +36,6 @@
} }
}, },
"required": [ "required": [
"name" "project"
] ]
} }

View File

@ -5,7 +5,7 @@ import { createApp, createEmptyWorkspace } from '../../utils/testing-utils';
import { getFileContent } from '@schematics/angular/utility/test'; import { getFileContent } from '@schematics/angular/utility/test';
import { readJsonInTree } from '../../utils/ast-utils'; import { readJsonInTree } from '../../utils/ast-utils';
xdescribe('upgrade-module', () => { describe('upgrade-module', () => {
const schematicRunner = new SchematicTestRunner( const schematicRunner = new SchematicTestRunner(
'@nrwl/schematics', '@nrwl/schematics',
path.join(__dirname, '../../collection.json') path.join(__dirname, '../../collection.json')
@ -23,7 +23,8 @@ xdescribe('upgrade-module', () => {
const tree = schematicRunner.runSchematic( const tree = schematicRunner.runSchematic(
'upgrade-module', 'upgrade-module',
{ {
name: 'legacy' name: 'legacy',
project: 'myapp'
}, },
appTree appTree
); );
@ -53,7 +54,8 @@ xdescribe('upgrade-module', () => {
const tree = schematicRunner.runSchematic( const tree = schematicRunner.runSchematic(
'upgrade-module', 'upgrade-module',
{ {
name: 'legacy' name: 'legacy',
project: 'myapp'
}, },
appTree appTree
); );
@ -77,7 +79,8 @@ xdescribe('upgrade-module', () => {
'upgrade-module', 'upgrade-module',
{ {
name: 'legacy', name: 'legacy',
skipPackageJson: true skipPackageJson: true,
project: 'myapp'
}, },
appTree appTree
); );
@ -91,7 +94,8 @@ xdescribe('upgrade-module', () => {
'upgrade-module', 'upgrade-module',
{ {
name: 'legacy', name: 'legacy',
router: true router: true,
project: 'myapp'
}, },
appTree appTree
); );
@ -105,7 +109,8 @@ xdescribe('upgrade-module', () => {
'upgrade-module', 'upgrade-module',
{ {
name: 'legacy', name: 'legacy',
angularJsImport: 'legacy-app' angularJsImport: 'legacy-app',
project: 'myapp'
}, },
appTree appTree
); );

View File

@ -1,383 +1,351 @@
import { import { chain, Rule } from '@angular-devkit/schematics';
apply,
branchAndMerge,
chain,
mergeWith,
Rule,
SchematicContext,
Tree,
url
} from '@angular-devkit/schematics';
import { Schema } from './schema'; import { Schema } from './schema';
import * as path from 'path';
import { join } from 'path';
import {
angularCliSchema,
angularCliVersion,
latestMigration,
ngrxStoreFreezeVersion,
ngrxVersion,
nxVersion,
prettierVersion,
routerStoreVersion,
schematicsVersion
} from '../../lib-versions';
import * as fs from 'fs';
import { updateJsonFile } from '../../utils/fileutils';
import { toFileName } from '../../utils/name-utils';
import {
getAngularCliConfig,
insert,
updateJsonInTree
} from '../../utils/ast-utils';
import { stripIndents } from '@angular-devkit/core/src/utils/literals';
import { InsertChange } from '@schematics/angular/utility/change';
function updatePackageJson() { // function updatePackageJson() {
return updateJsonInTree('package.json', packageJson => { // return updateJsonInTree('package.json', packageJson => {
if (!packageJson.devDependencies) { // if (!packageJson.devDependencies) {
packageJson.devDependencies = {}; // packageJson.devDependencies = {};
} // }
if (!packageJson.dependencies) { // if (!packageJson.dependencies) {
packageJson.dependencies = {}; // packageJson.dependencies = {};
} // }
if (!packageJson.scripts) { // if (!packageJson.scripts) {
packageJson.scripts = {}; // packageJson.scripts = {};
} // }
if (!packageJson.dependencies['@nrwl/nx']) { // if (!packageJson.dependencies['@nrwl/nx']) {
packageJson.dependencies['@nrwl/nx'] = nxVersion; // packageJson.dependencies['@nrwl/nx'] = nxVersion;
} // }
if (!packageJson.dependencies['@ngrx/store']) { // if (!packageJson.dependencies['@ngrx/store']) {
packageJson.dependencies['@ngrx/store'] = ngrxVersion; // packageJson.dependencies['@ngrx/store'] = ngrxVersion;
} // }
if (!packageJson.dependencies['@ngrx/router-store']) { // if (!packageJson.dependencies['@ngrx/router-store']) {
packageJson.dependencies['@ngrx/router-store'] = routerStoreVersion; // packageJson.dependencies['@ngrx/router-store'] = routerStoreVersion;
} // }
if (!packageJson.dependencies['@ngrx/effects']) { // if (!packageJson.dependencies['@ngrx/effects']) {
packageJson.dependencies['@ngrx/effects'] = ngrxVersion; // packageJson.dependencies['@ngrx/effects'] = ngrxVersion;
} // }
if (!packageJson.dependencies['@ngrx/store-devtools']) { // if (!packageJson.dependencies['@ngrx/store-devtools']) {
packageJson.dependencies['@ngrx/store-devtools'] = ngrxVersion; // packageJson.dependencies['@ngrx/store-devtools'] = ngrxVersion;
} // }
if (!packageJson.dependencies['ngrx-store-freeze']) { // if (!packageJson.dependencies['ngrx-store-freeze']) {
packageJson.dependencies['ngrx-store-freeze'] = ngrxStoreFreezeVersion; // packageJson.dependencies['ngrx-store-freeze'] = ngrxStoreFreezeVersion;
} // }
if (!packageJson.devDependencies['@nrwl/schematics']) { // if (!packageJson.devDependencies['@nrwl/schematics']) {
packageJson.devDependencies['@nrwl/schematics'] = schematicsVersion; // packageJson.devDependencies['@nrwl/schematics'] = schematicsVersion;
} // }
if (!packageJson.dependencies['@angular/cli']) { // if (!packageJson.dependencies['@angular/cli']) {
packageJson.dependencies['@angular/cli'] = angularCliVersion; // packageJson.dependencies['@angular/cli'] = angularCliVersion;
} // }
if (!packageJson.devDependencies['prettier']) { // if (!packageJson.devDependencies['prettier']) {
packageJson.devDependencies['prettier'] = prettierVersion; // packageJson.devDependencies['prettier'] = prettierVersion;
} // }
//
packageJson.scripts['affected:apps'] = // packageJson.scripts['affected:apps'] =
'./node_modules/.bin/nx affected:apps'; // './node_modules/.bin/nx affected:apps';
packageJson.scripts['affected:build'] = // packageJson.scripts['affected:build'] =
'./node_modules/.bin/nx affected:build'; // './node_modules/.bin/nx affected:build';
packageJson.scripts['affected:e2e'] = './node_modules/.bin/nx affected:e2e'; // packageJson.scripts['affected:e2e'] = './node_modules/.bin/nx affected:e2e';
//
packageJson.scripts['affected:dep-graph'] = // packageJson.scripts['affected:dep-graph'] =
'./node_modules/.bin/nx affected:dep-graph'; // './node_modules/.bin/nx affected:dep-graph';
//
packageJson.scripts['format'] = './node_modules/.bin/nx format:write'; // packageJson.scripts['format'] = './node_modules/.bin/nx format:write';
packageJson.scripts['format:write'] = './node_modules/.bin/nx format:write'; // packageJson.scripts['format:write'] = './node_modules/.bin/nx format:write';
packageJson.scripts['format:check'] = './node_modules/.bin/nx format:check'; // packageJson.scripts['format:check'] = './node_modules/.bin/nx format:check';
//
packageJson.scripts['update'] = './node_modules/.bin/nx update'; // packageJson.scripts['update'] = './node_modules/.bin/nx update';
packageJson.scripts['update:check'] = './node_modules/.bin/nx update:check'; // packageJson.scripts['update:check'] = './node_modules/.bin/nx update:check';
packageJson.scripts['update:skip'] = './node_modules/.bin/nx update:skip'; // packageJson.scripts['update:skip'] = './node_modules/.bin/nx update:skip';
//
packageJson.scripts['lint'] = './node_modules/.bin/nx lint && ng lint'; // packageJson.scripts['lint'] = './node_modules/.bin/nx lint && ng lint';
//
packageJson.scripts['dep-graph'] = './node_modules/.bin/nx dep-graph'; // packageJson.scripts['dep-graph'] = './node_modules/.bin/nx dep-graph';
//
packageJson.scripts['postinstall'] = './node_modules/.bin/nx postinstall'; // packageJson.scripts['postinstall'] = './node_modules/.bin/nx postinstall';
packageJson.scripts['workspace-schematic'] = // packageJson.scripts['workspace-schematic'] =
'./node_modules/.bin/nx workspace-schematic'; // './node_modules/.bin/nx workspace-schematic';
//
return packageJson; // return packageJson;
}); // });
} // }
//
function updateAngularCLIJson(options: Schema): Rule { // function updateAngularCLIJson(options: Schema): Rule {
return updateJsonInTree('.angular-cli.json', angularCliJson => { // return updateJsonInTree('.angular-cli.json', angularCliJson => {
angularCliJson.$schema = angularCliSchema; // angularCliJson.$schema = angularCliSchema;
angularCliJson.project.npmScope = npmScope(options); // angularCliJson.project.npmScope = npmScope(options);
angularCliJson.project.latestMigration = latestMigration; // angularCliJson.project.latestMigration = latestMigration;
//
if (angularCliJson.apps.length !== 1) { // if (angularCliJson.apps.length !== 1) {
throw new Error('Can only convert projects with one app'); // throw new Error('Can only convert projects with one app');
} // }
//
const app = angularCliJson.apps[0]; // const app = angularCliJson.apps[0];
app.name = options.name; // app.name = options.name;
app.root = path.join('apps', options.name, app.root); // app.root = path.join('apps', options.name, app.root);
app.outDir = path.join('dist', 'apps', options.name); // app.outDir = path.join('dist', 'apps', options.name);
app.test = '../../../test.js'; // app.test = '../../../test.js';
app.testTsconfig = '../../../tsconfig.spec.json'; // app.testTsconfig = '../../../tsconfig.spec.json';
app.scripts = app.scripts.map(p => path.join('../../', p)); // app.scripts = app.scripts.map(p => path.join('../../', p));
app.tags = []; // app.tags = [];
if (!angularCliJson.defaults) { // if (!angularCliJson.defaults) {
angularCliJson.defaults = {}; // angularCliJson.defaults = {};
} // }
if (!angularCliJson.defaults.schematics) { // if (!angularCliJson.defaults.schematics) {
angularCliJson.defaults.schematics = {}; // angularCliJson.defaults.schematics = {};
} // }
angularCliJson.defaults.schematics['collection'] = '@nrwl/schematics'; // angularCliJson.defaults.schematics['collection'] = '@nrwl/schematics';
angularCliJson.defaults.schematics['postGenerate'] = 'npm run format'; // angularCliJson.defaults.schematics['postGenerate'] = 'npm run format';
angularCliJson.defaults.schematics['newProject'] = ['app', 'lib']; // angularCliJson.defaults.schematics['newProject'] = ['app', 'lib'];
//
angularCliJson.lint = [ // angularCliJson.lint = [
{ // {
project: `${app.root}/tsconfig.app.json`, // project: `${app.root}/tsconfig.app.json`,
exclude: '**/node_modules/**' // exclude: '**/node_modules/**'
}, // },
{ // {
project: './tsconfig.spec.json', // project: './tsconfig.spec.json',
exclude: '**/node_modules/**' // exclude: '**/node_modules/**'
}, // },
{ // {
project: join('apps', options.name, 'e2e', 'tsconfig.e2e.json'), // project: join('apps', options.name, 'e2e', 'tsconfig.e2e.json'),
exclude: '**/node_modules/**' // exclude: '**/node_modules/**'
} // }
]; // ];
//
return angularCliJson; // return angularCliJson;
}); // });
} // }
//
function updateTsConfig(options: Schema): Rule { // function updateTsConfig(options: Schema): Rule {
return updateJsonInTree('tsconfig.json', tsConfigJson => // return updateJsonInTree('tsconfig.json', tsConfigJson =>
setUpCompilerOptions(tsConfigJson, npmScope(options), '') // setUpCompilerOptions(tsConfigJson, npmScope(options), '')
); // );
} // }
//
function updateTsConfigsJson(options: Schema) { // function updateTsConfigsJson(options: Schema) {
return (host: Tree) => { // return (host: Tree) => {
const angularCliJson = getAngularCliConfig(host); // const angularCliJson = getAngularCliConfig(host);
const app = angularCliJson.apps[0]; // const app = angularCliJson.apps[0];
//
// This has to stay using fs since it is created with fs // // This has to stay using fs since it is created with fs
const offset = '../../../'; // const offset = '../../../';
updateJsonFile(`${app.root}/tsconfig.app.json`, json => { // updateJsonFile(`${app.root}/tsconfig.app.json`, json => {
json.extends = `${offset}tsconfig.json`; // json.extends = `${offset}tsconfig.json`;
json.compilerOptions.outDir = `${offset}dist/out-tsc/apps/${ // json.compilerOptions.outDir = `${offset}dist/out-tsc/apps/${
options.name // options.name
}`; // }`;
if (!json.exclude) json.exclude = []; // if (!json.exclude) json.exclude = [];
json.exclude = dedup(json.exclude.concat(['**/*.spec.ts'])); // json.exclude = dedup(json.exclude.concat(['**/*.spec.ts']));
//
if (!json.include) json.include = []; // if (!json.include) json.include = [];
json.include = dedup(json.include.concat(['**/*.ts'])); // json.include = dedup(json.include.concat(['**/*.ts']));
}); // });
//
// This has to stay using fs since it is created with fs // // This has to stay using fs since it is created with fs
updateJsonFile('tsconfig.spec.json', json => { // updateJsonFile('tsconfig.spec.json', json => {
json.extends = './tsconfig.json'; // json.extends = './tsconfig.json';
json.compilerOptions.outDir = `./dist/out-tsc/spec`; // json.compilerOptions.outDir = `./dist/out-tsc/spec`;
//
if (!json.exclude) json.exclude = []; // if (!json.exclude) json.exclude = [];
json.files = ['test.js']; // json.files = ['test.js'];
json.include = ['**/*.ts']; // json.include = ['**/*.ts'];
json.exclude = dedup( // json.exclude = dedup(
json.exclude.concat([ // json.exclude.concat([
'**/e2e/*.ts', // '**/e2e/*.ts',
'**/*.e2e-spec.ts', // '**/*.e2e-spec.ts',
'**/*.po.ts', // '**/*.po.ts',
'node_modules', // 'node_modules',
'tmp' // 'tmp'
]) // ])
); // );
}); // });
//
// This has to stay using fs since it is created with fs // // This has to stay using fs since it is created with fs
updateJsonFile(`apps/${options.name}/e2e/tsconfig.e2e.json`, json => { // updateJsonFile(`apps/${options.name}/e2e/tsconfig.e2e.json`, json => {
json.extends = `${offset}tsconfig.json`; // json.extends = `${offset}tsconfig.json`;
json.compilerOptions.outDir = `${offset}dist/out-tsc/e2e/${options.name}`; // json.compilerOptions.outDir = `${offset}dist/out-tsc/e2e/${options.name}`;
if (!json.exclude) json.exclude = []; // if (!json.exclude) json.exclude = [];
json.exclude = dedup(json.exclude.concat(['**/*.spec.ts'])); // json.exclude = dedup(json.exclude.concat(['**/*.spec.ts']));
//
if (!json.include) json.include = []; // if (!json.include) json.include = [];
json.include = dedup(json.include.concat(['../**/*.ts'])); // json.include = dedup(json.include.concat(['../**/*.ts']));
}); // });
//
return host; // return host;
}; // };
} // }
//
function updateTsLint() { // function updateTsLint() {
return updateJsonInTree('tslint.json', tslintJson => { // return updateJsonInTree('tslint.json', tslintJson => {
[ // [
'no-trailing-whitespace', // 'no-trailing-whitespace',
'one-line', // 'one-line',
'quotemark', // 'quotemark',
'typedef-whitespace', // 'typedef-whitespace',
'whitespace' // 'whitespace'
].forEach(key => { // ].forEach(key => {
tslintJson[key] = undefined; // tslintJson[key] = undefined;
}); // });
tslintJson.rulesDirectory = tslintJson.rulesDirectory || []; // tslintJson.rulesDirectory = tslintJson.rulesDirectory || [];
tslintJson.rulesDirectory.push('node_modules/@nrwl/schematics/src/tslint'); // tslintJson.rulesDirectory.push('node_modules/@nrwl/schematics/src/tslint');
tslintJson['nx-enforce-module-boundaries'] = [ // tslintJson['nx-enforce-module-boundaries'] = [
true, // true,
{ // {
allow: [], // allow: [],
depConstraints: [{ sourceTag: '*', onlyDependOnLibsWithTags: ['*'] }] // depConstraints: [{ sourceTag: '*', onlyDependOnLibsWithTags: ['*'] }]
} // }
]; // ];
return tslintJson; // return tslintJson;
}); // });
} // }
//
function npmScope(options: Schema): string { // function npmScope(options: Schema): string {
return options && options.npmScope ? options.npmScope : options.name; // return options && options.npmScope ? options.npmScope : options.name;
} // }
//
function updateKarmaConf() { // function updateKarmaConf() {
return (host: Tree, context: SchematicContext) => { // return (host: Tree, context: SchematicContext) => {
const angularCliJson = getAngularCliConfig(host); // const angularCliJson = getAngularCliConfig(host);
//
const karmaConfig = angularCliJson.test!.karma; // const karmaConfig = angularCliJson.test!.karma;
//
if (!karmaConfig) { // if (!karmaConfig) {
return; // return;
} // }
//
const karmaConfPath = karmaConfig.config; // const karmaConfPath = karmaConfig.config;
//
const contents = host.read(karmaConfPath).toString(); // const contents = host.read(karmaConfPath).toString();
//
const change = new InsertChange( // const change = new InsertChange(
karmaConfPath, // karmaConfPath,
contents.indexOf('module.exports ='), // contents.indexOf('module.exports ='),
stripIndents` // stripIndents`
const { makeSureNoAppIsSelected } = require('@nrwl/schematics/src/utils/cli-config-utils'); // const { makeSureNoAppIsSelected } = require('@nrwl/schematics/src/utils/cli-config-utils');
// Nx only supports running unit tests for all apps and libs. // // Nx only supports running unit tests for all apps and libs.
makeSureNoAppIsSelected(); // makeSureNoAppIsSelected();
` + '\n\n' // ` + '\n\n'
); // );
//
insert(host, karmaConfPath, [change]); // insert(host, karmaConfPath, [change]);
//
return host; // return host;
}; // };
} // }
//
function updateProtractorConf() { // function updateProtractorConf() {
return (host: Tree) => { // return (host: Tree) => {
if (!host.exists('protractor.conf.js')) { // if (!host.exists('protractor.conf.js')) {
throw new Error('Cannot find protractor.conf.js'); // throw new Error('Cannot find protractor.conf.js');
} // }
const protractorConf = host.read('protractor.conf.js')!.toString('utf-8'); // const protractorConf = host.read('protractor.conf.js')!.toString('utf-8');
const updatedConf = protractorConf // const updatedConf = protractorConf
.replace(`'./e2e/**/*.e2e-spec.ts'`, `appDir + '/e2e/**/*.e2e-spec.ts'`) // .replace(`'./e2e/**/*.e2e-spec.ts'`, `appDir + '/e2e/**/*.e2e-spec.ts'`)
.replace(`'e2e/tsconfig.e2e.json'`, `appDir + '/e2e/tsconfig.e2e.json'`) // .replace(`'e2e/tsconfig.e2e.json'`, `appDir + '/e2e/tsconfig.e2e.json'`)
.replace( // .replace(
`exports.config = {`, // `exports.config = {`,
` // `
const { getAppDirectoryUsingCliConfig } = require('@nrwl/schematics/src/utils/cli-config-utils'); // const { getAppDirectoryUsingCliConfig } = require('@nrwl/schematics/src/utils/cli-config-utils');
const appDir = getAppDirectoryUsingCliConfig(); // const appDir = getAppDirectoryUsingCliConfig();
exports.config = { // exports.config = {
` // `
); // );
//
host.overwrite('protractor.conf.js', updatedConf); // host.overwrite('protractor.conf.js', updatedConf);
//
return host; // return host;
}; // };
} // }
//
function setUpCompilerOptions( // function setUpCompilerOptions(
tsconfig: any, // tsconfig: any,
npmScope: string, // npmScope: string,
offset: string // offset: string
): any { // ): any {
if (!tsconfig.compilerOptions.paths) { // if (!tsconfig.compilerOptions.paths) {
tsconfig.compilerOptions.paths = {}; // tsconfig.compilerOptions.paths = {};
} // }
tsconfig.compilerOptions.baseUrl = '.'; // tsconfig.compilerOptions.baseUrl = '.';
tsconfig.compilerOptions.paths[`@${npmScope}/*`] = [`${offset}libs/*`]; // tsconfig.compilerOptions.paths[`@${npmScope}/*`] = [`${offset}libs/*`];
//
return tsconfig; // return tsconfig;
} // }
//
function moveExistingFiles(options: Schema) { // function moveExistingFiles(options: Schema) {
return (host: Tree) => { // return (host: Tree) => {
const angularCliJson = getAngularCliConfig(host); // const angularCliJson = getAngularCliConfig(host);
const app = angularCliJson.apps[0]; // const app = angularCliJson.apps[0];
//
fs.mkdirSync('apps'); // fs.mkdirSync('apps');
fs.mkdirSync('libs'); // fs.mkdirSync('libs');
fs.unlinkSync(path.join(app.root, app.test)); // fs.unlinkSync(path.join(app.root, app.test));
fs.mkdirSync(path.join('apps', options.name)); // fs.mkdirSync(path.join('apps', options.name));
fs.renameSync(path.join(app.root, app.testTsconfig), 'tsconfig.spec.json'); // fs.renameSync(path.join(app.root, app.testTsconfig), 'tsconfig.spec.json');
fs.renameSync(app.root, join('apps', options.name, app.root)); // fs.renameSync(app.root, join('apps', options.name, app.root));
fs.renameSync('e2e', join('apps', options.name, 'e2e')); // fs.renameSync('e2e', join('apps', options.name, 'e2e'));
//
return host; // return host;
}; // };
} // }
//
function createAdditionalFiles(options: Schema) { // function createAdditionalFiles(options: Schema) {
return (host: Tree, _context: SchematicContext) => { // return (host: Tree, _context: SchematicContext) => {
// if the user does not already have a prettier configuration // // if the user does not already have a prettier configuration
// of any kind, create one // // of any kind, create one
// return fromPromise(resolveUserExistingPrettierConfig()).pipe( // // return fromPromise(resolveUserExistingPrettierConfig()).pipe(
// tap(resolvedExistingConfig => { // // tap(resolvedExistingConfig => {
// if (!resolvedExistingConfig) { // // if (!resolvedExistingConfig) {
// fs.writeFileSync( // // fs.writeFileSync(
// '.prettierrc', // // '.prettierrc',
// JSON.stringify(DEFAULT_NRWL_PRETTIER_CONFIG, null, 2) // // JSON.stringify(DEFAULT_NRWL_PRETTIER_CONFIG, null, 2)
// ); // // );
// } // // }
// }), // // }),
// map(() => host) // // map(() => host)
// ); // // );
}; // };
} // }
//
function dedup(array: any[]): any[] { // function dedup(array: any[]): any[] {
const res = []; // const res = [];
//
array.forEach(a => { // array.forEach(a => {
if (res.indexOf(a) === -1) { // if (res.indexOf(a) === -1) {
res.push(a); // res.push(a);
} // }
}); // });
return res; // return res;
} // }
//
function checkCanConvertToWorkspace(options: Schema) { // function checkCanConvertToWorkspace(options: Schema) {
return (host: Tree) => { // return (host: Tree) => {
if (!host.exists('package.json')) { // if (!host.exists('package.json')) {
throw new Error('Cannot find package.json'); // throw new Error('Cannot find package.json');
} // }
if (!host.exists('protractor.conf.js')) { // if (!host.exists('protractor.conf.js')) {
throw new Error('Cannot find protractor.conf.js'); // throw new Error('Cannot find protractor.conf.js');
} // }
const angularCliJson = getAngularCliConfig(host); // const angularCliJson = getAngularCliConfig(host);
if (angularCliJson.apps.length !== 1) { // if (angularCliJson.apps.length !== 1) {
throw new Error('Can only convert projects with one app'); // throw new Error('Can only convert projects with one app');
} // }
return host; // return host;
}; // };
} // }
export default function(schema: Schema): Rule { export default function(schema: Schema): Rule {
const options = { ...schema, name: toFileName(schema.name) }; // const options = { ...schema, name: toFileName(schema.name) };
return chain([ return chain([
checkCanConvertToWorkspace(options), // checkCanConvertToWorkspace(options),
moveExistingFiles(options), // moveExistingFiles(options),
createAdditionalFiles(options), // createAdditionalFiles(options),
branchAndMerge(chain([mergeWith(apply(url('./files'), []))])), // branchAndMerge(chain([mergeWith(apply(url('./files'), []))])),
updatePackageJson(), // updatePackageJson(),
updateAngularCLIJson(options), // updateAngularCLIJson(options),
updateTsLint(), // updateTsLint(),
updateTsConfig(options), // updateTsConfig(options),
updateTsConfigsJson(options), // updateTsConfigsJson(options),
updateKarmaConf(), // updateKarmaConf(),
updateProtractorConf() // updateProtractorConf()
]); ]);
} }

View File

@ -5,7 +5,7 @@
* Use of this source code is governed by an MIT- style license that can be * Use of this source code is governed by an MIT- style license that can be
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import { Tree, Rule } from '@angular-devkit/schematics'; import { Rule, Tree } from '@angular-devkit/schematics';
import { import {
findNodes, findNodes,
getDecoratorMetadata, getDecoratorMetadata,
@ -575,31 +575,14 @@ export function updateJsonInTree<T = any, O = T>(
}; };
} }
// TODO DELETE THIS function getProjectConfig(host: Tree, name: string): any {
/** const angularJson = readJsonInTree(host, '/angular.json');
* This method is specifically for getting the .angular-cli.json data from a Tree const projectConfig = angularJson.projects[name];
* @param host The host tree if (!projectConfig) {
*/ throw new Error(`Cannot find project '${name}'`);
export function getAngularCliConfig(host: Tree) { } else {
return readJsonInTree(host, '.angular-cli.json'); return projectConfig;
}
// TODO DELETE THIS
export function getAppConfig(host: Tree, name: string): any {
const angularCliJson = getAngularCliConfig(host);
const apps = angularCliJson.apps;
if (!apps || apps.length === 0) {
throw new Error(`Cannot find app '${name}'`);
} }
if (name) {
const appConfig = apps.filter(a => a.name === name)[0];
if (!appConfig) {
throw new Error(`Cannot find app '${name}'`);
} else {
return appConfig;
}
}
return apps[0];
} }
export function readBootstrapInfo( export function readBootstrapInfo(
@ -614,8 +597,15 @@ export function readBootstrapInfo(
bootstrapComponentClassName: string; bootstrapComponentClassName: string;
bootstrapComponentFileName: string; bootstrapComponentFileName: string;
} { } {
const config = getAppConfig(host, app); const config = getProjectConfig(host, app);
const mainPath = path.join(config.root, config.main);
let mainPath;
try {
mainPath = config.architect.build.options.main;
} catch (e) {
throw new Error('Main file cannot be located');
}
if (!host.exists(mainPath)) { if (!host.exists(mainPath)) {
throw new Error('Main file cannot be located'); throw new Error('Main file cannot be located');
} }

View File

@ -96,21 +96,23 @@ export function createApp(
include: ['../**/*.ts'] include: ['../**/*.ts']
}) })
); );
// tree.overwrite( tree.overwrite(
// '/angular.json', '/angular.json',
// JSON.stringify({ JSON.stringify({
// projects: { newProjectRoot: '',
// projects: {
// }, [appName]: {
// apps: [ root: `apps/${appName}/src`,
// { architect: {
// name: appName, build: {
// root: `apps/${appName}/src`, options: {
// main: 'main.ts', main: `apps/${appName}/src/main.ts`
// index: 'index.html' }
// } }
// ] }
// }) }
// ); }
})
);
return tree; return tree;
} }

View File

@ -7,7 +7,6 @@
"typeRoots": ["node_modules/@types"], "typeRoots": ["node_modules/@types"],
"experimentalDecorators": true, "experimentalDecorators": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
"noUnusedLocals": true,
"skipLibCheck": true, "skipLibCheck": true,
"lib": ["es2017"], "lib": ["es2017"],
"declaration": true, "declaration": true,