From af0c7acc4fd6d9716f9d1f78e91bf527b66f865c Mon Sep 17 00:00:00 2001 From: Victor Savkin Date: Tue, 8 May 2018 12:14:48 -0400 Subject: [PATCH] feat(schematics): change upgrade-module and downgrade-module schematics to work with CLI6 --- e2e/schematics/downgrade-module.test.ts | 8 +- e2e/schematics/upgrade-module.test.ts | 6 +- .../downgrade-module/downgrade-module.spec.ts | 17 +- .../src/collection/downgrade-module/index.ts | 10 +- .../collection/downgrade-module/schema.d.ts | 2 +- .../collection/downgrade-module/schema.json | 12 +- .../files/__name__-setup.ts__tmpl__ | 4 +- .../src/collection/upgrade-module/index.ts | 6 +- .../src/collection/upgrade-module/schema.d.ts | 2 +- .../src/collection/upgrade-module/schema.json | 12 +- .../upgrade-module/upgrade-module.spec.ts | 17 +- .../src/collection/workspace/index.ts | 720 +++++++++--------- packages/schematics/src/utils/ast-utils.ts | 44 +- .../schematics/src/utils/testing-utils.ts | 34 +- tsconfig.json | 1 - 15 files changed, 437 insertions(+), 458 deletions(-) diff --git a/e2e/schematics/downgrade-module.test.ts b/e2e/schematics/downgrade-module.test.ts index 8f55e8b035..579380ae17 100644 --- a/e2e/schematics/downgrade-module.test.ts +++ b/e2e/schematics/downgrade-module.test.ts @@ -1,6 +1,6 @@ import { newApp, newProject, runCLI, updateFile } from '../utils'; -xdescribe('DowngradeModule', () => { +describe('DowngradeModule', () => { it( 'should generate a downgradeModule setup', () => { @@ -12,10 +12,12 @@ xdescribe('DowngradeModule', () => { `window.angular.module('legacy', []);` ); - runCLI('generate downgrade-module legacy --angularJsImport=./legacy'); + runCLI( + 'generate downgrade-module legacy --angularJsImport=./legacy --project=myapp' + ); 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 ); diff --git a/e2e/schematics/upgrade-module.test.ts b/e2e/schematics/upgrade-module.test.ts index 1407ca3a14..5d725d9ab6 100644 --- a/e2e/schematics/upgrade-module.test.ts +++ b/e2e/schematics/upgrade-module.test.ts @@ -1,7 +1,7 @@ import { newApp, newProject, runCLI, updateFile } from '../utils'; -xdescribe('Upgrade', () => { - it( +describe('Upgrade', () => { + fit( 'should generate an UpgradeModule setup', () => { newProject(); @@ -28,7 +28,7 @@ xdescribe('Upgrade', () => { runCLI( 'generate upgrade-module legacy --angularJsImport=./legacy ' + - '--angularJsCmpSelector=rootLegacyCmp' + '--angularJsCmpSelector=rootLegacyCmp --project=myapp' ); runCLI('build'); diff --git a/packages/schematics/src/collection/downgrade-module/downgrade-module.spec.ts b/packages/schematics/src/collection/downgrade-module/downgrade-module.spec.ts index 3b104f0ab7..9ce8bfe622 100644 --- a/packages/schematics/src/collection/downgrade-module/downgrade-module.spec.ts +++ b/packages/schematics/src/collection/downgrade-module/downgrade-module.spec.ts @@ -5,7 +5,7 @@ import { createApp, createEmptyWorkspace } from '../../utils/testing-utils'; import { getFileContent } from '@schematics/angular/utility/test'; import { readJsonInTree } from '../../utils/ast-utils'; -xdescribe('downgrade-module', () => { +describe('downgrade-module', () => { const schematicRunner = new SchematicTestRunner( '@nrwl/schematics', path.join(__dirname, '../../collection.json') @@ -23,7 +23,8 @@ xdescribe('downgrade-module', () => { const tree = schematicRunner.runSchematic( 'downgrade-module', { - name: 'legacy' + name: 'legacy', + project: 'myapp' }, appTree ); @@ -40,7 +41,8 @@ xdescribe('downgrade-module', () => { const tree = schematicRunner.runSchematic( 'downgrade-module', { - name: 'legacy' + name: 'legacy', + project: 'myapp' }, appTree ); @@ -64,7 +66,8 @@ xdescribe('downgrade-module', () => { const tree = schematicRunner.runSchematic( 'downgrade-module', { - name: 'legacy' + name: 'legacy', + project: 'myapp' }, appTree ); @@ -88,7 +91,8 @@ xdescribe('downgrade-module', () => { 'downgrade-module', { name: 'legacy', - skipPackageJson: true + skipPackageJson: true, + project: 'myapp' }, appTree ); @@ -102,7 +106,8 @@ xdescribe('downgrade-module', () => { 'downgrade-module', { name: 'legacy', - angularJsImport: 'legacy-app' + angularJsImport: 'legacy-app', + project: 'myapp' }, appTree ); diff --git a/packages/schematics/src/collection/downgrade-module/index.ts b/packages/schematics/src/collection/downgrade-module/index.ts index 9580de67f8..8cfdef456e 100644 --- a/packages/schematics/src/collection/downgrade-module/index.ts +++ b/packages/schematics/src/collection/downgrade-module/index.ts @@ -18,7 +18,7 @@ function updateMain(angularJsImport: string, options: Schema): Rule { moduleSpec, bootstrapComponentClassName, bootstrapComponentFileName - } = readBootstrapInfo(host, options.app); + } = readBootstrapInfo(host, options.project); host.overwrite( mainPath, @@ -27,7 +27,7 @@ function updateMain(angularJsImport: string, options: Schema): Rule { import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 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 { environment } from './environments/environment'; @@ -35,7 +35,7 @@ import '${angularJsImport}'; import { ${bootstrapComponentClassName} } from '${bootstrapComponentFileName}'; export function bootstrapAngular(extra: StaticProvider[]): any { - setAngularLib(angular); + setAngularJSGlobal(angular); if (environment.production) { enableProdMode(); } @@ -59,7 +59,7 @@ function rewriteBootstrapLogic(options: Schema): Rule { return (host: Tree) => { const { modulePath, moduleSource, moduleClassName } = readBootstrapInfo( host, - options.app + options.project ); insert(host, modulePath, [ ...addMethod(moduleSource, modulePath, { @@ -78,7 +78,7 @@ function addEntryComponentsToModule(options: Schema): Rule { modulePath, moduleSource, bootstrapComponentClassName - } = readBootstrapInfo(host, options.app); + } = readBootstrapInfo(host, options.project); insert( host, modulePath, diff --git a/packages/schematics/src/collection/downgrade-module/schema.d.ts b/packages/schematics/src/collection/downgrade-module/schema.d.ts index c7189a93b6..ff5167442e 100644 --- a/packages/schematics/src/collection/downgrade-module/schema.d.ts +++ b/packages/schematics/src/collection/downgrade-module/schema.d.ts @@ -2,5 +2,5 @@ export interface Schema { angularJsImport: string; name: string; skipPackageJson: boolean; - app: string; + project: string; } diff --git a/packages/schematics/src/collection/downgrade-module/schema.json b/packages/schematics/src/collection/downgrade-module/schema.json index ef32ac3ec3..7991dee52f 100644 --- a/packages/schematics/src/collection/downgrade-module/schema.json +++ b/packages/schematics/src/collection/downgrade-module/schema.json @@ -4,13 +4,17 @@ "title": "Generates downgradeModule setup", "type": "object", "properties": { - "app": { + "project": { "type": "string", - "description": "The name of the application" + "description": "The name of the project" }, "name": { "type": "string", - "description": "The name of the main AngularJS module." + "description": "The name of the main AngularJS module.", + "$default": { + "$source": "argv", + "index": 0 + } }, "angularJsImport": { "type": "string", @@ -23,6 +27,6 @@ } }, "required": [ - "name" + "project" ] } diff --git a/packages/schematics/src/collection/upgrade-module/files/__name__-setup.ts__tmpl__ b/packages/schematics/src/collection/upgrade-module/files/__name__-setup.ts__tmpl__ index ef14864b11..100d98077e 100644 --- a/packages/schematics/src/collection/upgrade-module/files/__name__-setup.ts__tmpl__ +++ b/packages/schematics/src/collection/upgrade-module/files/__name__-setup.ts__tmpl__ @@ -1,5 +1,5 @@ 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) { %> import {Router} from '@angular/router'; import {setUpLocationSync} from '@angular/router/upgrade'; @@ -35,7 +35,7 @@ export const upgradedComponents = []; // additional configuration invoked right before bootstrap export function configure<%= className %>(i: Injector) { - setAngularLib(angular); + setAngularJSGlobal(angular); // Insert additional configuration here <% if (router) { %> angular.module('downgraded').run(() => { diff --git a/packages/schematics/src/collection/upgrade-module/index.ts b/packages/schematics/src/collection/upgrade-module/index.ts index 7b03b5f1a9..d033125150 100644 --- a/packages/schematics/src/collection/upgrade-module/index.ts +++ b/packages/schematics/src/collection/upgrade-module/index.ts @@ -34,7 +34,7 @@ function addImportsToModule(options: Schema): Rule { return (host: Tree) => { const { moduleClassName, modulePath, moduleSource } = readBootstrapInfo( host, - options.app + options.project ); insert(host, modulePath, [ @@ -71,7 +71,7 @@ function addNgDoBootstrapToModule(options: Schema): Rule { return (host: Tree) => { const { moduleClassName, modulePath, moduleSource } = readBootstrapInfo( host, - options.app + options.project ); insert(host, modulePath, [ @@ -102,7 +102,7 @@ function createFiles(angularJsImport: string, options: Schema): Rule { moduleSpec, bootstrapComponentClassName, bootstrapComponentFileName - } = readBootstrapInfo(host, options.app); + } = readBootstrapInfo(host, options.project); const dir = path.dirname(mainPath); const templateSource = apply(url('./files'), [ diff --git a/packages/schematics/src/collection/upgrade-module/schema.d.ts b/packages/schematics/src/collection/upgrade-module/schema.d.ts index 3646391cbf..748844d013 100644 --- a/packages/schematics/src/collection/upgrade-module/schema.d.ts +++ b/packages/schematics/src/collection/upgrade-module/schema.d.ts @@ -1,5 +1,5 @@ export interface Schema { - app: string; + project: string; angularJsImport: string; angularJsCmpSelector: string; name: string; diff --git a/packages/schematics/src/collection/upgrade-module/schema.json b/packages/schematics/src/collection/upgrade-module/schema.json index 18634a5f59..3feb177ac9 100644 --- a/packages/schematics/src/collection/upgrade-module/schema.json +++ b/packages/schematics/src/collection/upgrade-module/schema.json @@ -4,13 +4,17 @@ "title": "Generates UpgradeModule setup", "type": "object", "properties": { - "app": { + "project": { "type": "string", - "description": "The name of the application" + "description": "The name of the project" }, "name": { "type": "string", - "description": "The name of the main AngularJS module." + "description": "The name of the main AngularJS module.", + "$default": { + "$source": "argv", + "index": 0 + } }, "angularJsImport": { "type": "string", @@ -32,6 +36,6 @@ } }, "required": [ - "name" + "project" ] } diff --git a/packages/schematics/src/collection/upgrade-module/upgrade-module.spec.ts b/packages/schematics/src/collection/upgrade-module/upgrade-module.spec.ts index 5f4f023260..a13297fae7 100644 --- a/packages/schematics/src/collection/upgrade-module/upgrade-module.spec.ts +++ b/packages/schematics/src/collection/upgrade-module/upgrade-module.spec.ts @@ -5,7 +5,7 @@ import { createApp, createEmptyWorkspace } from '../../utils/testing-utils'; import { getFileContent } from '@schematics/angular/utility/test'; import { readJsonInTree } from '../../utils/ast-utils'; -xdescribe('upgrade-module', () => { +describe('upgrade-module', () => { const schematicRunner = new SchematicTestRunner( '@nrwl/schematics', path.join(__dirname, '../../collection.json') @@ -23,7 +23,8 @@ xdescribe('upgrade-module', () => { const tree = schematicRunner.runSchematic( 'upgrade-module', { - name: 'legacy' + name: 'legacy', + project: 'myapp' }, appTree ); @@ -53,7 +54,8 @@ xdescribe('upgrade-module', () => { const tree = schematicRunner.runSchematic( 'upgrade-module', { - name: 'legacy' + name: 'legacy', + project: 'myapp' }, appTree ); @@ -77,7 +79,8 @@ xdescribe('upgrade-module', () => { 'upgrade-module', { name: 'legacy', - skipPackageJson: true + skipPackageJson: true, + project: 'myapp' }, appTree ); @@ -91,7 +94,8 @@ xdescribe('upgrade-module', () => { 'upgrade-module', { name: 'legacy', - router: true + router: true, + project: 'myapp' }, appTree ); @@ -105,7 +109,8 @@ xdescribe('upgrade-module', () => { 'upgrade-module', { name: 'legacy', - angularJsImport: 'legacy-app' + angularJsImport: 'legacy-app', + project: 'myapp' }, appTree ); diff --git a/packages/schematics/src/collection/workspace/index.ts b/packages/schematics/src/collection/workspace/index.ts index d36f905c19..42013beff3 100755 --- a/packages/schematics/src/collection/workspace/index.ts +++ b/packages/schematics/src/collection/workspace/index.ts @@ -1,383 +1,351 @@ -import { - apply, - branchAndMerge, - chain, - mergeWith, - Rule, - SchematicContext, - Tree, - url -} from '@angular-devkit/schematics'; +import { chain, Rule } from '@angular-devkit/schematics'; 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() { - return updateJsonInTree('package.json', packageJson => { - if (!packageJson.devDependencies) { - packageJson.devDependencies = {}; - } - if (!packageJson.dependencies) { - packageJson.dependencies = {}; - } - if (!packageJson.scripts) { - packageJson.scripts = {}; - } - if (!packageJson.dependencies['@nrwl/nx']) { - packageJson.dependencies['@nrwl/nx'] = nxVersion; - } - if (!packageJson.dependencies['@ngrx/store']) { - packageJson.dependencies['@ngrx/store'] = ngrxVersion; - } - if (!packageJson.dependencies['@ngrx/router-store']) { - packageJson.dependencies['@ngrx/router-store'] = routerStoreVersion; - } - if (!packageJson.dependencies['@ngrx/effects']) { - packageJson.dependencies['@ngrx/effects'] = ngrxVersion; - } - if (!packageJson.dependencies['@ngrx/store-devtools']) { - packageJson.dependencies['@ngrx/store-devtools'] = ngrxVersion; - } - if (!packageJson.dependencies['ngrx-store-freeze']) { - packageJson.dependencies['ngrx-store-freeze'] = ngrxStoreFreezeVersion; - } - if (!packageJson.devDependencies['@nrwl/schematics']) { - packageJson.devDependencies['@nrwl/schematics'] = schematicsVersion; - } - if (!packageJson.dependencies['@angular/cli']) { - packageJson.dependencies['@angular/cli'] = angularCliVersion; - } - if (!packageJson.devDependencies['prettier']) { - packageJson.devDependencies['prettier'] = prettierVersion; - } - - packageJson.scripts['affected:apps'] = - './node_modules/.bin/nx affected:apps'; - packageJson.scripts['affected:build'] = - './node_modules/.bin/nx affected:build'; - packageJson.scripts['affected:e2e'] = './node_modules/.bin/nx affected:e2e'; - - packageJson.scripts['affected:dep-graph'] = - './node_modules/.bin/nx affected:dep-graph'; - - packageJson.scripts['format'] = './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['update'] = './node_modules/.bin/nx update'; - packageJson.scripts['update:check'] = './node_modules/.bin/nx update:check'; - packageJson.scripts['update:skip'] = './node_modules/.bin/nx update:skip'; - - packageJson.scripts['lint'] = './node_modules/.bin/nx lint && ng lint'; - - packageJson.scripts['dep-graph'] = './node_modules/.bin/nx dep-graph'; - - packageJson.scripts['postinstall'] = './node_modules/.bin/nx postinstall'; - packageJson.scripts['workspace-schematic'] = - './node_modules/.bin/nx workspace-schematic'; - - return packageJson; - }); -} - -function updateAngularCLIJson(options: Schema): Rule { - return updateJsonInTree('.angular-cli.json', angularCliJson => { - angularCliJson.$schema = angularCliSchema; - angularCliJson.project.npmScope = npmScope(options); - angularCliJson.project.latestMigration = latestMigration; - - if (angularCliJson.apps.length !== 1) { - throw new Error('Can only convert projects with one app'); - } - - const app = angularCliJson.apps[0]; - app.name = options.name; - app.root = path.join('apps', options.name, app.root); - app.outDir = path.join('dist', 'apps', options.name); - app.test = '../../../test.js'; - app.testTsconfig = '../../../tsconfig.spec.json'; - app.scripts = app.scripts.map(p => path.join('../../', p)); - app.tags = []; - if (!angularCliJson.defaults) { - angularCliJson.defaults = {}; - } - if (!angularCliJson.defaults.schematics) { - angularCliJson.defaults.schematics = {}; - } - angularCliJson.defaults.schematics['collection'] = '@nrwl/schematics'; - angularCliJson.defaults.schematics['postGenerate'] = 'npm run format'; - angularCliJson.defaults.schematics['newProject'] = ['app', 'lib']; - - angularCliJson.lint = [ - { - project: `${app.root}/tsconfig.app.json`, - exclude: '**/node_modules/**' - }, - { - project: './tsconfig.spec.json', - exclude: '**/node_modules/**' - }, - { - project: join('apps', options.name, 'e2e', 'tsconfig.e2e.json'), - exclude: '**/node_modules/**' - } - ]; - - return angularCliJson; - }); -} - -function updateTsConfig(options: Schema): Rule { - return updateJsonInTree('tsconfig.json', tsConfigJson => - setUpCompilerOptions(tsConfigJson, npmScope(options), '') - ); -} - -function updateTsConfigsJson(options: Schema) { - return (host: Tree) => { - const angularCliJson = getAngularCliConfig(host); - const app = angularCliJson.apps[0]; - - // This has to stay using fs since it is created with fs - const offset = '../../../'; - updateJsonFile(`${app.root}/tsconfig.app.json`, json => { - json.extends = `${offset}tsconfig.json`; - json.compilerOptions.outDir = `${offset}dist/out-tsc/apps/${ - options.name - }`; - if (!json.exclude) json.exclude = []; - json.exclude = dedup(json.exclude.concat(['**/*.spec.ts'])); - - if (!json.include) json.include = []; - json.include = dedup(json.include.concat(['**/*.ts'])); - }); - - // This has to stay using fs since it is created with fs - updateJsonFile('tsconfig.spec.json', json => { - json.extends = './tsconfig.json'; - json.compilerOptions.outDir = `./dist/out-tsc/spec`; - - if (!json.exclude) json.exclude = []; - json.files = ['test.js']; - json.include = ['**/*.ts']; - json.exclude = dedup( - json.exclude.concat([ - '**/e2e/*.ts', - '**/*.e2e-spec.ts', - '**/*.po.ts', - 'node_modules', - 'tmp' - ]) - ); - }); - - // This has to stay using fs since it is created with fs - updateJsonFile(`apps/${options.name}/e2e/tsconfig.e2e.json`, json => { - json.extends = `${offset}tsconfig.json`; - json.compilerOptions.outDir = `${offset}dist/out-tsc/e2e/${options.name}`; - if (!json.exclude) json.exclude = []; - json.exclude = dedup(json.exclude.concat(['**/*.spec.ts'])); - - if (!json.include) json.include = []; - json.include = dedup(json.include.concat(['../**/*.ts'])); - }); - - return host; - }; -} - -function updateTsLint() { - return updateJsonInTree('tslint.json', tslintJson => { - [ - 'no-trailing-whitespace', - 'one-line', - 'quotemark', - 'typedef-whitespace', - 'whitespace' - ].forEach(key => { - tslintJson[key] = undefined; - }); - tslintJson.rulesDirectory = tslintJson.rulesDirectory || []; - tslintJson.rulesDirectory.push('node_modules/@nrwl/schematics/src/tslint'); - tslintJson['nx-enforce-module-boundaries'] = [ - true, - { - allow: [], - depConstraints: [{ sourceTag: '*', onlyDependOnLibsWithTags: ['*'] }] - } - ]; - return tslintJson; - }); -} - -function npmScope(options: Schema): string { - return options && options.npmScope ? options.npmScope : options.name; -} - -function updateKarmaConf() { - return (host: Tree, context: SchematicContext) => { - const angularCliJson = getAngularCliConfig(host); - - const karmaConfig = angularCliJson.test!.karma; - - if (!karmaConfig) { - return; - } - - const karmaConfPath = karmaConfig.config; - - const contents = host.read(karmaConfPath).toString(); - - const change = new InsertChange( - karmaConfPath, - contents.indexOf('module.exports ='), - stripIndents` - const { makeSureNoAppIsSelected } = require('@nrwl/schematics/src/utils/cli-config-utils'); - // Nx only supports running unit tests for all apps and libs. - makeSureNoAppIsSelected(); - ` + '\n\n' - ); - - insert(host, karmaConfPath, [change]); - - return host; - }; -} - -function updateProtractorConf() { - return (host: Tree) => { - if (!host.exists('protractor.conf.js')) { - throw new Error('Cannot find protractor.conf.js'); - } - const protractorConf = host.read('protractor.conf.js')!.toString('utf-8'); - const updatedConf = protractorConf - .replace(`'./e2e/**/*.e2e-spec.ts'`, `appDir + '/e2e/**/*.e2e-spec.ts'`) - .replace(`'e2e/tsconfig.e2e.json'`, `appDir + '/e2e/tsconfig.e2e.json'`) - .replace( - `exports.config = {`, - ` -const { getAppDirectoryUsingCliConfig } = require('@nrwl/schematics/src/utils/cli-config-utils'); -const appDir = getAppDirectoryUsingCliConfig(); -exports.config = { -` - ); - - host.overwrite('protractor.conf.js', updatedConf); - - return host; - }; -} - -function setUpCompilerOptions( - tsconfig: any, - npmScope: string, - offset: string -): any { - if (!tsconfig.compilerOptions.paths) { - tsconfig.compilerOptions.paths = {}; - } - tsconfig.compilerOptions.baseUrl = '.'; - tsconfig.compilerOptions.paths[`@${npmScope}/*`] = [`${offset}libs/*`]; - - return tsconfig; -} - -function moveExistingFiles(options: Schema) { - return (host: Tree) => { - const angularCliJson = getAngularCliConfig(host); - const app = angularCliJson.apps[0]; - - fs.mkdirSync('apps'); - fs.mkdirSync('libs'); - fs.unlinkSync(path.join(app.root, app.test)); - fs.mkdirSync(path.join('apps', options.name)); - fs.renameSync(path.join(app.root, app.testTsconfig), 'tsconfig.spec.json'); - fs.renameSync(app.root, join('apps', options.name, app.root)); - fs.renameSync('e2e', join('apps', options.name, 'e2e')); - - return host; - }; -} - -function createAdditionalFiles(options: Schema) { - return (host: Tree, _context: SchematicContext) => { - // if the user does not already have a prettier configuration - // of any kind, create one - // return fromPromise(resolveUserExistingPrettierConfig()).pipe( - // tap(resolvedExistingConfig => { - // if (!resolvedExistingConfig) { - // fs.writeFileSync( - // '.prettierrc', - // JSON.stringify(DEFAULT_NRWL_PRETTIER_CONFIG, null, 2) - // ); - // } - // }), - // map(() => host) - // ); - }; -} - -function dedup(array: any[]): any[] { - const res = []; - - array.forEach(a => { - if (res.indexOf(a) === -1) { - res.push(a); - } - }); - return res; -} - -function checkCanConvertToWorkspace(options: Schema) { - return (host: Tree) => { - if (!host.exists('package.json')) { - throw new Error('Cannot find package.json'); - } - if (!host.exists('protractor.conf.js')) { - throw new Error('Cannot find protractor.conf.js'); - } - const angularCliJson = getAngularCliConfig(host); - if (angularCliJson.apps.length !== 1) { - throw new Error('Can only convert projects with one app'); - } - return host; - }; -} +// function updatePackageJson() { +// return updateJsonInTree('package.json', packageJson => { +// if (!packageJson.devDependencies) { +// packageJson.devDependencies = {}; +// } +// if (!packageJson.dependencies) { +// packageJson.dependencies = {}; +// } +// if (!packageJson.scripts) { +// packageJson.scripts = {}; +// } +// if (!packageJson.dependencies['@nrwl/nx']) { +// packageJson.dependencies['@nrwl/nx'] = nxVersion; +// } +// if (!packageJson.dependencies['@ngrx/store']) { +// packageJson.dependencies['@ngrx/store'] = ngrxVersion; +// } +// if (!packageJson.dependencies['@ngrx/router-store']) { +// packageJson.dependencies['@ngrx/router-store'] = routerStoreVersion; +// } +// if (!packageJson.dependencies['@ngrx/effects']) { +// packageJson.dependencies['@ngrx/effects'] = ngrxVersion; +// } +// if (!packageJson.dependencies['@ngrx/store-devtools']) { +// packageJson.dependencies['@ngrx/store-devtools'] = ngrxVersion; +// } +// if (!packageJson.dependencies['ngrx-store-freeze']) { +// packageJson.dependencies['ngrx-store-freeze'] = ngrxStoreFreezeVersion; +// } +// if (!packageJson.devDependencies['@nrwl/schematics']) { +// packageJson.devDependencies['@nrwl/schematics'] = schematicsVersion; +// } +// if (!packageJson.dependencies['@angular/cli']) { +// packageJson.dependencies['@angular/cli'] = angularCliVersion; +// } +// if (!packageJson.devDependencies['prettier']) { +// packageJson.devDependencies['prettier'] = prettierVersion; +// } +// +// packageJson.scripts['affected:apps'] = +// './node_modules/.bin/nx affected:apps'; +// packageJson.scripts['affected:build'] = +// './node_modules/.bin/nx affected:build'; +// packageJson.scripts['affected:e2e'] = './node_modules/.bin/nx affected:e2e'; +// +// packageJson.scripts['affected:dep-graph'] = +// './node_modules/.bin/nx affected:dep-graph'; +// +// packageJson.scripts['format'] = './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['update'] = './node_modules/.bin/nx update'; +// packageJson.scripts['update:check'] = './node_modules/.bin/nx update:check'; +// packageJson.scripts['update:skip'] = './node_modules/.bin/nx update:skip'; +// +// packageJson.scripts['lint'] = './node_modules/.bin/nx lint && ng lint'; +// +// packageJson.scripts['dep-graph'] = './node_modules/.bin/nx dep-graph'; +// +// packageJson.scripts['postinstall'] = './node_modules/.bin/nx postinstall'; +// packageJson.scripts['workspace-schematic'] = +// './node_modules/.bin/nx workspace-schematic'; +// +// return packageJson; +// }); +// } +// +// function updateAngularCLIJson(options: Schema): Rule { +// return updateJsonInTree('.angular-cli.json', angularCliJson => { +// angularCliJson.$schema = angularCliSchema; +// angularCliJson.project.npmScope = npmScope(options); +// angularCliJson.project.latestMigration = latestMigration; +// +// if (angularCliJson.apps.length !== 1) { +// throw new Error('Can only convert projects with one app'); +// } +// +// const app = angularCliJson.apps[0]; +// app.name = options.name; +// app.root = path.join('apps', options.name, app.root); +// app.outDir = path.join('dist', 'apps', options.name); +// app.test = '../../../test.js'; +// app.testTsconfig = '../../../tsconfig.spec.json'; +// app.scripts = app.scripts.map(p => path.join('../../', p)); +// app.tags = []; +// if (!angularCliJson.defaults) { +// angularCliJson.defaults = {}; +// } +// if (!angularCliJson.defaults.schematics) { +// angularCliJson.defaults.schematics = {}; +// } +// angularCliJson.defaults.schematics['collection'] = '@nrwl/schematics'; +// angularCliJson.defaults.schematics['postGenerate'] = 'npm run format'; +// angularCliJson.defaults.schematics['newProject'] = ['app', 'lib']; +// +// angularCliJson.lint = [ +// { +// project: `${app.root}/tsconfig.app.json`, +// exclude: '**/node_modules/**' +// }, +// { +// project: './tsconfig.spec.json', +// exclude: '**/node_modules/**' +// }, +// { +// project: join('apps', options.name, 'e2e', 'tsconfig.e2e.json'), +// exclude: '**/node_modules/**' +// } +// ]; +// +// return angularCliJson; +// }); +// } +// +// function updateTsConfig(options: Schema): Rule { +// return updateJsonInTree('tsconfig.json', tsConfigJson => +// setUpCompilerOptions(tsConfigJson, npmScope(options), '') +// ); +// } +// +// function updateTsConfigsJson(options: Schema) { +// return (host: Tree) => { +// const angularCliJson = getAngularCliConfig(host); +// const app = angularCliJson.apps[0]; +// +// // This has to stay using fs since it is created with fs +// const offset = '../../../'; +// updateJsonFile(`${app.root}/tsconfig.app.json`, json => { +// json.extends = `${offset}tsconfig.json`; +// json.compilerOptions.outDir = `${offset}dist/out-tsc/apps/${ +// options.name +// }`; +// if (!json.exclude) json.exclude = []; +// json.exclude = dedup(json.exclude.concat(['**/*.spec.ts'])); +// +// if (!json.include) json.include = []; +// json.include = dedup(json.include.concat(['**/*.ts'])); +// }); +// +// // This has to stay using fs since it is created with fs +// updateJsonFile('tsconfig.spec.json', json => { +// json.extends = './tsconfig.json'; +// json.compilerOptions.outDir = `./dist/out-tsc/spec`; +// +// if (!json.exclude) json.exclude = []; +// json.files = ['test.js']; +// json.include = ['**/*.ts']; +// json.exclude = dedup( +// json.exclude.concat([ +// '**/e2e/*.ts', +// '**/*.e2e-spec.ts', +// '**/*.po.ts', +// 'node_modules', +// 'tmp' +// ]) +// ); +// }); +// +// // This has to stay using fs since it is created with fs +// updateJsonFile(`apps/${options.name}/e2e/tsconfig.e2e.json`, json => { +// json.extends = `${offset}tsconfig.json`; +// json.compilerOptions.outDir = `${offset}dist/out-tsc/e2e/${options.name}`; +// if (!json.exclude) json.exclude = []; +// json.exclude = dedup(json.exclude.concat(['**/*.spec.ts'])); +// +// if (!json.include) json.include = []; +// json.include = dedup(json.include.concat(['../**/*.ts'])); +// }); +// +// return host; +// }; +// } +// +// function updateTsLint() { +// return updateJsonInTree('tslint.json', tslintJson => { +// [ +// 'no-trailing-whitespace', +// 'one-line', +// 'quotemark', +// 'typedef-whitespace', +// 'whitespace' +// ].forEach(key => { +// tslintJson[key] = undefined; +// }); +// tslintJson.rulesDirectory = tslintJson.rulesDirectory || []; +// tslintJson.rulesDirectory.push('node_modules/@nrwl/schematics/src/tslint'); +// tslintJson['nx-enforce-module-boundaries'] = [ +// true, +// { +// allow: [], +// depConstraints: [{ sourceTag: '*', onlyDependOnLibsWithTags: ['*'] }] +// } +// ]; +// return tslintJson; +// }); +// } +// +// function npmScope(options: Schema): string { +// return options && options.npmScope ? options.npmScope : options.name; +// } +// +// function updateKarmaConf() { +// return (host: Tree, context: SchematicContext) => { +// const angularCliJson = getAngularCliConfig(host); +// +// const karmaConfig = angularCliJson.test!.karma; +// +// if (!karmaConfig) { +// return; +// } +// +// const karmaConfPath = karmaConfig.config; +// +// const contents = host.read(karmaConfPath).toString(); +// +// const change = new InsertChange( +// karmaConfPath, +// contents.indexOf('module.exports ='), +// stripIndents` +// const { makeSureNoAppIsSelected } = require('@nrwl/schematics/src/utils/cli-config-utils'); +// // Nx only supports running unit tests for all apps and libs. +// makeSureNoAppIsSelected(); +// ` + '\n\n' +// ); +// +// insert(host, karmaConfPath, [change]); +// +// return host; +// }; +// } +// +// function updateProtractorConf() { +// return (host: Tree) => { +// if (!host.exists('protractor.conf.js')) { +// throw new Error('Cannot find protractor.conf.js'); +// } +// const protractorConf = host.read('protractor.conf.js')!.toString('utf-8'); +// const updatedConf = protractorConf +// .replace(`'./e2e/**/*.e2e-spec.ts'`, `appDir + '/e2e/**/*.e2e-spec.ts'`) +// .replace(`'e2e/tsconfig.e2e.json'`, `appDir + '/e2e/tsconfig.e2e.json'`) +// .replace( +// `exports.config = {`, +// ` +// const { getAppDirectoryUsingCliConfig } = require('@nrwl/schematics/src/utils/cli-config-utils'); +// const appDir = getAppDirectoryUsingCliConfig(); +// exports.config = { +// ` +// ); +// +// host.overwrite('protractor.conf.js', updatedConf); +// +// return host; +// }; +// } +// +// function setUpCompilerOptions( +// tsconfig: any, +// npmScope: string, +// offset: string +// ): any { +// if (!tsconfig.compilerOptions.paths) { +// tsconfig.compilerOptions.paths = {}; +// } +// tsconfig.compilerOptions.baseUrl = '.'; +// tsconfig.compilerOptions.paths[`@${npmScope}/*`] = [`${offset}libs/*`]; +// +// return tsconfig; +// } +// +// function moveExistingFiles(options: Schema) { +// return (host: Tree) => { +// const angularCliJson = getAngularCliConfig(host); +// const app = angularCliJson.apps[0]; +// +// fs.mkdirSync('apps'); +// fs.mkdirSync('libs'); +// fs.unlinkSync(path.join(app.root, app.test)); +// fs.mkdirSync(path.join('apps', options.name)); +// fs.renameSync(path.join(app.root, app.testTsconfig), 'tsconfig.spec.json'); +// fs.renameSync(app.root, join('apps', options.name, app.root)); +// fs.renameSync('e2e', join('apps', options.name, 'e2e')); +// +// return host; +// }; +// } +// +// function createAdditionalFiles(options: Schema) { +// return (host: Tree, _context: SchematicContext) => { +// // if the user does not already have a prettier configuration +// // of any kind, create one +// // return fromPromise(resolveUserExistingPrettierConfig()).pipe( +// // tap(resolvedExistingConfig => { +// // if (!resolvedExistingConfig) { +// // fs.writeFileSync( +// // '.prettierrc', +// // JSON.stringify(DEFAULT_NRWL_PRETTIER_CONFIG, null, 2) +// // ); +// // } +// // }), +// // map(() => host) +// // ); +// }; +// } +// +// function dedup(array: any[]): any[] { +// const res = []; +// +// array.forEach(a => { +// if (res.indexOf(a) === -1) { +// res.push(a); +// } +// }); +// return res; +// } +// +// function checkCanConvertToWorkspace(options: Schema) { +// return (host: Tree) => { +// if (!host.exists('package.json')) { +// throw new Error('Cannot find package.json'); +// } +// if (!host.exists('protractor.conf.js')) { +// throw new Error('Cannot find protractor.conf.js'); +// } +// const angularCliJson = getAngularCliConfig(host); +// if (angularCliJson.apps.length !== 1) { +// throw new Error('Can only convert projects with one app'); +// } +// return host; +// }; +// } export default function(schema: Schema): Rule { - const options = { ...schema, name: toFileName(schema.name) }; + // const options = { ...schema, name: toFileName(schema.name) }; return chain([ - checkCanConvertToWorkspace(options), - moveExistingFiles(options), - createAdditionalFiles(options), - branchAndMerge(chain([mergeWith(apply(url('./files'), []))])), - updatePackageJson(), - updateAngularCLIJson(options), - updateTsLint(), - updateTsConfig(options), - updateTsConfigsJson(options), - updateKarmaConf(), - updateProtractorConf() + // checkCanConvertToWorkspace(options), + // moveExistingFiles(options), + // createAdditionalFiles(options), + // branchAndMerge(chain([mergeWith(apply(url('./files'), []))])), + // updatePackageJson(), + // updateAngularCLIJson(options), + // updateTsLint(), + // updateTsConfig(options), + // updateTsConfigsJson(options), + // updateKarmaConf(), + // updateProtractorConf() ]); } diff --git a/packages/schematics/src/utils/ast-utils.ts b/packages/schematics/src/utils/ast-utils.ts index ca251cd503..909ff92f83 100755 --- a/packages/schematics/src/utils/ast-utils.ts +++ b/packages/schematics/src/utils/ast-utils.ts @@ -5,7 +5,7 @@ * 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 */ -import { Tree, Rule } from '@angular-devkit/schematics'; +import { Rule, Tree } from '@angular-devkit/schematics'; import { findNodes, getDecoratorMetadata, @@ -575,31 +575,14 @@ export function updateJsonInTree( }; } -// TODO DELETE THIS -/** - * This method is specifically for getting the .angular-cli.json data from a Tree - * @param host The host tree - */ -export function getAngularCliConfig(host: Tree) { - return readJsonInTree(host, '.angular-cli.json'); -} - -// 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}'`); +function getProjectConfig(host: Tree, name: string): any { + const angularJson = readJsonInTree(host, '/angular.json'); + const projectConfig = angularJson.projects[name]; + if (!projectConfig) { + throw new Error(`Cannot find project '${name}'`); + } else { + return projectConfig; } - 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( @@ -614,8 +597,15 @@ export function readBootstrapInfo( bootstrapComponentClassName: string; bootstrapComponentFileName: string; } { - const config = getAppConfig(host, app); - const mainPath = path.join(config.root, config.main); + const config = getProjectConfig(host, app); + + let mainPath; + try { + mainPath = config.architect.build.options.main; + } catch (e) { + throw new Error('Main file cannot be located'); + } + if (!host.exists(mainPath)) { throw new Error('Main file cannot be located'); } diff --git a/packages/schematics/src/utils/testing-utils.ts b/packages/schematics/src/utils/testing-utils.ts index 07c0f39b6b..8a71acb258 100644 --- a/packages/schematics/src/utils/testing-utils.ts +++ b/packages/schematics/src/utils/testing-utils.ts @@ -96,21 +96,23 @@ export function createApp( include: ['../**/*.ts'] }) ); - // tree.overwrite( - // '/angular.json', - // JSON.stringify({ - // projects: { - // - // }, - // apps: [ - // { - // name: appName, - // root: `apps/${appName}/src`, - // main: 'main.ts', - // index: 'index.html' - // } - // ] - // }) - // ); + tree.overwrite( + '/angular.json', + JSON.stringify({ + newProjectRoot: '', + projects: { + [appName]: { + root: `apps/${appName}/src`, + architect: { + build: { + options: { + main: `apps/${appName}/src/main.ts` + } + } + } + } + } + }) + ); return tree; } diff --git a/tsconfig.json b/tsconfig.json index 4e6cc27987..62da300793 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,7 +7,6 @@ "typeRoots": ["node_modules/@types"], "experimentalDecorators": true, "emitDecoratorMetadata": true, - "noUnusedLocals": true, "skipLibCheck": true, "lib": ["es2017"], "declaration": true,