diff --git a/.appveyor.yml b/.appveyor.yml
index 26f8d6968d55..ec90cf597337 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -1,5 +1,7 @@
environment:
- nodejs_version: "5.0"
+ matrix:
+ - nodejs_version: "5.0"
+ - nodejs_version: "6.0"
install:
- ps: Install-Product node $env:nodejs_version
diff --git a/.travis.yml b/.travis.yml
index 874ac8c166df..f4f5e0bd6d67 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,6 +7,8 @@ env:
- NODE_VERSION=5 SCRIPT=lint
- NODE_VERSION=5 SCRIPT=test
- NODE_VERSION=5 TARGET=mobile SCRIPT=mobile_test
+ - NODE_VERSION=6 SCRIPT=test
+ - NODE_VERSION=6 TARGET=mobile SCRIPT=mobile_test
os:
- linux
- osx
@@ -16,6 +18,8 @@ matrix:
env: NODE_VERSION=5 SCRIPT=lint
- os: osx
env: NODE_VERSION=5 TARGET=mobile SCRIPT=mobile_test
+ - os: osx
+ env: NODE_VERSION=6 TARGET=mobile SCRIPT=mobile_test
script:
- npm run-script $SCRIPT
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 07567ddd5cb3..039ba99e2802 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,22 @@
+
+# [1.0.0-beta.10](https://github.com/angular/angular-cli/compare/1.0.0-beta.9...v1.0.0-beta.10) (2016-07-19)
+
+
+### Bug Fixes
+
+* **build:** don't ignore js in public ([#1129](https://github.com/angular/angular-cli/issues/1129)) ([00e111a](https://github.com/angular/angular-cli/commit/00e111a)), closes [#540](https://github.com/angular/angular-cli/issues/540)
+* **mobile:** remove app/index.js from concatenated bundle ([#1267](https://github.com/angular/angular-cli/issues/1267)) ([03fd4c4](https://github.com/angular/angular-cli/commit/03fd4c4))
+* Fix all versions of dependencies to Angular-CLI ([#1331](https://github.com/angular/angular-cli/issues/1331)) ([022e7f9](https://github.com/angular/angular-cli/commit/022e7f9)), closes [#1331](https://github.com/angular/angular-cli/issues/1331)
+* fix versions in the shrinkwrap instead of using ranges ([#1350](https://github.com/angular/angular-cli/issues/1350)) ([72bc9d9](https://github.com/angular/angular-cli/commit/72bc9d9)), closes [#1350](https://github.com/angular/angular-cli/issues/1350)
+
+
+### Features
+
+* **router:** upgrade the router version ([#1288](https://github.com/angular/angular-cli/issues/1288)) ([2c9a371](https://github.com/angular/angular-cli/commit/2c9a371))
+* add get-dependent-fils utils ([6590743](https://github.com/angular/angular-cli/commit/6590743))
+
+
+
**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.**
---
diff --git a/README.md b/README.md
index 2deb864fa7b2..a91d41328aec 100644
--- a/README.md
+++ b/README.md
@@ -102,25 +102,9 @@ Enum | `ng g enum my-new-enum`
### Generating a route
-You can generate a new route with the following command (note the singular
-used in `hero`):
+Generating routes in the CLI has been disabled for the time being. A new router and new route generation blueprints are coming.
-```bash
-ng generate route hero
-```
-
-This will create a folder which will contain the hero component and related test and style files.
-
-The generated route will also be registered with the parent component's `@RouteConfig` decorator.
-
-By default the route will be designated as a **lazy** route which means that it will be loaded into the browser when needed, not upfront as part of a bundle.
-
-In order to visually distinguish lazy routes from other routes the folder for the route will be prefixed with a `+` per the above example the folder will be named `+hero`.
-This is done in accordance with the [style guide](https://angular.io/styleguide#!#prefix-lazy-loaded-folders-with-).
-
-The default lazy nature of routes can be turned off via the lazy flag (`--lazy false`)
-
-There is an optional flag for `skip-router-generation` which will not add the route to the parent component's `@RouteConfig` decorator.
+You can read the official documentation for the new Router here: https://angular.io/docs/ts/latest/guide/router.html. Please note that even though route generation is disabled, building your projects with routing is still fully supported.
### Creating a build
diff --git a/addon/ng2/blueprints/ng2/files/__path__/system-config.ts b/addon/ng2/blueprints/ng2/files/__path__/system-config.ts
index 55e4ac712886..f15ddf871001 100644
--- a/addon/ng2/blueprints/ng2/files/__path__/system-config.ts
+++ b/addon/ng2/blueprints/ng2/files/__path__/system-config.ts
@@ -1,3 +1,5 @@
+"use strict";
+
// SystemJS configuration file, see links for more information
// https://github.com/systemjs/systemjs
// https://github.com/systemjs/systemjs/blob/master/docs/config-api.md
diff --git a/addon/ng2/blueprints/ng2/files/__path__/typings.d.ts b/addon/ng2/blueprints/ng2/files/__path__/typings.d.ts
index a58a428505dd..96dd4854d801 100644
--- a/addon/ng2/blueprints/ng2/files/__path__/typings.d.ts
+++ b/addon/ng2/blueprints/ng2/files/__path__/typings.d.ts
@@ -2,5 +2,5 @@
// https://github.com/typings/typings
// https://www.typescriptlang.org/docs/handbook/writing-declaration-files.html
-///
+///
<% if(!isMobile) { %>declare var module: { id: string };<% } %>
diff --git a/addon/ng2/blueprints/ng2/files/e2e/typings.d.ts b/addon/ng2/blueprints/ng2/files/e2e/typings.d.ts
index 9c2f2d0252ef..eebc2728b868 100644
--- a/addon/ng2/blueprints/ng2/files/e2e/typings.d.ts
+++ b/addon/ng2/blueprints/ng2/files/e2e/typings.d.ts
@@ -1 +1 @@
-///
+///
diff --git a/addon/ng2/blueprints/ng2/files/package.json b/addon/ng2/blueprints/ng2/files/package.json
index 9c58713a4b9f..01ada2be0e42 100644
--- a/addon/ng2/blueprints/ng2/files/package.json
+++ b/addon/ng2/blueprints/ng2/files/package.json
@@ -47,6 +47,6 @@
"ts-node": "0.5.5",
"tslint": "3.11.0",
"typescript": "1.8.10",
- "typings": "0.8.1"<%= stylePackage %>
+ "typings": "1.3.1"<%= stylePackage %>
}
}
diff --git a/addon/ng2/blueprints/ng2/files/typings.json b/addon/ng2/blueprints/ng2/files/typings.json
index 21f9888ab067..dc0f75bd2140 100644
--- a/addon/ng2/blueprints/ng2/files/typings.json
+++ b/addon/ng2/blueprints/ng2/files/typings.json
@@ -1,11 +1,11 @@
{
- "ambientDevDependencies": {
+ "globalDevDependencies": {
"angular-protractor": "registry:dt/angular-protractor#1.5.0+20160425143459",
- "jasmine": "registry:dt/jasmine#2.2.0+20160412134438",
+ "jasmine": "registry:dt/jasmine#2.2.0+20160621224255",
"selenium-webdriver": "registry:dt/selenium-webdriver#2.44.0+20160317120654"
},
- "ambientDependencies": {
- "es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654"<% if (isMobile) {%>,
- "node": "registry:dt/node#4.0.0+20160509154515" <% } %>
+ "globalDependencies": {
+ "es6-shim": "registry:dt/es6-shim#0.31.2+20160602141504"<% if (isMobile) {%>,
+ "node": "registry:dt/node#6.0.0+20160709114037" <% } %>
}
}
diff --git a/addon/ng2/utilities/get-dependent-files.ts b/addon/ng2/utilities/get-dependent-files.ts
new file mode 100644
index 000000000000..6f38efd4dfcf
--- /dev/null
+++ b/addon/ng2/utilities/get-dependent-files.ts
@@ -0,0 +1,124 @@
+'use strict';
+
+import * as fs from 'fs';
+import * as ts from 'typescript';
+import * as glob from 'glob';
+import * as path from 'path';
+import * as denodeify from 'denodeify';
+
+import { Promise } from 'es6-promise';
+
+/**
+ * Interface that represents a module specifier and its position in the source file.
+ * Use for storing a string literal, start position and end posittion of ImportClause node kinds.
+ */
+export interface ModuleImport {
+ specifierText: string;
+ pos: number;
+ end: number;
+};
+
+export interface ModuleMap {
+ [key: string]: ModuleImport[];
+}
+
+/**
+ * Create a SourceFile as defined by Typescript Compiler API.
+ * Generate a AST structure from a source file.
+ *
+ * @param fileName source file for which AST is to be extracted
+ */
+export function createTsSourceFile(fileName: string): Promise {
+ const readFile = denodeify(fs.readFile);
+ return readFile(fileName, 'utf8')
+ .then((contents: string) => {
+ return ts.createSourceFile(fileName, contents, ts.ScriptTarget.ES6, true);
+ });
+}
+
+/**
+ * Traverses through AST of a given file of kind 'ts.SourceFile', filters out child
+ * nodes of the kind 'ts.SyntaxKind.ImportDeclaration' and returns import clauses as
+ * ModuleImport[]
+ *
+ * @param {ts.SourceFile} node: Typescript Node of whose AST is being traversed
+ *
+ * @return {ModuleImport[]} traverses through ts.Node and returns an array of moduleSpecifiers.
+ */
+export function getImportClauses(node: ts.SourceFile): ModuleImport[] {
+ return node.statements
+ .filter(node => node.kind === ts.SyntaxKind.ImportDeclaration) // Only Imports.
+ .map((node: ts.ImportDeclaration) => {
+ let moduleSpecifier = node.moduleSpecifier;
+ return {
+ specifierText: moduleSpecifier.getText().slice(1, -1),
+ pos: moduleSpecifier.pos,
+ end: moduleSpecifier.end
+ };
+ });
+}
+
+/**
+ * Find the file, 'index.ts' given the directory name and return boolean value
+ * based on its findings.
+ *
+ * @param dirPath
+ *
+ * @return a boolean value after it searches for a barrel (index.ts by convention) in a given path
+ */
+export function hasIndexFile(dirPath: string): Promise {
+ const globSearch = denodeify(glob);
+ return globSearch(path.join(dirPath, 'index.ts'), { nodir: true })
+ .then((indexFile: string[]) => {
+ return indexFile.length > 0;
+ });
+}
+
+/**
+ * Returns a map of all dependent file/s' path with their moduleSpecifier object
+ * (specifierText, pos, end)
+ *
+ * @param fileName file upon which other files depend
+ * @param rootPath root of the project
+ *
+ * @return {Promise} ModuleMap of all dependent file/s (specifierText, pos, end)
+ *
+ */
+export function getDependentFiles(fileName: string, rootPath: string): Promise {
+ const globSearch = denodeify(glob);
+ return globSearch(path.join(rootPath, '**/*.*.ts'), { nodir: true })
+ .then((files: string[]) => Promise.all(files.map(file => createTsSourceFile(file)))
+ .then((tsFiles: ts.SourceFile[]) => tsFiles.map(file => getImportClauses(file)))
+ .then((moduleSpecifiers: ModuleImport[][]) => {
+ let allFiles: ModuleMap = {};
+ files.forEach((file, index) => {
+ let sourcePath = path.normalize(file);
+ allFiles[sourcePath] = moduleSpecifiers[index];
+ });
+ return allFiles;
+ })
+ .then((allFiles: ModuleMap) => {
+ let relevantFiles: ModuleMap = {};
+ Object.keys(allFiles).forEach(filePath => {
+ const tempModuleSpecifiers: ModuleImport[] = allFiles[filePath]
+ .filter(importClause => {
+ // Filter only relative imports
+ let singleSlash = importClause.specifierText.charAt(0) === '/';
+ let currentDirSyntax = importClause.specifierText.slice(0, 2) === './';
+ let parentDirSyntax = importClause.specifierText.slice(0, 3) === '../';
+ return singleSlash || currentDirSyntax || parentDirSyntax;
+ })
+ .filter(importClause => {
+ let modulePath = path.resolve(path.dirname(filePath), importClause.specifierText);
+ let resolvedFileName = path.resolve(fileName);
+ let fileBaseName = path.basename(resolvedFileName, '.ts');
+ let parsedFilePath = path.join(path.dirname(resolvedFileName), fileBaseName);
+ return (parsedFilePath === modulePath) || (resolvedFileName === modulePath);
+ });
+ if (tempModuleSpecifiers.length > 0) {
+ relevantFiles[filePath] = tempModuleSpecifiers;
+ };
+ });
+ return relevantFiles;
+ }));
+}
diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json
index 5fc2d093f6fb..c7ddd786a527 100644
--- a/npm-shrinkwrap.json
+++ b/npm-shrinkwrap.json
@@ -1104,6 +1104,10 @@
"version": "1.0.0",
"from": "delegates@1.0.0"
},
+ "denodeify": {
+ "version": "1.2.1",
+ "from": "denodeify@>=1.2.1 <2.0.0"
+ },
"depd": {
"version": "1.1.0",
"from": "depd@1.1.0"
@@ -2346,6 +2350,10 @@
"version": "0.1.4",
"from": "es6-map@0.1.4"
},
+ "es6-promise": {
+ "version": "3.2.1",
+ "from": "es6-promise@>=3.2.1 <4.0.0"
+ },
"es6-set": {
"version": "0.1.4",
"from": "es6-set@0.1.4"
diff --git a/package.json b/package.json
index 4aafdb5f276e..2d6c3ed36e21 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "angular-cli",
- "version": "1.0.0-beta.9",
+ "version": "1.0.0-beta.10",
"description": "CLI tool for Angular",
"main": "lib/cli/index.js",
"trackingCode": "UA-8594346-19",
@@ -40,8 +40,10 @@
"broccoli-uglify-js": "^0.1.3",
"broccoli-writer": "^0.1.1",
"chalk": "^1.1.3",
+ "denodeify": "^1.2.1",
"ember-cli": "2.5.0",
"ember-cli-string-utils": "^1.0.0",
+ "es6-promise": "^3.2.1",
"exit": "^0.1.2",
"fs-extra": "^0.30.0",
"glob": "^7.0.3",
diff --git a/tests/acceptance/get-dependent-files.spec.ts b/tests/acceptance/get-dependent-files.spec.ts
new file mode 100644
index 000000000000..ff36244a0971
--- /dev/null
+++ b/tests/acceptance/get-dependent-files.spec.ts
@@ -0,0 +1,154 @@
+'use strict';
+
+// This needs to be first so fs module can be mocked correctly.
+let mockFs = require('mock-fs');
+import { expect, assert } from 'chai';
+import * as path from 'path';
+import * as ts from 'typescript';
+import * as dependentFilesUtils from '../../addon/ng2/utilities/get-dependent-files';
+
+describe('Get Dependent Files: ', () => {
+ let rootPath = 'src/app';
+
+ beforeEach(() => {
+ let mockDrive = {
+ 'src/app': {
+ 'foo': {
+ 'foo.component.ts': `import * from '../bar/baz/baz.component'
+ import * from '../bar/bar.component'`,
+ 'index.ts': `export * from './foo.component'`
+ },
+ 'bar': {
+ 'baz': {
+ 'baz.component.ts': 'import * from "../bar.component"',
+ 'baz.html': ' Hello
'
+ },
+ 'bar.component.ts': `import * from './baz/baz.component'
+ import * from '../foo'`
+ },
+ 'foo-baz': {
+ 'no-module.component.ts': ''
+ },
+ 'empty-dir': {}
+ }
+ };
+ mockFs(mockDrive);
+ });
+ afterEach(() => {
+ mockFs.restore();
+ });
+
+ describe('getImportClauses', () => {
+ it('returns import specifiers when there is a single import statement', () => {
+ let sourceFile = path.join(rootPath, 'bar/baz/baz.component.ts');
+ return dependentFilesUtils.createTsSourceFile(sourceFile)
+ .then((tsFile: ts.SourceFile) => {
+ let contents = dependentFilesUtils.getImportClauses(tsFile);
+ let expectedContents = [{
+ specifierText: '../bar.component',
+ pos: 13,
+ end: 32
+ }];
+ assert.deepEqual(contents, expectedContents);
+ });
+ });
+ it('returns imports specifiers when there are multiple import statements', () => {
+ let sourceFile = path.join(rootPath, 'foo/foo.component.ts');
+ return dependentFilesUtils.createTsSourceFile(sourceFile)
+ .then((tsFile: ts.SourceFile) => {
+ let contents = dependentFilesUtils.getImportClauses(tsFile);
+ let expectedContents = [
+ {
+ specifierText: '../bar/baz/baz.component',
+ pos: 13,
+ end: 40
+ },
+ {
+ specifierText: '../bar/bar.component',
+ pos: 85,
+ end: 108
+ }
+ ];
+ assert.deepEqual(contents, expectedContents);
+ });
+ });
+ });
+
+ describe('createTsSourceFile', () => {
+ it('creates ts.SourceFile give a file path', () => {
+ let sourceFile = path.join(rootPath, 'foo/foo.component.ts');
+ return dependentFilesUtils.createTsSourceFile(sourceFile)
+ .then((tsFile: ts.SourceFile) => {
+ let isTsSourceFile = (tsFile.kind === ts.SyntaxKind.SourceFile);
+ expect(isTsSourceFile).to.be.true;
+ });
+ });
+ });
+
+ describe('hasIndexFile', () => {
+ it('returns true when there is a index file', () => {
+ let sourceFile = path.join(rootPath, 'foo');
+ dependentFilesUtils.hasIndexFile(sourceFile)
+ .then((booleanValue: boolean) => {
+ expect(booleanValue).to.be.true;
+ });
+ });
+ it('returns false when there is no index file', () => {
+ let sourceFile = path.join(rootPath, 'bar');
+ dependentFilesUtils.hasIndexFile(sourceFile)
+ .then((booleanValue: boolean) => {
+ expect(booleanValue).to.be.false;
+ });
+ });
+ });
+
+ describe('returns a map of all files which depend on a given file ', () => {
+ it('when the given component unit has no index file', () => {
+ let sourceFile = path.join(rootPath, 'bar/bar.component.ts');
+ return dependentFilesUtils.getDependentFiles(sourceFile, rootPath)
+ .then((contents: dependentFilesUtils.ModuleMap) => {
+ let bazFile = path.join(rootPath, 'bar/baz/baz.component.ts');
+ let fooFile = path.join(rootPath, 'foo/foo.component.ts');
+ let expectedContents: dependentFilesUtils.ModuleMap = {};
+ expectedContents[bazFile] = [{
+ specifierText: '../bar.component',
+ pos: 13,
+ end: 32
+ }];
+ expectedContents[fooFile] = [{
+ specifierText: '../bar/bar.component',
+ pos: 85,
+ end: 108
+ }];
+ assert.deepEqual(contents, expectedContents);
+ });
+ });
+ it('when the given component unit has no index file [More Test]', () => {
+ let sourceFile = path.join(rootPath, 'bar/baz/baz.component.ts');
+ return dependentFilesUtils.getDependentFiles(sourceFile, rootPath)
+ .then((contents: dependentFilesUtils.ModuleMap) => {
+ let expectedContents: dependentFilesUtils.ModuleMap = {};
+ let barFile = path.join(rootPath, 'bar/bar.component.ts');
+ let fooFile = path.join(rootPath, 'foo/foo.component.ts');
+ expectedContents[barFile] = [{
+ specifierText: './baz/baz.component',
+ pos: 13,
+ end: 35
+ }];
+ expectedContents[fooFile] = [{
+ specifierText: '../bar/baz/baz.component',
+ pos: 13,
+ end: 40
+ }];
+ assert.deepEqual(contents, expectedContents);
+ });
+ });
+ it('when there are no dependent files', () => {
+ let sourceFile = path.join(rootPath, 'foo-baz/no-module.component.ts');
+ return dependentFilesUtils.getDependentFiles(sourceFile, rootPath)
+ .then((contents: dependentFilesUtils.ModuleMap) => {
+ assert.deepEqual(contents, {});
+ });
+ });
+ });
+});
diff --git a/typings.json b/typings.json
index e9093d1857fc..5d47c2fc7a0b 100644
--- a/typings.json
+++ b/typings.json
@@ -1,5 +1,7 @@
{
- "dependencies": {},
+ "dependencies": {
+ "es6-promise": "registry:npm/es6-promise#3.0.0+20160211003958"
+ },
"devDependencies": {
"chalk": "github:typings/typed-chalk#a7e422c5455e70292e5675a727d43a7b05fc3e58"
},