diff --git a/.travis.yml b/.travis.yml index 8a9876e669c6..72305cb70144 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,11 @@ dist: trusty sudo: required env: - - NODE_VERSION=5 SCRIPT=lint - - NODE_VERSION=5 SCRIPT=test + global: + - DBUS_SESSION_BUS_ADDRESS=/dev/null + matrix: + - NODE_VERSION=5 SCRIPT=lint + - NODE_VERSION=5 SCRIPT=test os: - linux - osx diff --git a/CHANGELOG.md b/CHANGELOG.md index 9abc840911a6..4abf0e151d50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,35 +1,145 @@ -## Always follow the [upgrade guide](https://github.com/angular/angular-cli/blob/master/CHANGELOG.md#updating-angular-cli) when upgrading to a new version. The changelog does not list breaking changes that are fixed via the update procedure. +**Always follow the [update guide](https://github.com/angular/angular-cli/blob/master/README.md#updating-angular-cli) when updating to a new version. The changelog does not list breaking changes that are fixed via the update procedure.** - -# 1.0.0-beta.6 (2016-06-13) +--- + + +# 1.0.0-beta.7 (2016-06-23) + + +### Bug Fixes + +* **deps:** update router (#1121) ([b90a110](https://github.com/angular/angular-cli/commit/b90a110)) +* **e2e:** prevent chrome race condition (#1141) ([9df0ffe](https://github.com/angular/angular-cli/commit/9df0ffe)) +* **init:** don't replace live reload script on diffs (#1128) ([e97fd9f](https://github.com/angular/angular-cli/commit/e97fd9f)), closes [#1122](https://github.com/angular/angular-cli/issues/1122) +* **lint:** add missing rulesDirectory (#1108) ([1690a82](https://github.com/angular/angular-cli/commit/1690a82)), closes [#1094](https://github.com/angular/angular-cli/issues/1094) +* **mobile:** partially fix dep problem (#1151) ([4b638c8](https://github.com/angular/angular-cli/commit/4b638c8)), closes [(#1151](https://github.com/(/issues/1151) ### Features -- Admin elevation no longer required on Windows (https://github.com/angular/angular-cli/pull/905). -- Automatically add SASS/Stylus if project is initialized with `--style={sass|scss|styl}` (https://github.com/angular/angular-cli/pull/998). -- Allow any number of env files (https://github.com/angular/angular-cli/pull/913). + +* add file system utilities for 'upgrade' process ([327f649](https://github.com/angular/angular-cli/commit/327f649)) + + + + +# 1.0.0-beta.6 (2016-06-15) + ### Bug Fixes -- Fix adding 3rd party libs without package format (https://github.com/angular/angular-cli/pull/1028/commits/065e98f40384f8b28dcaf84028c411043697ff11). -- Fix github deploy deep links (https://github.com/angular/angular-cli/pull/1020). -- Fix `ng e2e` exit code (https://github.com/angular/angular-cli/pull/1025). -- Fix missing vendor file (https://github.com/angular/angular-cli/pull/972). -- Fix github user pages base href (https://github.com/angular/angular-cli/pull/965). + +* **admin:** added support for non Administrator CLI user ([0bc3d94](https://github.com/angular/angular-cli/commit/0bc3d94)), closes [#905](https://github.com/angular/angular-cli/issues/905) [#886](https://github.com/angular/angular-cli/issues/886) [#370](https://github.com/angular/angular-cli/issues/370) +* **barrel:** alphabetized barrel exports ([67b577d](https://github.com/angular/angular-cli/commit/67b577d)), closes [#582](https://github.com/angular/angular-cli/issues/582) +* **deploy:** Fix base href for user pages (#965) ([424cff2](https://github.com/angular/angular-cli/commit/424cff2)), closes [(#965](https://github.com/(/issues/965) +* **e2e:** return exit codes on failure of e2e tests ([d0c07ac](https://github.com/angular/angular-cli/commit/d0c07ac)), closes [#1017](https://github.com/angular/angular-cli/issues/1017) [#1025](https://github.com/angular/angular-cli/issues/1025) [#1044](https://github.com/angular/angular-cli/issues/1044) +* **generator:** --dry-run no longer modifies files ([6efc8ee](https://github.com/angular/angular-cli/commit/6efc8ee)) +* Persist style extension config at project creation. ([85c9aec](https://github.com/angular/angular-cli/commit/85c9aec)), closes [#780](https://github.com/angular/angular-cli/issues/780) +* skips git-init if working folder is inside a git repo ([52c0cfb](https://github.com/angular/angular-cli/commit/52c0cfb)), closes [#802](https://github.com/angular/angular-cli/issues/802) +* **gh-deploy:** fix deep links (#1020) ([f8f8179](https://github.com/angular/angular-cli/commit/f8f8179)), closes [(#1020](https://github.com/(/issues/1020) [#995](https://github.com/angular/angular-cli/issues/995) +* **mobile:** add missing vendor file to build (#972) ([9a7bfe0](https://github.com/angular/angular-cli/commit/9a7bfe0)), closes [#847](https://github.com/angular/angular-cli/issues/847) +* **mobile:** lock dependency (#961) ([740805b](https://github.com/angular/angular-cli/commit/740805b)), closes [#958](https://github.com/angular/angular-cli/issues/958) +* **sourcemaps:** try to improve the source maps by fixing the path (#1028) ([5f909aa](https://github.com/angular/angular-cli/commit/5f909aa)) +* **template:** Update pipe template to include Pipe in name ([c92f330](https://github.com/angular/angular-cli/commit/c92f330)), closes [#869](https://github.com/angular/angular-cli/issues/869) + +### Features + +* allow lazy route prefix to be configurable ([c3fd9c7](https://github.com/angular/angular-cli/commit/c3fd9c7)), closes [#842](https://github.com/angular/angular-cli/issues/842) +* **router:** upgrade the router version ([eb9b80e](https://github.com/angular/angular-cli/commit/eb9b80e)) +* **style:** automatically add dependencies if style is set on new projects ([01e31ab](https://github.com/angular/angular-cli/commit/01e31ab)), closes [#986](https://github.com/angular/angular-cli/issues/986) +* **test:** run e2e of generated project (#490) ([d0dbd70](https://github.com/angular/angular-cli/commit/d0dbd70)) + ### BREAKING CHANGES -- `AppComponent` is now simply `AppComponent`, and it's selector is now `app-root` (https://github.com/angular/angular-cli/pull/1042). -- Route generation is temporarily disabled while we move to the [recently announce router](http://angularjs.blogspot.ie/2016/06/improvements-coming-for-routing-in.html)(https://github.com/angular/angular-cli/pull/992). It is recommended that users manually move to this router in all new projects. +* The router has been updated to the newest version, usage of the deprecated router and the original release candidate routers are no longer supported + +* `AppComponent` is now simply `AppComponent`, and it's selector is now `app-root` (https://github.com/angular/angular-cli/pull/1042). + +* Route generation is temporarily disabled while we move to the [recently announce router](http://angularjs.blogspot.ie/2016/06/improvements-coming-for-routing-in.html)(https://github.com/angular/angular-cli/pull/992). It is recommended that users manually move to this router in all new projects. + + # 1.0.0-beta.5 (2016-05-19) -### Known Issues -- `ng new -mobile` fails npm install (https://github.com/angular/angular-cli/issues/958). -- Adding 3rd party libs without SystemJS package format breaks prod mode (https://github.com/angular/angular-cli/issues/951). -- Deep links do not work on Github pages deploys (https://github.com/angular/angular-cli/issues/995). -- `ng e2e` doesn't return error exit code on test failures (https://github.com/angular/angular-cli/issues/1017). -- `ng build -prod` fails on mobile projects due to missing vendor file (https://github.com/angular/angular-cli/issues/847). -- Github deploy to user pages doesn't use correct base href (https://github.com/angular/angular-cli/pull/965). -- `ng test` on windows hits the file discriptor limit (https://github.com/angular/angular-cli/issues/977). -- `ng serve/build/test` need admin elevation on Windows (https://github.com/angular/angular-cli/issues/641). \ No newline at end of file +### Bug Fixes + +* **build:** fix broken sourcemaps (#839) ([234de2b](https://github.com/angular/angular-cli/commit/234de2b)), closes [(#839](https://github.com/(/issues/839) + +### Features + +* **blueprint:** add blueprint for generating interfaces (#757) ([482aa74](https://github.com/angular/angular-cli/commit/482aa74)), closes [#729](https://github.com/angular/angular-cli/issues/729) +* **test:** use link-cli option on e2e (#841) ([85d1400](https://github.com/angular/angular-cli/commit/85d1400)) + +### Performance Improvements + +* **ng new:** command to link to `angular-cli` (#778) ([9b8334f](https://github.com/angular/angular-cli/commit/9b8334f)) + + + + +# 1.0.0-beta.4 (2016-05-18) + + +### Bug Fixes + +* **build:** fix infinite loop on ng serve (#775) ([285db13](https://github.com/angular/angular-cli/commit/285db13)), closes [(#775](https://github.com/(/issues/775) +* **deploy:** fix file copy, index tag rewrite (#772) ([a34aca8](https://github.com/angular/angular-cli/commit/a34aca8)), closes [(#772](https://github.com/(/issues/772) +* **index:** fix live reload file path (#774) ([be718cb](https://github.com/angular/angular-cli/commit/be718cb)), closes [(#774](https://github.com/(/issues/774) +* **mobile:** don't import system-config in system-import.js (#794) ([7ab7d72](https://github.com/angular/angular-cli/commit/7ab7d72)) +* **mobile:** make app-shell compilation synchronous ([9ed28ba](https://github.com/angular/angular-cli/commit/9ed28ba)) +* **mobile:** prevent already-bundled JS from getting cached by Service Worker ([9d18f74](https://github.com/angular/angular-cli/commit/9d18f74)) + +### Features + +* **mobile:** add app shell to mobile blueprint (#809) ([e7d7ed8](https://github.com/angular/angular-cli/commit/e7d7ed8)) +* **SASSPlugin:** Allow regexes to be passed to include/exclude certain file patterns ([6b45099](https://github.com/angular/angular-cli/commit/6b45099)), closes [#558](https://github.com/angular/angular-cli/issues/558) + + + + +# 1.0.0-beta.2-mobile.3 (2016-05-13) + + +### Bug Fixes + +* **broccoli-typescript:** properly parse compilerOptions (#764) ([bbf1bc8](https://github.com/angular/angular-cli/commit/bbf1bc8)) +* **mobile:** include vendor scripts in bundle ([679d0e6](https://github.com/angular/angular-cli/commit/679d0e6)), closes [#733](https://github.com/angular/angular-cli/issues/733) +* **mobile:** remove mobile-specific dependencies from root package ([263e23b](https://github.com/angular/angular-cli/commit/263e23b)) +* **mobile:** update path to reflect updated service worker package (#746) ([818fb19](https://github.com/angular/angular-cli/commit/818fb19)) +* **package:** temporarily remove angular2-service-worker ([7f86ab3](https://github.com/angular/angular-cli/commit/7f86ab3)) + +### Features + +* **blueprints:** add enum blueprint. ([eddb354](https://github.com/angular/angular-cli/commit/eddb354)), closes [#707](https://github.com/angular/angular-cli/issues/707) + + + + +# 1.0.0-beta.2-mobile (2016-05-12) + + +### Bug Fixes + +* package.json use sourceDir for new command ([8dcd996](https://github.com/angular/angular-cli/commit/8dcd996)) +* use options sourceDir, and fix null property access. Also use 1.9 ([7ba388d](https://github.com/angular/angular-cli/commit/7ba388d)), closes [#619](https://github.com/angular/angular-cli/issues/619) +* **710:** Missing http module dependency ([c0aadae](https://github.com/angular/angular-cli/commit/c0aadae)) +* **commands:** fix outdated string utils import. ([7db40df](https://github.com/angular/angular-cli/commit/7db40df)) + +### Features + +* **mobile:** add blueprint for app manifest and icons ([f717bde](https://github.com/angular/angular-cli/commit/f717bde)) +* **mobile:** add prod build step to concatenate scripts ([51569ce](https://github.com/angular/angular-cli/commit/51569ce)) +* **mobile:** add ServiceWorker generation to build process and index ([04593eb](https://github.com/angular/angular-cli/commit/04593eb)) +* **mobile:** add support for generating App Shell in index.html ([cb1270f](https://github.com/angular/angular-cli/commit/cb1270f)) +* **ng2 blueprint:** add test script entry to package.json ([eabc160](https://github.com/angular/angular-cli/commit/eabc160)) + + + + +# 1.0.0-beta.1 (2016-05-07) + + +### Bug Fixes + +* **generated-project:** cli was not using the correct version of CLI in generated project. (#672) ([02073ae](https://github.com/angular/angular-cli/commit/02073ae)) + diff --git a/README.md b/README.md index 7fb9e7f58cb6..2deb864fa7b2 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,9 @@ If you wish to collaborate while the project is still young, check out [our issu ## Prerequisites -The generated project has dependencies that require **Node 4 or greater**. +The generated project has dependencies that require +* **Node 4 or greater**. +* **Typings v1 or greater**. ## Table of Contents @@ -29,6 +31,7 @@ The generated project has dependencies that require **Node 4 or greater**. * [Generating a Route](#generating-a-route) * [Creating a Build](#creating-a-build) * [Environments](#environments) +* [Bundling](#bundling) * [Running Unit Tests](#running-unit-tests) * [Running End-to-End Tests](#running-end-to-end-tests) * [Deploying the App via GitHub Pages](#deploying-the-app-via-github-pages) @@ -129,16 +132,21 @@ The build artifacts will be stored in the `dist/` directory. ### Environments -At build time, the `src/client/app/environment.ts` will be replaced by either +At build time, the `src/app/environment.ts` will be replaced by either `config/environment.dev.ts` or `config/environment.prod.ts`, depending on the -current cli environment. +current cli environment. The resulting file will be `dist/app/environment.ts`. Environment defaults to `dev`, but you can generate a production build via the `-prod` flag in either `ng build -prod` or `ng serve -prod`. -You can also add your own env files other than `dev` and `prod` by creating a -`src/client/app/environment.{NAME}.ts` and use them by using the `--env=NAME` -flag on the build/serve commands. +You can also add your own env files other than `dev` and `prod` by creating a +`config/environment.{NAME}.ts` and use them by using the `--env=NAME` +flag on the build/serve commands. + +### Bundling + +Builds created with the `-prod` flag via `ng build -prod` or `ng serve -prod` bundle +all dependencies into a single file, and make use of tree-shaking techniques. ### Running unit tests @@ -206,7 +214,7 @@ You can modify the these scripts in `package.json` to run whatever tool you pref ### Support for offline applications -The index.html file includes a commented-out code snippet for installing the angular2-service-worker. This support is experimental, please see the angular/mobile-toolkit project for documentation on how to make use of this functionality. +The index.html file includes a commented-out code snippet for installing the angular2-service-worker. This support is experimental, please see the angular/mobile-toolkit project and https://mobile.angular.io/ for documentation on how to make use of this functionality. ### Commands autocompletion diff --git a/addon/ng2/blueprints/ng2/files/__path__/system-config.ts b/addon/ng2/blueprints/ng2/files/__path__/system-config.ts index 36e6f9403836..55e4ac712886 100644 --- a/addon/ng2/blueprints/ng2/files/__path__/system-config.ts +++ b/addon/ng2/blueprints/ng2/files/__path__/system-config.ts @@ -22,6 +22,7 @@ const barrels: string[] = [ '@angular/core', '@angular/common', '@angular/compiler', + '@angular/forms', '@angular/http', '@angular/router', '@angular/platform-browser', diff --git a/addon/ng2/blueprints/ng2/files/package.json b/addon/ng2/blueprints/ng2/files/package.json index a0bc9b676b58..723bdbc12380 100644 --- a/addon/ng2/blueprints/ng2/files/package.json +++ b/addon/ng2/blueprints/ng2/files/package.json @@ -13,13 +13,14 @@ }, "private": true, "dependencies": { - "@angular/common": "2.0.0-rc.1", - "@angular/compiler": "2.0.0-rc.1", - "@angular/core": "2.0.0-rc.1", - "@angular/http": "2.0.0-rc.1", - "@angular/platform-browser": "2.0.0-rc.1", - "@angular/platform-browser-dynamic": "2.0.0-rc.1", - "@angular/router": "3.0.0-alpha.3", + "@angular/common": "2.0.0-rc.3", + "@angular/compiler": "2.0.0-rc.3", + "@angular/core": "2.0.0-rc.3", + "@angular/forms": "0.2.0", + "@angular/http": "2.0.0-rc.3", + "@angular/platform-browser": "2.0.0-rc.3", + "@angular/platform-browser-dynamic": "2.0.0-rc.3", + "@angular/router": "3.0.0-alpha.8", "es6-shim": "0.35.1", "reflect-metadata": "0.1.3", "rxjs": "5.0.0-beta.6", @@ -27,12 +28,11 @@ "zone.js": "0.6.12" }, "devDependencies": {<% if(isMobile) { %> - "@angular/platform-server": "2.0.0-rc.1", - "@angular/router-deprecated": "2.0.0-rc.1", + "@angular/platform-server": "2.0.0-rc.3", "@angular/service-worker": "0.2.0", "@angular/app-shell": "0.0.0", "angular2-broccoli-prerender": "0.11.0", - "angular2-universal":"0.101.5", + "angular2-universal":"0.100.5", "angular2-universal-polyfills": "0.4.1", "preboot": "2.0.10",<% } %> "angular-cli": "<%= version %>", diff --git a/addon/ng2/blueprints/ng2/files/tslint.json b/addon/ng2/blueprints/ng2/files/tslint.json index 490c4bd51da5..7b13bd1790a4 100644 --- a/addon/ng2/blueprints/ng2/files/tslint.json +++ b/addon/ng2/blueprints/ng2/files/tslint.json @@ -1,4 +1,7 @@ { + "rulesDirectory": [ + "node_modules/codelyzer" + ], "rules": { "class-name": true, "comment-format": [ diff --git a/addon/ng2/commands/init.js b/addon/ng2/commands/init.js index f77a1c2852b7..7c7fff8aa460 100644 --- a/addon/ng2/commands/init.js +++ b/addon/ng2/commands/init.js @@ -7,6 +7,7 @@ var validProjectName = require('ember-cli/lib/utilities/valid-project-name'); var normalizeBlueprint = require('ember-cli/lib/utilities/normalize-blueprint-option'); var GitInit = require('../tasks/git-init'); var LinkCli = require('../tasks/link-cli'); +var NpmInstall = require('../tasks/npm-install'); module.exports = Command.extend({ name: 'init', @@ -68,7 +69,7 @@ module.exports = Command.extend({ } if (!commandOptions.skipNpm) { - var npmInstall = new this.tasks.NpmInstall({ + var npmInstall = new NpmInstall({ ui: this.ui, analytics: this.analytics, project: this.project diff --git a/addon/ng2/tasks/npm-install.js b/addon/ng2/tasks/npm-install.js new file mode 100644 index 000000000000..40fa58af9cbe --- /dev/null +++ b/addon/ng2/tasks/npm-install.js @@ -0,0 +1,11 @@ +'use strict'; + +// Runs `npm install` in cwd + +var NpmTask = require('./npm-task'); + +module.exports = NpmTask.extend({ + command: 'install', + startProgressMessage: 'Installing packages for tooling via npm', + completionMessage: 'Installed packages for tooling via npm.' +}); diff --git a/addon/ng2/tasks/npm-task.js b/addon/ng2/tasks/npm-task.js new file mode 100644 index 000000000000..4f720da73175 --- /dev/null +++ b/addon/ng2/tasks/npm-task.js @@ -0,0 +1,64 @@ +/*eslint-disable no-console */ +'use strict'; + +// Runs `npm install` in cwd + +var chalk = require('chalk'); +var Task = require('ember-cli/lib/models/task'); +var npm = require('../utilities/npm'); + +module.exports = Task.extend({ + // The command to run: can be 'install' or 'uninstall' + command: '', + // Message to send to ui.startProgress + startProgressMessage: '', + // Message to send to ui.writeLine on completion + completionMessage: '', + + init: function() { + this.npm = this.npm || require('npm'); + }, + // Options: Boolean verbose + run: function(options) { + this.ui.startProgress(chalk.green(this.startProgressMessage), chalk.green('.')); + + var npmOptions = { + loglevel: options.verbose ? 'verbose' : 'error', + progress: false, + logstream: this.ui.outputStream, + color: 'always', + // by default, do install peoples optional deps + 'optional': 'optional' in options ? options.optional : true, + 'save-dev': !!options['save-dev'], + 'save-exact': !!options['save-exact'] + }; + + var packages = options.packages || []; + + // npm otherwise is otherwise noisy, already submitted PR for npm to fix + // misplaced console.log + this.disableLogger(); + + return npm(this.command, packages, npmOptions, this.npm). + finally(this.finally.bind(this)). + then(this.announceCompletion.bind(this)); + }, + + announceCompletion: function() { + this.ui.writeLine(chalk.green(this.completionMessage)); + }, + + finally: function() { + this.ui.stopProgress(); + this.restoreLogger(); + }, + + disableLogger: function() { + this.oldLog = console.log; + console.log = function() {}; + }, + + restoreLogger: function() { + console.log = this.oldLog; // Hack, see above + } +}); diff --git a/addon/ng2/utilities/change.ts b/addon/ng2/utilities/change.ts new file mode 100644 index 000000000000..4e6191952875 --- /dev/null +++ b/addon/ng2/utilities/change.ts @@ -0,0 +1,114 @@ +'use strict'; + +import * as Promise from 'ember-cli/lib/ext/promise'; +import fs = require('fs'); + +const readFile = Promise.denodeify(fs.readFile); +const writeFile = Promise.denodeify(fs.writeFile); + +export interface Change { + + apply(): Promise; + + // The file this change should be applied to. Some changes might not apply to + // a file (maybe the config). + path: string | null; + + // The order this change should be applied. Normally the position inside the file. + // Changes are applied from the bottom of a file to the top. + order: number; + + // The description of this change. This will be outputted in a dry or verbose run. + description: string; +} + +/** + * Will add text to the source code. + */ +export class InsertChange implements Change { + + const order: number; + const description: string; + + constructor( + public path: string, + private pos: number, + private toAdd: string, + ) { + if (pos < 0) { + throw new Error('Negative positions are invalid'); + } + this.description = `Inserted ${toAdd} into position ${pos} of ${path}`; + this.order = pos; + } + + /** + * This method does not insert spaces if there is none in the original string. + */ + apply(): Promise { + return readFile(this.path, 'utf8').then(content => { + let prefix = content.substring(0, this.pos); + let suffix = content.substring(this.pos); + return writeFile(this.path, `${prefix}${this.toAdd}${suffix}`); + }); + } +} + +/** + * Will remove text from the source code. + */ +export class RemoveChange implements Change { + + const order: number; + const description: string; + + constructor( + public path: string, + private pos: number, + private toRemove: string) { + if (pos < 0) { + throw new Error('Negative positions are invalid'); + } + this.description = `Removed ${toRemove} into position ${pos} of ${path}`; + this.order = pos; + } + + apply(): Promise { + return readFile(this.path, 'utf8').then(content => { + let prefix = content.substring(0, this.pos); + let suffix = content.substring(this.pos + this.toRemove.length); + // TODO: throw error if toRemove doesn't match removed string. + return writeFile(this.path, `${prefix}${suffix}`); + }); + } +} + +/** + * Will replace text from the source code. + */ +export class ReplaceChange implements Change { + + const order: number; + const description: string; + + constructor( + public path: string, + private pos: number, + private oldText: string, + private newText: string) { + if (pos < 0) { + throw new Error('Negative positions are invalid'); + } + this.description = `Replaced ${oldText} into position ${pos} of ${path} with ${newText}`; + this.order = pos; + } + + apply(): Promise { + return readFile(this.path, 'utf8').then(content => { + let prefix = content.substring(0, this.pos); + let suffix = content.substring(this.pos + this.oldText.length); + // TODO: throw error if oldText doesn't match removed string. + return writeFile(this.path, `${prefix}${this.newText}${suffix}`); + }); + } +} diff --git a/addon/ng2/utilities/npm.js b/addon/ng2/utilities/npm.js new file mode 100644 index 000000000000..fd88e14538d1 --- /dev/null +++ b/addon/ng2/utilities/npm.js @@ -0,0 +1,38 @@ +'use strict'; + +var Promise = require('ember-cli/lib/ext/promise'); + +// + +/** + Runs the npm command `command` with the supplied args and load options. + + Please note that the loaded module appears to retain some state, so do not + expect multiple invocations within the same process to work without quirks. + This problem is likely fixable. + + @method npm + @param {String} command The npm command to run. + @param {Array} npmArgs The arguments passed to the npm command. + @param {Array} options The options passed when loading npm. + @param {Module} [npm] A reference to the npm module. +*/ +module.exports = function npm(command, npmArgs, options/*, npm*/) { + var lib; + if (arguments.length === 4) { + lib = arguments[3]; + } else { + lib = require('npm'); + } + + var load = Promise.denodeify(lib.load); + + return load(options) + .then(function() { + // if install is denodeified outside load.then(), + // it throws "Call npm.load(config, cb) before using this command." + var operation = Promise.denodeify(lib.commands[command]); + + return operation(npmArgs || []); + }); +}; diff --git a/lib/broccoli/angular-broccoli-sass.js b/lib/broccoli/angular-broccoli-sass.js index 9d0f5e35b82e..aca7d93aac20 100644 --- a/lib/broccoli/angular-broccoli-sass.js +++ b/lib/broccoli/angular-broccoli-sass.js @@ -26,10 +26,13 @@ class SASSPlugin extends Plugin { build() { this.listFiles().forEach(fileName => { - // Normalize is necessary for changing `\`s into `/`s on windows. - this.compile(path.normalize(fileName), - path.normalize(this.inputPaths[0]), - path.normalize(this.outputPath)); + // We skip compiling partials (_*.scss files) + if(!/^_+.*.s[ac]ss$/.test(path.basename(fileName))) { + // Normalize is necessary for changing `\`s into `/`s on windows. + this.compile(path.normalize(fileName), + path.normalize(this.inputPaths[0]), + path.normalize(this.outputPath)); + } }); } diff --git a/lib/broccoli/angular2-app.js b/lib/broccoli/angular2-app.js index 06d94fae2e48..1d2879b5296e 100644 --- a/lib/broccoli/angular2-app.js +++ b/lib/broccoli/angular2-app.js @@ -53,6 +53,14 @@ class Angular2App extends BroccoliPlugin { this._tree = this._buildTree(); } + /** + * For compatibility with Ember addons + * @returns {*|{}} + */ + get options(){ + return this._options; + } + /** * For backward compatibility. * @public diff --git a/lib/cli/index.js b/lib/cli/index.js index ec87c3dbec98..bcf0fdd2c3c5 100644 --- a/lib/cli/index.js +++ b/lib/cli/index.js @@ -74,6 +74,10 @@ module.exports = function(options) { if (line.match(/version:|WARNING:/)) { return; } + if (line.match(/ember-cli-(inject-)?live-reload/)) { + // don't replace 'ember-cli-live-reload' on ng init diffs + return oldStdoutWrite.apply(process.stdout, arguments); + } line = line.replace(/ember-cli(?!.com)/g, 'angular-cli') .replace(/ember(?!-cli.com)/g, 'ng'); return oldStdoutWrite.apply(process.stdout, arguments); diff --git a/package.json b/package.json index da14efca3de7..3aa0fb95d0da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "angular-cli", - "version": "1.0.0-beta.6", + "version": "1.0.0-beta.9", "description": "CLI tool for Angular", "main": "lib/cli/index.js", "trackingCode": "UA-8594346-19", @@ -47,6 +47,7 @@ "handlebars": "^4.0.5", "leek": "0.0.21", "lodash": "^4.11.1", + "npm": "3.10.2", "opn": "4.0.1", "resolve": "^1.1.7", "shelljs": "^0.7.0", @@ -63,6 +64,7 @@ }, "devDependencies": { "chai": "^3.5.0", + "conventional-changelog": "^1.1.0", "eslint": "^2.8.0", "exists-sync": "0.0.3", "minimatch": "^3.0.0", @@ -72,8 +74,8 @@ "rewire": "^2.5.1", "sinon": "^1.17.3", "through": "^2.3.8", - "tslint": "^3.8.1", "tree-kill": "^1.0.0", + "tslint": "^3.8.1", "walk-sync": "^0.2.6" } } diff --git a/scripts/publish/changelog.js b/scripts/publish/changelog.js new file mode 100755 index 000000000000..9064ee0ef0a9 --- /dev/null +++ b/scripts/publish/changelog.js @@ -0,0 +1,41 @@ +#!/usr/bin/env node +'use strict'; + +/** + * Just a small command-line wrapper around the conventional-changelog npm module + * (https://www.npmjs.com/package/conventional-changelog), which also prepends + * changes to CHANGELOG.md. + * + * Appends CHANGELOG.md with the changes between tag and HEAD. + * NOTE: only `fix`, `feat`, `perf` and `revert` commits are used + * see: https://github.com/conventional-changelog/conventional-changelog/blob/v0.2.1/presets/angular.js#L24 + */ + +var fs = require('fs'); +var cl = require('conventional-changelog'); +const exec = require('child_process').exec; + +var changelogStream = fs.createWriteStream('CHANGELOG-delta.md'); + +if (process.argv.length < 3) { + console.log('Usage: ./scripts/publish/changelog.js '); + process.exit(-1); +} + +var config = { + preset: 'angular', + releaseCount: 1, +}; + +var prependDelta = function() { + exec('cat CHANGELOG-delta.md CHANGELOG.md > CHANGELOG-new.md;' + + 'mv CHANGELOG-new.md CHANGELOG.md;' + + 'rm CHANGELOG-delta.md'); +} + +cl(config, null, { from: process.argv[2] }) + .on('error', function(err) { + console.error('Failed to generate changelog: ' + err); + }) + .pipe(changelogStream) + .on('close', prependDelta); diff --git a/tests/acceptance/change.spec.ts b/tests/acceptance/change.spec.ts new file mode 100644 index 000000000000..aaed20037394 --- /dev/null +++ b/tests/acceptance/change.spec.ts @@ -0,0 +1,120 @@ +'use strict'; + +// This needs to be first so fs module can be mocked correctly. +let mockFs = require('mock-fs'); + +import {expect} from 'chai'; +import {InsertChange, RemoveChange, ReplaceChange} from '../../addon/ng2/utilities/change'; +import fs = require('fs'); + +let path = require('path'); +let Promise = require('ember-cli/lib/ext/promise'); + +const readFile = Promise.denodeify(fs.readFile); + +describe('Change', () => { + let sourcePath = 'src/app/my-component'; + + beforeEach(() => { + let mockDrive = { + 'src/app/my-component': { + 'add-file.txt': 'hello', + 'remove-replace-file.txt': 'import * as foo from "./bar"', + 'replace-file.txt': 'import { FooComponent } from "./baz"' + } + }; + mockFs(mockDrive); + }); + afterEach(() => { + mockFs.restore(); + }); + + describe('InsertChange', () => { + let sourceFile = path.join(sourcePath, 'add-file.txt'); + + it('adds text to the source code', () => { + let changeInstance = new InsertChange(sourceFile, 6, ' world!'); + return changeInstance + .apply() + .then(() => readFile(sourceFile, 'utf8')) + .then(contents => { + expect(contents).to.equal('hello world!'); + }); + }); + it('fails for negative position', () => { + expect(() => new InsertChange(sourceFile, -6, ' world!')).to.throw(Error); + }); + it('adds nothing in the source code if empty string is inserted', () => { + let changeInstance = new InsertChange(sourceFile, 6, ''); + return changeInstance + .apply() + .then(() => readFile(sourceFile, 'utf8')) + .then(contents => { + expect(contents).to.equal('hello'); + }); + }); + }); + + describe('RemoveChange', () => { + let sourceFile = path.join(sourcePath, 'remove-replace-file.txt'); + + it('removes given text from the source code', () => { + let changeInstance = new RemoveChange(sourceFile, 9, 'as foo'); + return changeInstance + .apply() + .then(() => readFile(sourceFile, 'utf8')) + .then(contents => { + expect(contents).to.equal('import * from "./bar"'); + }); + }); + it('fails for negative position', () => { + expect(() => new RemoveChange(sourceFile, -6, ' world!')).to.throw(Error); + }); + it('does not change the file if told to remove empty string', () => { + let changeInstance = new RemoveChange(sourceFile, 9, ''); + return changeInstance + .apply() + .then(() => readFile(sourceFile, 'utf8')) + .then(contents => { + expect(contents).to.equal('import * as foo from "./bar"'); + }); + }); + }); + + describe('ReplaceChange', () => { + it('replaces the given text in the source code', () => { + let sourceFile = path.join(sourcePath, 'remove-replace-file.txt'); + let changeInstance = new ReplaceChange(sourceFile, 7, '* as foo', '{ fooComponent }'); + return changeInstance + .apply() + .then(() => readFile(sourceFile, 'utf8')) + .then(contents => { + expect(contents).to.equal('import { fooComponent } from "./bar"'); + }); + }); + it('fails for negative position', () => { + let sourceFile = path.join(sourcePath, 'remove-replace-file.txt'); + expect(() => new ReplaceChange(sourceFile, -6, 'hello', ' world!')).to.throw(Error); + }); + it('adds string to the position of an empty string', () => { + let sourceFile = path.join(sourcePath, 'replace-file.txt'); + let changeInstance = new ReplaceChange(sourceFile, 9, '', 'BarComponent, '); + return changeInstance + .apply() + .then(() => readFile(sourceFile, 'utf8')) + .then(contents => { + expect(contents).to.equal('import { BarComponent, FooComponent } from "./baz"'); + }); + }); + it('removes the given string only if an empty string to add is given', () => { + let sourceFile = path.join(sourcePath, 'remove-replace-file.txt'); + let changeInstance = new ReplaceChange(sourceFile, 9, ' as foo', ''); + return changeInstance + .apply() + .then(() => readFile(sourceFile, 'utf8')) + .then(contents => { + expect(contents).to.equal('import * from "./bar"'); + }); + }); + }); +}); diff --git a/tests/e2e/e2e_workflow.spec.js b/tests/e2e/e2e_workflow.spec.js index 3c90073b84fe..ea1ea1d2d920 100644 --- a/tests/e2e/e2e_workflow.spec.js +++ b/tests/e2e/e2e_workflow.spec.js @@ -291,12 +291,17 @@ describe('Basic end-to-end Workflow', function () { let componentPath = path.join(process.cwd(), 'src', 'app', 'test-component'); let cssFile = path.join(componentPath, 'test-component.component.css'); let scssFile = path.join(componentPath, 'test-component.component.scss'); + let scssPartialFile = path.join(componentPath, '_test-component.component.partial.scss'); + + let scssPartialExample = '.partial {\n @extend .outer;\n }'; + fs.writeFileSync(scssPartialFile, scssPartialExample, 'utf8'); + expect(existsSync(scssPartialFile)).to.be.equal(true); expect(existsSync(componentPath)).to.be.equal(true); sh.mv(cssFile, scssFile); expect(existsSync(scssFile)).to.be.equal(true); expect(existsSync(cssFile)).to.be.equal(false); - let scssExample = '.outer {\n .inner { background: #fff; }\n }'; + let scssExample = '@import "test-component.component.partial";\n\n.outer {\n .inner { background: #fff; }\n }'; fs.writeFileSync(scssFile, scssExample, 'utf8'); sh.exec(`${ngBin} build`); @@ -304,6 +309,7 @@ describe('Basic end-to-end Workflow', function () { expect(existsSync(destCss)).to.be.equal(true); let contents = fs.readFileSync(destCss, 'utf8'); expect(contents).to.include('.outer .inner'); + expect(contents).to.include('.partial .inner'); sh.rm('-f', destCss); process.chdir('src'); @@ -311,6 +317,7 @@ describe('Basic end-to-end Workflow', function () { expect(existsSync(destCss)).to.be.equal(true); contents = fs.readFileSync(destCss, 'utf8'); expect(contents).to.include('.outer .inner'); + expect(contents).to.include('.partial .inner'); process.chdir('..'); sh.exec('npm uninstall node-sass', { silent: true });