From 9f43be01fe9bbbbc46df0c7025d07addc9cf7401 Mon Sep 17 00:00:00 2001 From: Jan Kuri Date: Thu, 28 Jul 2016 00:11:27 +0200 Subject: [PATCH] refactor(RC5): prepare for RC5 --- addon/ng2/blueprints/component/index.js | 26 +++++++++----- addon/ng2/blueprints/directive/index.js | 26 +++++++++----- addon/ng2/blueprints/interface/index.js | 16 ++++++--- .../mobile/files/__path__/app-shell-module.ts | 19 ++++++++++ .../mobile/files/__path__/main-app-shell.ts | 22 ++++++------ .../files/__path__/app/app.component.spec.ts | 29 ++++++++------- .../ng2/files/__path__/app/app.module.ts | 24 +++++++++++++ .../ng2/files/__path__/app/index.ts | 1 + .../ng2/blueprints/ng2/files/__path__/main.ts | 7 ++-- .../ng2/blueprints/ng2/files/angular-cli.json | 1 + addon/ng2/blueprints/ng2/files/package.json | 32 ++++++++--------- addon/ng2/blueprints/pipe/index.js | 28 ++++++++++----- addon/ng2/utilities/ast-utils.ts | 20 +++++++++++ addon/ng2/utilities/ng-module-utils.ts | 35 +++++++++++++++++++ tests/e2e/e2e_workflow.spec.js | 5 +-- 15 files changed, 213 insertions(+), 78 deletions(-) create mode 100644 addon/ng2/blueprints/mobile/files/__path__/app-shell-module.ts create mode 100644 addon/ng2/blueprints/ng2/files/__path__/app/app.module.ts create mode 100644 addon/ng2/utilities/ng-module-utils.ts diff --git a/addon/ng2/blueprints/component/index.js b/addon/ng2/blueprints/component/index.js index 51c1b030fc1e..5bc91161b979 100644 --- a/addon/ng2/blueprints/component/index.js +++ b/addon/ng2/blueprints/component/index.js @@ -4,7 +4,8 @@ var Blueprint = require('ember-cli/lib/models/blueprint'); var dynamicPathParser = require('../../utilities/dynamic-path-parser'); var addBarrelRegistration = require('../../utilities/barrel-management'); var getFiles = Blueprint.prototype.files; -const stringUtils = require('ember-cli-string-utils'); +var stringUtils = require('ember-cli-string-utils'); +const ngModuleUtils = require('../../utilities/ng-module-utils'); module.exports = { description: '', @@ -115,17 +116,26 @@ module.exports = { }, afterInstall: function(options) { + const _this = this; + if (options.dryRun) { return; } - if (!options.flat) { - return addBarrelRegistration(this, this.generatePath); - } else { - return addBarrelRegistration( - this, - this.generatePath, - options.entity.name + '.component'); + function addBarrels() { + if (!options.flat) { + return addBarrelRegistration(_this, _this.generatePath); + } else { + return addBarrelRegistration( + _this, + _this.generatePath, + options.entity.name + '.component'); + } } + + return Promise.all([ + addBarrels(), + ngModuleUtils.importIntoModule(options, _this.dynamicPath.appRoot, _this.project.root) + ]); } }; diff --git a/addon/ng2/blueprints/directive/index.js b/addon/ng2/blueprints/directive/index.js index d88faa6a0693..e670f41a0906 100644 --- a/addon/ng2/blueprints/directive/index.js +++ b/addon/ng2/blueprints/directive/index.js @@ -3,6 +3,7 @@ var Blueprint = require('ember-cli/lib/models/blueprint'); var dynamicPathParser = require('../../utilities/dynamic-path-parser'); var addBarrelRegistration = require('../../utilities/barrel-management'); var getFiles = Blueprint.prototype.files; +const ngModuleUtils = require('../../utilities/ng-module-utils'); module.exports = { description: '', @@ -52,15 +53,22 @@ module.exports = { }, afterInstall: function(options) { - if (!options.flat) { - return addBarrelRegistration( - this, - this.generatePath); - } else { - return addBarrelRegistration( - this, - this.generatePath, - options.entity.name + '.directive'); + const _this = this; + + function addBarrels() { + if (!options.flat) { + return addBarrelRegistration(_this, _this.generatePath); + } else { + return addBarrelRegistration( + _this, + _this.generatePath, + options.entity.name + '.directive'); + } } + + return Promise.all([ + addBarrels(), + ngModuleUtils.importIntoModule(options, _this.dynamicPath.appRoot, _this.project.root) + ]); } }; diff --git a/addon/ng2/blueprints/interface/index.js b/addon/ng2/blueprints/interface/index.js index 0ed4979ed602..7412f631dd25 100644 --- a/addon/ng2/blueprints/interface/index.js +++ b/addon/ng2/blueprints/interface/index.js @@ -1,6 +1,7 @@ const stringUtils = require('ember-cli-string-utils'); var dynamicPathParser = require('../../utilities/dynamic-path-parser'); var addBarrelRegistration = require('../../utilities/barrel-management'); +const ngModuleUtils = require('../../utilities/ng-module-utils'); module.exports = { description: '', @@ -50,9 +51,16 @@ module.exports = { }, afterInstall: function() { - return addBarrelRegistration( - this, - this.generatePath, - this.fileName); + function addBarrels() { + return addBarrelRegistration( + this, + this.generatePath, + this.fileName); + } + + return Promise.all([ + addBarrels(), + ngModuleUtils.importIntoModule(options, _this.dynamicPath.appRoot, _this.project.root) + ]); } }; diff --git a/addon/ng2/blueprints/mobile/files/__path__/app-shell-module.ts b/addon/ng2/blueprints/mobile/files/__path__/app-shell-module.ts new file mode 100644 index 000000000000..aa022ff3ddbe --- /dev/null +++ b/addon/ng2/blueprints/mobile/files/__path__/app-shell-module.ts @@ -0,0 +1,19 @@ +import { NgModule, ModuleWithProviders } from '@angular/core'; +import { + APP_SHELL_DIRECTIVES, + APP_SHELL_RUNTIME_PROVIDERS, + APP_SHELL_BUILD_PROVIDERS +} from '@angular/app-shell'; + +@NgModule({ + declarations: APP_SHELL_DIRECTIVES, + exports: APP_SHELL_DIRECTIVES +}) +export class AppShellModule { + static forRoot(): ModuleWithProviders { + return { + ngModule: AppShellModule, + providers: [APP_SHELL_RUNTIME_PROVIDERS, APP_SHELL_BUILD_PROVIDERS] + }; + } +} diff --git a/addon/ng2/blueprints/mobile/files/__path__/main-app-shell.ts b/addon/ng2/blueprints/mobile/files/__path__/main-app-shell.ts index d3e009cb19c5..11ebf4d6ca23 100644 --- a/addon/ng2/blueprints/mobile/files/__path__/main-app-shell.ts +++ b/addon/ng2/blueprints/mobile/files/__path__/main-app-shell.ts @@ -2,12 +2,12 @@ import 'angular2-universal-polyfills'; import { provide } from '@angular/core'; import { APP_BASE_HREF } from '@angular/common'; import { APP_SHELL_BUILD_PROVIDERS } from '@angular/app-shell'; -import { - REQUEST_URL, - ORIGIN_URL, - Bootloader, - BootloaderConfig, - AppConfig +import { + REQUEST_URL, + ORIGIN_URL, + Bootloader, + BootloaderConfig, + AppConfig } from 'angular2-universal'; import { AppComponent } from './app/'; @@ -21,7 +21,7 @@ const bootloaderConfig: BootloaderConfig = { ], async: true, preboot: false -} +}; const appConfig: AppConfig = { directives: [ @@ -32,16 +32,16 @@ const appConfig: AppConfig = { // What URL should Angular be treating the app as if navigating provide(REQUEST_URL, { useValue: '/' }) ] -} +}; // The build system will call this function to get a bootloader -export function getBootloader() : Bootloader { +export function getBootloader(): Bootloader { return new Bootloader(bootloaderConfig); } // The build system will call this function with the bootloader from // getBootloader and the contents of the index page -export function serialize(bootloader: Bootloader, template: string) : string { +export function serialize(bootloader: Bootloader, template: string): string { appConfig.template = template; return bootloader.serializeApplication(appConfig); -} \ No newline at end of file +} diff --git a/addon/ng2/blueprints/ng2/files/__path__/app/app.component.spec.ts b/addon/ng2/blueprints/ng2/files/__path__/app/app.component.spec.ts index be843756c906..10c1d8ce67cd 100644 --- a/addon/ng2/blueprints/ng2/files/__path__/app/app.component.spec.ts +++ b/addon/ng2/blueprints/ng2/files/__path__/app/app.component.spec.ts @@ -1,20 +1,19 @@ -/* tslint:disable:no-unused-variable */ - -import { addProviders, async, inject } from '@angular/core/testing'; +import { TestBed, async } from '@angular/core/testing'; import { AppComponent } from './app.component'; -describe('App: <%= jsComponentName %>', () => { - beforeEach(() => { - addProviders([AppComponent]); - }); +describe('App: TestProject', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({ declarations: [AppComponent] }); + TestBed.compileComponents(); + })); - it('should create the app', - inject([AppComponent], (app: AppComponent) => { - expect(app).toBeTruthy(); - })); + it('should create the app', () => { + const compFixture = TestBed.createComponent(AppComponent); + expect(compFixture).toBeTruthy(); + }); - it('should have as title \'app works!\'', - inject([AppComponent], (app: AppComponent) => { - expect(app.title).toEqual('app works!'); - })); + it('should have a title `app works!`', () => { + const compFixture = TestBed.createComponent(AppComponent); + expect(compFixture.componentInstance.title).toBe('app works!'); + }); }); diff --git a/addon/ng2/blueprints/ng2/files/__path__/app/app.module.ts b/addon/ng2/blueprints/ng2/files/__path__/app/app.module.ts new file mode 100644 index 000000000000..c3839e65eda8 --- /dev/null +++ b/addon/ng2/blueprints/ng2/files/__path__/app/app.module.ts @@ -0,0 +1,24 @@ +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule, ApplicationRef } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { AppComponent } from './app.component'; +<% if (isMobile) { %> +import { AppShellModule } from '../app-shell-module'; +<% } %> + +@NgModule({ + declarations: [AppComponent], + imports: [ + BrowserModule, + CommonModule, + FormsModule<% if (isMobile) { %>, + AppShellModule<% } %> + ], + entryComponents: [AppComponent] +}) +export class AppModule { + constructor(appRef: ApplicationRef) { + appRef.bootstrap(AppComponent); + } +} diff --git a/addon/ng2/blueprints/ng2/files/__path__/app/index.ts b/addon/ng2/blueprints/ng2/files/__path__/app/index.ts index 7aa84b623989..87743c9d56ee 100644 --- a/addon/ng2/blueprints/ng2/files/__path__/app/index.ts +++ b/addon/ng2/blueprints/ng2/files/__path__/app/index.ts @@ -1,2 +1,3 @@ export * from './environments/environment'; export * from './app.component'; +export * from './app.module'; diff --git a/addon/ng2/blueprints/ng2/files/__path__/main.ts b/addon/ng2/blueprints/ng2/files/__path__/main.ts index 68e79759c3b4..4bdf15c04a38 100644 --- a/addon/ng2/blueprints/ng2/files/__path__/main.ts +++ b/addon/ng2/blueprints/ng2/files/__path__/main.ts @@ -1,10 +1,9 @@ -import { bootstrap } from '@angular/platform-browser-dynamic'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { enableProdMode } from '@angular/core'; -import { AppComponent, environment } from './app/';<% if(isMobile) { %> -import { APP_SHELL_RUNTIME_PROVIDERS } from '@angular/app-shell';<% } %> +import { AppModule, environment } from './app/'; if (environment.production) { enableProdMode(); } -bootstrap(AppComponent<% if(isMobile) { %>, [ APP_SHELL_RUNTIME_PROVIDERS ]<% } %>); +platformBrowserDynamic().bootstrapModule(AppModule); diff --git a/addon/ng2/blueprints/ng2/files/angular-cli.json b/addon/ng2/blueprints/ng2/files/angular-cli.json index 5b96ba0ba88c..73b3b12170cc 100644 --- a/addon/ng2/blueprints/ng2/files/angular-cli.json +++ b/addon/ng2/blueprints/ng2/files/angular-cli.json @@ -6,6 +6,7 @@ "apps": [ { "main": "<%= sourceDir %>/main.ts", + "appmodule": "app.module.ts", "tsconfig": "<%= sourceDir %>/tsconfig.json", "mobile": <%= isMobile %> } diff --git a/addon/ng2/blueprints/ng2/files/package.json b/addon/ng2/blueprints/ng2/files/package.json index 161087266c4c..e0eccab835d6 100644 --- a/addon/ng2/blueprints/ng2/files/package.json +++ b/addon/ng2/blueprints/ng2/files/package.json @@ -11,22 +11,7 @@ "e2e": "protractor" }, "private": true, - "dependencies": { - "@angular/common": "2.0.0-rc.4", - "@angular/compiler": "2.0.0-rc.4", - "@angular/core": "2.0.0-rc.4", - "@angular/forms": "0.2.0", - "@angular/http": "2.0.0-rc.4", - "@angular/platform-browser": "2.0.0-rc.4", - "@angular/platform-browser-dynamic": "2.0.0-rc.4", - "@angular/router": "3.0.0-beta.2", - "core-js": "^2.4.0", - "reflect-metadata": "0.1.3", - "rxjs": "5.0.0-beta.6", - "ts-helpers": "^1.1.1", - "zone.js": "0.6.12" - }, - "devDependencies": {<% if(isMobile) { %> + "dependencies": {<% if(isMobile) { %> "@angular/platform-server": "2.0.0-rc.4", "@angular/service-worker": "0.2.0", "@angular/app-shell": "0.0.0", @@ -34,6 +19,21 @@ "angular2-universal-polyfills": "0.4.1", "preboot": "2.1.2", "parse5": "1.5.1",<% } %> + "@angular/common": "github:angular/common-builds", + "@angular/compiler": "github:angular/compiler-builds", + "@angular/core": "github:angular/core-builds", + "@angular/forms": "github:angular/forms-builds", + "@angular/http": "github:angular/http-builds", + "@angular/platform-browser": "github:angular/platform-browser-builds", + "@angular/platform-browser-dynamic": "github:angular/platform-browser-dynamic-builds", + "@angular/router": "github:angular/router-builds", + "core-js": "^2.4.0", + "reflect-metadata": "0.1.3", + "rxjs": "5.0.0-beta.6", + "ts-helpers": "^1.1.1", + "zone.js": "0.6.12" + }, + "devDependencies": { "@types/jasmine": "^2.2.30", "@types/protractor": "^1.5.16", "angular-cli": "<%= version %>", diff --git a/addon/ng2/blueprints/pipe/index.js b/addon/ng2/blueprints/pipe/index.js index 6ea6ceff46ae..9514ef016dd8 100644 --- a/addon/ng2/blueprints/pipe/index.js +++ b/addon/ng2/blueprints/pipe/index.js @@ -3,6 +3,7 @@ var Blueprint = require('ember-cli/lib/models/blueprint'); var dynamicPathParser = require('../../utilities/dynamic-path-parser'); var addBarrelRegistration = require('../../utilities/barrel-management'); var getFiles = Blueprint.prototype.files; +const ngModuleUtils = require('../../utilities/ng-module-utils'); module.exports = { description: '', @@ -50,15 +51,24 @@ module.exports = { }, afterInstall: function(options) { - if (!options.flat) { - return addBarrelRegistration( - this, - this.generatePath); - } else { - return addBarrelRegistration( - this, - this.generatePath, - options.entity.name + '.pipe'); + const _this = this; + + function addBarrels() { + if (!options.flat) { + return addBarrelRegistration( + _this, + _this.generatePath); + } else { + return addBarrelRegistration( + _this, + _this.generatePath, + options.entity.name + '.pipe'); + } } + + return Promise.all([ + addBarrels(), + ngModuleUtils.importIntoModule(options, _this.dynamicPath.appRoot, _this.project.root) + ]); } }; diff --git a/addon/ng2/utilities/ast-utils.ts b/addon/ng2/utilities/ast-utils.ts index 7b9f1104f33f..88ef9ad9d73a 100644 --- a/addon/ng2/utilities/ast-utils.ts +++ b/addon/ng2/utilities/ast-utils.ts @@ -19,6 +19,26 @@ export function findNodes(node: ts.Node, kind: ts.SyntaxKind): ts.Node[] { foundNodes.concat(findNodes(child, kind)), arr); } +/** +* Find all nodes from the AST in the subtree of node based on text. +* @param node +* @param name +* @return all nodes of that match given name, or [] if none is found +*/ +export function findNodesByText(node: ts.Node, name: string): ts.Node[] { + if (!node) { + return []; + } + let nodes: ts.Node[] = []; + if (node.getText() === name) { + nodes.push(node); + } + + return node.getChildren().reduce((foundNodes, child) => { + return foundNodes.concat(findNodesByText(child, name)); + }, nodes); +} + /** * Helper for sorting nodes. * @return function to sort nodes in increasing order of position in sourceFile diff --git a/addon/ng2/utilities/ng-module-utils.ts b/addon/ng2/utilities/ng-module-utils.ts new file mode 100644 index 000000000000..33227fccf516 --- /dev/null +++ b/addon/ng2/utilities/ng-module-utils.ts @@ -0,0 +1,35 @@ +import * as ts from 'typescript'; +import * as fs from 'fs'; +import * as path from 'path'; +import * as stringUtils from 'ember-cli-string-utils'; +import { findNodes, findNodesByText } from './ast-utils' +import { InsertChange } from './change'; +import { CliConfig } from '../models/config'; + +const config: any = CliConfig.fromProject(); + +export function insertIntoDeclarations(moduleFilePath: string, insertItem: string): Promise { + let sourceFile: ts.SourceFile = ts.createSourceFile(moduleFilePath, + fs.readFileSync(moduleFilePath).toString(), + ts.ScriptTarget.ES6, true); + let endPosition: number = findNodesByText(sourceFile, 'declarations')[0].end; + let position: ts.LineAndCharacter = sourceFile.getLineAndCharacterOfPosition(endPosition); + let line: number = position.line; + let start: number = sourceFile.getPositionOfLineAndCharacter(line + 1, -3); + + return new InsertChange(moduleFilePath, start, `, ${insertItem}`).apply(); +} + +export function importIntoModule(options: any, directory: string, projectRoot: string): Promise { + if (!options['skip-import'] && config.apps[0].appmodule) { + const appModulePath = path.join(projectRoot, directory, + config.apps[0].appmodule); + + const classifiedModuleName = + stringUtils.classify(`${options.entity.name}-${options.originBlueprintName}`); + + return this.insertIntoDeclarations(appModulePath, classifiedModuleName); + } else { + return Promise.resolve(); + } +} diff --git a/tests/e2e/e2e_workflow.spec.js b/tests/e2e/e2e_workflow.spec.js index 1aaa5159f3b7..52470485b717 100644 --- a/tests/e2e/e2e_workflow.spec.js +++ b/tests/e2e/e2e_workflow.spec.js @@ -155,10 +155,11 @@ describe('Basic end-to-end Workflow', function () { expect(existsSync(path.join(process.cwd(), 'dist/app-concat.js'))).to.be.equal(false); }); - it('lints', () => { + it('lints', function () { this.timeout(420000); - return ng(['lint']).then(() => { + return ng(['lint']).then((result) => { + expect(typeof result === 'object' ? result.exitCode : result).to.be.equal(0); }) .catch(err => { throw new Error('Linting failed: ' + err);