From 67ff7f0b3ba65e69d7c58141d9b8b50c29a6584f Mon Sep 17 00:00:00 2001
From: Mike Brocchi
Date: Thu, 16 Nov 2017 09:31:52 -0500
Subject: [PATCH 001/807] fix(@schematics/angular): Remove dep @angular/http
Fixes angular/angular-cli#8507
---
packages/schematics/angular/application/files/package.json | 1 -
1 file changed, 1 deletion(-)
diff --git a/packages/schematics/angular/application/files/package.json b/packages/schematics/angular/application/files/package.json
index 79d69c0a5c..a5ac05ae0c 100644
--- a/packages/schematics/angular/application/files/package.json
+++ b/packages/schematics/angular/application/files/package.json
@@ -17,7 +17,6 @@
"@angular/compiler": "^5.0.0",
"@angular/core": "^5.0.0",
"@angular/forms": "^5.0.0",
- "@angular/http": "^5.0.0",
"@angular/platform-browser": "^5.0.0",
"@angular/platform-browser-dynamic": "^5.0.0",
"@angular/router": "^5.0.0",<% if (serviceWorker) { %>
From d6d24627c90d31bf5eda0c8d24689ee6d32c147c Mon Sep 17 00:00:00 2001
From: Charles Lyding <19598772+clydin@users.noreply.github.com>
Date: Mon, 2 Oct 2017 13:15:35 -0400
Subject: [PATCH 002/807] refactor(@angular-devkit/schematics): make filesystem
tree get/read/branch lazy
---
.../schematics/src/tree/filesystem.ts | 25 +++++++++++++++++--
.../schematics/src/tree/memory-host.ts | 5 ++++
.../schematics/src/tree/node-host.ts | 3 +++
.../schematics/tools/file-system-host.ts | 5 +++-
4 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/packages/angular_devkit/schematics/src/tree/filesystem.ts b/packages/angular_devkit/schematics/src/tree/filesystem.ts
index 03e8805b00..dcb7652ff3 100644
--- a/packages/angular_devkit/schematics/src/tree/filesystem.ts
+++ b/packages/angular_devkit/schematics/src/tree/filesystem.ts
@@ -15,7 +15,7 @@ import {
normalize,
} from '@angular-devkit/core';
import { LazyFileEntry } from './entry';
-import { DirEntry, FileEntry } from './interface';
+import { DirEntry, FileEntry, Tree } from './interface';
import { VirtualDirEntry, VirtualTree } from './virtual';
@@ -23,6 +23,7 @@ export interface FileSystemTreeHost {
listDirectory: (path: string) => string[];
isDirectory: (path: string) => boolean;
readFile: (path: string) => Buffer;
+ exists: (path: string) => boolean;
join: (path1: string, other: string) => string;
}
@@ -122,7 +123,27 @@ export class FileSystemTree extends VirtualTree {
get(path: string): FileEntry | null {
const normalizedPath = this._normalizePath(path);
- return this._cacheMap.get(normalizedPath) || this.tree.get(normalizedPath) || null;
+ let entry = this._cacheMap.get(normalizedPath) || this._tree.get(normalizedPath) || null;
+
+ if (entry == null && !this._initialized) {
+ const systemPath = normalizedPath;
+ const fileExists = this._host.exists(systemPath) && !this._host.isDirectory(systemPath);
+
+ if (fileExists) {
+ const host = this._host;
+ entry = new LazyFileEntry(normalizedPath, () => host.readFile(systemPath));
+ this._tree.set(normalizedPath, entry);
+ }
+ }
+
+ return entry;
+ }
+
+ branch(): Tree {
+ const newTree = new FileSystemTree(this._host);
+ this._copyTo(newTree);
+
+ return newTree;
}
protected _copyTo(tree: T): void {
diff --git a/packages/angular_devkit/schematics/src/tree/memory-host.ts b/packages/angular_devkit/schematics/src/tree/memory-host.ts
index e75a4f37a4..a9135218da 100644
--- a/packages/angular_devkit/schematics/src/tree/memory-host.ts
+++ b/packages/angular_devkit/schematics/src/tree/memory-host.ts
@@ -42,6 +42,11 @@ export class InMemoryFileSystemTreeHost implements FileSystemTreeHost {
return this._content[path] || new Buffer('');
}
+ exists(path: string) {
+ path = normalize(path);
+
+ return this._content[path] != undefined;
+ }
join(path1: string, path2: string) {
return normalize(path1 + '/' + path2);
diff --git a/packages/angular_devkit/schematics/src/tree/node-host.ts b/packages/angular_devkit/schematics/src/tree/node-host.ts
index 2d8778095a..7736096a95 100644
--- a/packages/angular_devkit/schematics/src/tree/node-host.ts
+++ b/packages/angular_devkit/schematics/src/tree/node-host.ts
@@ -22,6 +22,9 @@ export class NodeJsHost implements FileSystemTreeHost {
readFile(path: string) {
return fs.readFileSync(this.join(this._root, path));
}
+ exists(path: string) {
+ return fs.existsSync(this.join(this._root, path));
+ }
join(path1: string, path2: string) {
return join(path1, path2);
diff --git a/packages/angular_devkit/schematics/tools/file-system-host.ts b/packages/angular_devkit/schematics/tools/file-system-host.ts
index 12c6a4f9ec..ad3317f7fd 100644
--- a/packages/angular_devkit/schematics/tools/file-system-host.ts
+++ b/packages/angular_devkit/schematics/tools/file-system-host.ts
@@ -7,7 +7,7 @@
*/
import { fs } from '@angular-devkit/core/node';
import { FileSystemTreeHost } from '@angular-devkit/schematics';
-import { readFileSync, readdirSync } from 'fs';
+import { existsSync, readFileSync, readdirSync } from 'fs';
import { join } from 'path';
export class FileSystemHost implements FileSystemTreeHost {
@@ -22,6 +22,9 @@ export class FileSystemHost implements FileSystemTreeHost {
readFile(path: string) {
return readFileSync(join(this._root, path));
}
+ exists(path: string) {
+ return existsSync(this.join(this._root, path));
+ }
join(path1: string, path2: string) {
return join(path1, path2);
From e1f5cf73ccdcd34f48d2a05acb54300d386155e9 Mon Sep 17 00:00:00 2001
From: Niklas
Date: Fri, 10 Nov 2017 10:18:16 +0100
Subject: [PATCH 003/807] fix(@schematics/angular): added alt tag to img
get that 100/100 in Lighthouse Accessibility
---
.../angular/application/other-files/app.component.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/schematics/angular/application/other-files/app.component.html b/packages/schematics/angular/application/other-files/app.component.html
index fd470954c1..0001f4d4e6 100644
--- a/packages/schematics/angular/application/other-files/app.component.html
+++ b/packages/schematics/angular/application/other-files/app.component.html
@@ -3,7 +3,7 @@
Welcome to {{title}}!
-
+
Here are some links to help you start:
From d7c99fac973e4132e1bfca824f14c886b4c06c4a Mon Sep 17 00:00:00 2001
From: Mike Brocchi
Date: Thu, 16 Nov 2017 13:46:34 -0500
Subject: [PATCH 004/807] fix(@schematics/angular): Remove default
ViewEncapsulation logic
---
.../schematics/angular/application/schema.json | 3 +--
.../__name@dasherize__.component.ts | 4 ++--
.../schematics/angular/component/index_spec.ts | 17 ++++++++++++++++-
.../schematics/angular/component/schema.json | 1 -
4 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/packages/schematics/angular/application/schema.json b/packages/schematics/angular/application/schema.json
index e8e18de8c6..86742ff1ae 100644
--- a/packages/schematics/angular/application/schema.json
+++ b/packages/schematics/angular/application/schema.json
@@ -36,8 +36,7 @@
"viewEncapsulation": {
"description": "Specifies the view encapsulation strategy.",
"enum": ["Emulated", "Native", "None"],
- "type": "string",
- "default": "Emulated"
+ "type": "string"
},
"changeDetection": {
"description": "Specifies the change detection strategy.",
diff --git a/packages/schematics/angular/component/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.ts b/packages/schematics/angular/component/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.ts
index a91388e8dd..a314e02f22 100644
--- a/packages/schematics/angular/component/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.ts
+++ b/packages/schematics/angular/component/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.ts
@@ -1,4 +1,4 @@
-import { Component, OnInit<% if(viewEncapsulation !== 'Emulated') { %>, ViewEncapsulation<% }%><% if(changeDetection !== 'Default') { %>, ChangeDetectionStrategy<% }%> } from '@angular/core';
+import { Component, OnInit<% if(!!viewEncapsulation) { %>, ViewEncapsulation<% }%><% if(changeDetection !== 'Default') { %>, ChangeDetectionStrategy<% }%> } from '@angular/core';
@Component({
selector: '<%= selector %>',<% if(inlineTemplate) { %>
@@ -9,7 +9,7 @@ import { Component, OnInit<% if(viewEncapsulation !== 'Emulated') { %>, ViewEnca
`,<% } else { %>
templateUrl: './<%= dasherize(name) %>.component.html',<% } if(inlineStyle) { %>
styles: []<% } else { %>
- styleUrls: ['./<%= dasherize(name) %>.component.<%= styleext %>']<% } %><% if(viewEncapsulation !== 'Emulated') { %>,
+ styleUrls: ['./<%= dasherize(name) %>.component.<%= styleext %>']<% } %><% if(!!viewEncapsulation) { %>,
encapsulation: ViewEncapsulation.<%= viewEncapsulation %><% } if (changeDetection !== 'Default') { %>,
changeDetection: ChangeDetectionStrategy.<%= changeDetection %><% } %>
})
diff --git a/packages/schematics/angular/component/index_spec.ts b/packages/schematics/angular/component/index_spec.ts
index dd101aba42..b9b138086f 100644
--- a/packages/schematics/angular/component/index_spec.ts
+++ b/packages/schematics/angular/component/index_spec.ts
@@ -23,7 +23,6 @@ describe('Component Schematic', () => {
sourceDir: 'src',
inlineStyle: false,
inlineTemplate: false,
- viewEncapsulation: 'Emulated',
changeDetection: 'Default',
routing: false,
styleext: 'css',
@@ -62,6 +61,22 @@ describe('Component Schematic', () => {
expect(tsContent).toMatch(/changeDetection: ChangeDetectionStrategy.OnPush/);
});
+ it('should not set view encapsulation', () => {
+ const options = { ...defaultOptions };
+
+ const tree = schematicRunner.runSchematic('component', options, appTree);
+ const tsContent = getFileContent(tree, '/src/app/foo/foo.component.ts');
+ expect(tsContent).not.toMatch(/encapsulation: ViewEncapsulation/);
+ });
+
+ it('should set view encapsulation to Emulated', () => {
+ const options = { ...defaultOptions, viewEncapsulation: 'Emulated' };
+
+ const tree = schematicRunner.runSchematic('component', options, appTree);
+ const tsContent = getFileContent(tree, '/src/app/foo/foo.component.ts');
+ expect(tsContent).toMatch(/encapsulation: ViewEncapsulation.Emulated/);
+ });
+
it('should set view encapsulation to None', () => {
const options = { ...defaultOptions, viewEncapsulation: 'None' };
diff --git a/packages/schematics/angular/component/schema.json b/packages/schematics/angular/component/schema.json
index a7f4e34ab3..83aff6e773 100644
--- a/packages/schematics/angular/component/schema.json
+++ b/packages/schematics/angular/component/schema.json
@@ -35,7 +35,6 @@
"description": "Specifies the view encapsulation strategy.",
"enum": ["Emulated", "Native", "None"],
"type": "string",
- "default": "Emulated",
"alias": "ve"
},
"changeDetection": {
From 99fce51b670d351e831e0bd6ce7cedb491700a43 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Thu, 16 Nov 2017 10:56:47 -0800
Subject: [PATCH 005/807] release: patch
---
.monorepo.json | 16 ++++-----
package-lock.json | 84 +++++++++++++++++++++++------------------------
2 files changed, 50 insertions(+), 50 deletions(-)
diff --git a/.monorepo.json b/.monorepo.json
index a8aa1264ae..a001031156 100644
--- a/.monorepo.json
+++ b/.monorepo.json
@@ -42,8 +42,8 @@
},
"packages": {
"@_/benchmark": {
- "version": "0.0.15",
- "hash": "37ed7e417435c92dbf301e7b26ea37ca"
+ "version": "0.0.16",
+ "hash": "b1f9f2d8e1eca2a865d39263f0ca5a38"
},
"@angular-devkit/build-optimizer": {
"name": "Build Optimizer",
@@ -69,20 +69,20 @@
"url": "https://github.com/angular/devkit/blob/master/packages/angular_devkit/schematics/README.md"
}
],
- "version": "0.0.35",
- "hash": "c22129c4ba74040eb388e8365f4b031f"
+ "version": "0.0.36",
+ "hash": "cbde94934c9c70852e98edb46bc88e2d"
},
"@schematics/angular": {
"name": "Angular Schematics",
"section": "Schematics",
- "version": "0.1.3",
- "hash": "5cad2c9718bfe9efa3cbebddab23ff5f"
+ "version": "0.1.4",
+ "hash": "296bcb580074a818045bd014f2f29f46"
},
"@schematics/schematics": {
"name": "Schematics Schematics",
- "version": "0.0.5",
+ "version": "0.0.6",
"section": "Schematics",
- "hash": "cbdcc5c14741e3d75ce6056059bbb50c"
+ "hash": "570c076f9bd85e7acb061adf921ed1a6"
}
}
}
diff --git a/package-lock.json b/package-lock.json
index 35222bd0b9..2206879003 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -57,7 +57,7 @@
"@types/minimatch": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.1.tgz",
- "integrity": "sha1-toPrYL41gwTvFG9XddtMDjaWpVA="
+ "integrity": "sha512-rUO/jz10KRSyA9SHoCWQ8WX9BICyj5jZYu1/ucKEJKb4KzLZCKMURdYbadP157Q6Zl1x0vHsrU+Z/O0XlhYQDw=="
},
"@types/minimist": {
"version": "1.2.0",
@@ -72,12 +72,12 @@
"@types/semver": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-5.4.0.tgz",
- "integrity": "sha1-82WFNa9/H1AqzW2n2vQF/+sffuQ="
+ "integrity": "sha512-PBHCvO98hNec9A491vBbh0ZNDOVxccwKL1u2pm6fs9oDgm7SEnw0lEHqHfjsYryDxnE3zaf7LvERWEXjOp1hig=="
},
"@types/source-list-map": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
- "integrity": "sha1-AHiDYGP/rxdBI0m7o2QIfgrALsk="
+ "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA=="
},
"@types/source-map": {
"version": "0.5.2",
@@ -87,12 +87,12 @@
"@types/tapable": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-0.2.4.tgz",
- "integrity": "sha1-gYGiKNpGGFQ5MA5gDFrjs7OYJYU="
+ "integrity": "sha512-pclMAvhPnXJcJu1ZZ8bQthuUcdDWzDuxDdbSf6l1U6s4fP6EBiZpPsOZYqFOrbqDV97sXGFSsb6AUpiLfv4xIA=="
},
"@types/uglify-js": {
"version": "2.6.29",
"resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-2.6.29.tgz",
- "integrity": "sha1-UhNH9p4gIB0hj1mRrmbhCHivzxo=",
+ "integrity": "sha512-BdFLCZW0GTl31AbqXSak8ss/MqEZ3DN2MH9rkAyGoTuzK7ifGUlX+u0nfbWeTsa7IPcZhtn8BlpYBXSV+vqGhQ==",
"requires": {
"@types/source-map": "0.5.2"
}
@@ -110,7 +110,7 @@
"@types/webpack-sources": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.3.tgz",
- "integrity": "sha1-L4uwx6Zs+VLzM8ghdamVWZQyFnQ=",
+ "integrity": "sha512-yS052yVjjyIjwcUqIEe2+JxbWsw27OM8UFb1fLUGacGYtqMRwgAx2qk41VTE/nPMjw/xfD0JiHPD0Q99dlrInA==",
"requires": {
"@types/node": "6.0.90",
"@types/source-list-map": "0.1.2",
@@ -163,7 +163,7 @@
"ansi-styles": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
- "integrity": "sha1-wVm41b4PnlpvNG2rlPFs4CIWG4g=",
+ "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
"requires": {
"color-convert": "1.9.0"
}
@@ -171,7 +171,7 @@
"aproba": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
- "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo="
+ "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
},
"are-we-there-yet": {
"version": "1.1.4",
@@ -311,7 +311,7 @@
"big.js": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
- "integrity": "sha1-pfwpi4G54Nyi5FiCR4S2XFK6WI4="
+ "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q=="
},
"block-stream": {
"version": "0.0.9",
@@ -472,7 +472,7 @@
"commander": {
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
- "integrity": "sha1-FXFS/R56bI2YpbcVzzdt+SgARWM="
+ "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ=="
},
"compare-func": {
"version": "1.3.2",
@@ -522,7 +522,7 @@
"conventional-changelog-atom": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-0.1.1.tgz",
- "integrity": "sha1-1AqbKXlhtTx0Xl0XGP0aM3n2qS8=",
+ "integrity": "sha512-6Nlu/+MiD4gi7k3Z+N1vMJWpaPSdvFPWzPGnH4OXewHAxiAl0L/TT9CGgA01fosPxmYr4hMNtD7kyN0tkg8vIA==",
"requires": {
"q": "1.5.1"
}
@@ -530,7 +530,7 @@
"conventional-changelog-codemirror": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-0.2.0.tgz",
- "integrity": "sha1-PMkllV87FEAoJ7FRaASYIZctlFk=",
+ "integrity": "sha512-jUbY98JoKdAOR5k3pOBiKZ+Iz9t2F84hL7x4WjSRW6x7FdeCEUOjyfml+YClE2h/h62Tf3mwur5jSO8upxxc1g==",
"requires": {
"q": "1.5.1"
}
@@ -566,7 +566,7 @@
"conventional-changelog-eslint": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-0.2.0.tgz",
- "integrity": "sha1-tLm13AlBeETYfHvPsWvcxobEscE=",
+ "integrity": "sha512-WGKnC0bGPD6BHGiRBfYqNGfy6DZDn2jGs1yxPRT8I2796wYdGqsbDF4477o4fdsxUJvckoW2OFPqkmRMQaCHSA==",
"requires": {
"q": "1.5.1"
}
@@ -574,7 +574,7 @@
"conventional-changelog-express": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-0.2.0.tgz",
- "integrity": "sha1-jWZq1BsQ6/lkpGAgYt3S4A3rUY0=",
+ "integrity": "sha512-ujSEmbWfozC1iIjH5Pl7AKtREowvAl10whs1q6c7nZLnoNZK5CmdB2PQ/V42O6rCgUzaLX+ACRW2+g0A/Htqvw==",
"requires": {
"q": "1.5.1"
}
@@ -598,7 +598,7 @@
"conventional-changelog-jshint": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-0.2.0.tgz",
- "integrity": "sha1-Y6167GbNGuVZuv6ANIxGV6brGHI=",
+ "integrity": "sha512-uUP4c0et6F2teapl+YY2JHFAHD401U5CkgI+P8PyU0y1zS8BdBy6EnhqgZEXhFOp9fPzUdic+Wv/9alOqw3agQ==",
"requires": {
"compare-func": "1.3.2",
"q": "1.5.1"
@@ -607,7 +607,7 @@
"conventional-changelog-writer": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-2.0.1.tgz",
- "integrity": "sha1-R8END6ulJreNGUOJ0ekx0J7mI3I=",
+ "integrity": "sha512-X4qC758celQOKw0iUPAsH5sJX6fH6N5dboFc3elXb1/SIKhsYMukhhaxWmxRdtVUSqGt9rZg8giwBQG5B2GeKg==",
"requires": {
"compare-func": "1.3.2",
"conventional-commits-filter": "1.0.0",
@@ -633,7 +633,7 @@
"conventional-commits-parser": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-2.0.0.tgz",
- "integrity": "sha1-cdAZEMsKma6yDBROUPgfTfMXhEc=",
+ "integrity": "sha512-8od6g684Fhi5Vpp4ABRv/RBsW1AY6wSHbJHEK6FGTv+8jvAAnlABniZu/FVmX9TcirkHepaEsa1QGkRvbg0CKw==",
"requires": {
"JSONStream": "1.3.1",
"is-text-path": "1.0.1",
@@ -710,7 +710,7 @@
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
@@ -961,7 +961,7 @@
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0="
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"gauge": {
"version": "2.7.4",
@@ -1051,7 +1051,7 @@
"glob": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
- "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=",
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
"requires": {
"fs.realpath": "1.0.0",
"inflight": "1.0.6",
@@ -1146,7 +1146,7 @@
"hosted-git-info": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz",
- "integrity": "sha1-bWDjSzq7yDEwYsO3mO+NkBoHrzw="
+ "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg=="
},
"http-signature": {
"version": "1.1.1",
@@ -1356,7 +1356,7 @@
"js-yaml": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz",
- "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=",
+ "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==",
"requires": {
"argparse": "1.0.9",
"esprima": "4.0.0"
@@ -1365,7 +1365,7 @@
"esprima": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
- "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ="
+ "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw=="
}
}
},
@@ -1520,7 +1520,7 @@
"lru-cache": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz",
- "integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=",
+ "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==",
"requires": {
"pseudomap": "1.0.2",
"yallist": "2.1.2"
@@ -1605,7 +1605,7 @@
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
- "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"requires": {
"brace-expansion": "1.1.8"
}
@@ -1618,7 +1618,7 @@
"minipass": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.1.tgz",
- "integrity": "sha1-WtqXU4sQJ7TPchNDJChXjLVkAR8=",
+ "integrity": "sha512-u1aUllxPJUI07cOqzR7reGmQxmCqlH88uIIsf6XZFEWgw7gXKpJdR+5R9Y3KEDmWYkdIz9wXZs3C0jOPxejk/Q==",
"requires": {
"yallist": "3.0.2"
},
@@ -1697,7 +1697,7 @@
"rimraf": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
- "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=",
+ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
"requires": {
"glob": "7.1.2"
}
@@ -1725,7 +1725,7 @@
"normalize-package-data": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
- "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=",
+ "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==",
"requires": {
"hosted-git-info": "2.5.0",
"is-builtin-module": "1.0.0",
@@ -5073,7 +5073,7 @@
"npm-run-all": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.1.tgz",
- "integrity": "sha1-MJXPPzys9X/LZishCrEMYJr23bs=",
+ "integrity": "sha512-qrmqqaJa+REbzUTIL/mHfTdgwz+gL1xUezY/ueyLa7GISZ4T3h0CH8D2r6AaZdCYN2unu7PzspP0ofpXla1ftg==",
"requires": {
"ansi-styles": "3.2.0",
"chalk": "2.3.0",
@@ -5135,7 +5135,7 @@
"npmlog": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
- "integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=",
+ "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
"requires": {
"are-we-there-yet": "1.1.4",
"console-control-strings": "1.1.0",
@@ -5407,7 +5407,7 @@
"readable-stream": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
- "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=",
+ "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
@@ -5498,12 +5498,12 @@
"safe-buffer": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
- "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM="
+ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
},
"semver": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
- "integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4="
+ "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg=="
},
"serializerr": {
"version": "1.0.3",
@@ -5558,7 +5558,7 @@
"source-list-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz",
- "integrity": "sha1-qqR0A/eyRakvvJfqCPJQ1gh+0IU="
+ "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A=="
},
"source-map": {
"version": "0.5.7",
@@ -5568,7 +5568,7 @@
"source-map-support": {
"version": "0.4.18",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
- "integrity": "sha1-Aoam3ovkJkEzhZTpfM6nXwosWF8=",
+ "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
"requires": {
"source-map": "0.5.7"
}
@@ -5594,7 +5594,7 @@
"split": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
- "integrity": "sha1-YFvZvjA6pZ+zX5Ip++oN3snqB9k=",
+ "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
"requires": {
"through": "2.3.8"
}
@@ -5665,7 +5665,7 @@
"string_decoder": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
- "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"requires": {
"safe-buffer": "5.1.1"
}
@@ -5725,7 +5725,7 @@
"tar": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/tar/-/tar-3.2.1.tgz",
- "integrity": "sha1-mqjkHIjwnnbBZgdbxx+T1RZuYbE=",
+ "integrity": "sha512-ZSzds1E0IqutvMU8HxjMaU8eB7urw2fGwTq88ukDOVuUIh0656l7/P7LiVPxhO5kS4flcRJQk8USG+cghQbTUQ==",
"requires": {
"chownr": "1.0.1",
"minipass": "2.2.1",
@@ -5996,7 +5996,7 @@
"uuid": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz",
- "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ="
+ "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g=="
},
"v8-profiler": {
"version": "5.7.0",
@@ -6044,7 +6044,7 @@
"webpack-sources": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.0.1.tgz",
- "integrity": "sha1-xzVkNqTRMSO+LiQmoF0drZy+Zc8=",
+ "integrity": "sha512-05tMxipUCwHqYaVS8xc7sYPTly8PzXayRCB4dTxLhWTqlKUiwH6ezmEe0OSreL1c30LAuA3Zqmc+uEBUGFJDjw==",
"requires": {
"source-list-map": "2.0.0",
"source-map": "0.5.7"
@@ -6053,7 +6053,7 @@
"which": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz",
- "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=",
+ "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==",
"requires": {
"isexe": "2.0.0"
}
@@ -6061,7 +6061,7 @@
"wide-align": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz",
- "integrity": "sha1-Vx4PGwYEY268DfwhsDObvjE0FxA=",
+ "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==",
"requires": {
"string-width": "1.0.2"
}
From 7201bccc491cb6d4961eeb0279a15cf3691a4c11 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Thu, 16 Nov 2017 11:21:31 -0800
Subject: [PATCH 006/807] revert: fix(@schematics/angular): Remove dep
@angular/http
This reverts commit cf70df19c2f419c87871aa66d7bc821ff7751a73.
---
packages/schematics/angular/application/files/package.json | 1 +
1 file changed, 1 insertion(+)
diff --git a/packages/schematics/angular/application/files/package.json b/packages/schematics/angular/application/files/package.json
index a5ac05ae0c..79d69c0a5c 100644
--- a/packages/schematics/angular/application/files/package.json
+++ b/packages/schematics/angular/application/files/package.json
@@ -17,6 +17,7 @@
"@angular/compiler": "^5.0.0",
"@angular/core": "^5.0.0",
"@angular/forms": "^5.0.0",
+ "@angular/http": "^5.0.0",
"@angular/platform-browser": "^5.0.0",
"@angular/platform-browser-dynamic": "^5.0.0",
"@angular/router": "^5.0.0",<% if (serviceWorker) { %>
From 8b70cae24ad9309fec72574fdd4c6a9135cad9c8 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Thu, 16 Nov 2017 11:25:03 -0800
Subject: [PATCH 007/807] release: patch
---
.monorepo.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.monorepo.json b/.monorepo.json
index a001031156..eb8999ccd2 100644
--- a/.monorepo.json
+++ b/.monorepo.json
@@ -75,8 +75,8 @@
"@schematics/angular": {
"name": "Angular Schematics",
"section": "Schematics",
- "version": "0.1.4",
- "hash": "296bcb580074a818045bd014f2f29f46"
+ "version": "0.1.5",
+ "hash": "83b90a55d09282a91f4da4f53d39ad3c"
},
"@schematics/schematics": {
"name": "Schematics Schematics",
From 7884fb1b333eb5d37f0e59df3946548a243c2722 Mon Sep 17 00:00:00 2001
From: Mike Brocchi
Date: Fri, 17 Nov 2017 16:08:31 -0500
Subject: [PATCH 008/807] fix(@schematics/angular): Correct positioning of
imports
Fixes angular/angular-cli#8084
---
packages/schematics/angular/utility/route-utils.ts | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/packages/schematics/angular/utility/route-utils.ts b/packages/schematics/angular/utility/route-utils.ts
index 7a113026a5..67e7e4974d 100644
--- a/packages/schematics/angular/utility/route-utils.ts
+++ b/packages/schematics/angular/utility/route-utils.ts
@@ -55,8 +55,9 @@ export function insertImport(source: ts.SourceFile, fileToEdit: string, symbolNa
// insert import if it's not there
if (importTextNodes.length === 0) {
- const fallbackPos = findNodes(relevantImports[0], ts.SyntaxKind.CloseBraceToken)[0].pos ||
- findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].pos;
+ const fallbackPos =
+ findNodes(relevantImports[0], ts.SyntaxKind.CloseBraceToken)[0].getStart() ||
+ findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart();
return insertAfterLastOccurrence(imports, `, ${symbolName}`, fileToEdit, fallbackPos);
}
From 10014dfe1169d7cacd75e5525cc0493c77e10c53 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Fri, 17 Nov 2017 17:43:36 -0800
Subject: [PATCH 009/807] build: allow any -files to be template dirs
---
scripts/build.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/build.ts b/scripts/build.ts
index 817963b040..9a01cda110 100644
--- a/scripts/build.ts
+++ b/scripts/build.ts
@@ -170,7 +170,7 @@ export default function(argv: { local?: boolean }, logger: Logger) {
.filter(fileName => {
// Schematics template files.
if (pkgJson['schematics'] &&
- (fileName.match(/(\/|\\)files(\/|\\)/) || fileName.match(/(\/|\\)other-files(\/|\\)/))) {
+ (fileName.match(/(\/|\\)files(\/|\\)/) || fileName.match(/(\/|\\)\w+-files(\/|\\)/))) {
return true;
}
From 571b564eeb28329c1952a1f207d23fc5a3ab5b23 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Fri, 17 Nov 2017 17:39:41 -0800
Subject: [PATCH 010/807] feat(@schematics/schematics): add a blank schematics
This will create a new project if the collection cannot be found, or add
a new schematics to the current project if it can.
---
.../schematics/schematics/blank/factory.ts | 147 ++++++++++++++++++
.../schematics/blank/project-files/README.md | 28 ++++
.../blank/project-files/__dot__gitignore | 18 +++
.../blank/project-files/package.json | 23 +++
.../blank/project-files/src/collection.json | 5 +
.../blank/project-files/tsconfig.json | 33 ++++
.../schematics/schematics/blank/schema.d.ts | 18 +++
.../schematics/schematics/blank/schema.json | 19 +++
.../src/__name@dasherize__/index.ts | 10 ++
.../src/__name@dasherize__/index_spec.ts | 16 ++
.../schematics/schematics/collection.json | 5 +
11 files changed, 322 insertions(+)
create mode 100644 packages/schematics/schematics/blank/factory.ts
create mode 100644 packages/schematics/schematics/blank/project-files/README.md
create mode 100644 packages/schematics/schematics/blank/project-files/__dot__gitignore
create mode 100644 packages/schematics/schematics/blank/project-files/package.json
create mode 100644 packages/schematics/schematics/blank/project-files/src/collection.json
create mode 100644 packages/schematics/schematics/blank/project-files/tsconfig.json
create mode 100644 packages/schematics/schematics/blank/schema.d.ts
create mode 100644 packages/schematics/schematics/blank/schema.json
create mode 100644 packages/schematics/schematics/blank/schematic-files/src/__name@dasherize__/index.ts
create mode 100644 packages/schematics/schematics/blank/schematic-files/src/__name@dasherize__/index_spec.ts
diff --git a/packages/schematics/schematics/blank/factory.ts b/packages/schematics/schematics/blank/factory.ts
new file mode 100644
index 0000000000..3af4f64064
--- /dev/null
+++ b/packages/schematics/schematics/blank/factory.ts
@@ -0,0 +1,147 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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 {
+ JsonAstObject,
+ JsonObject,
+ JsonValue,
+ Path,
+ camelize,
+ dasherize,
+ normalize,
+ parseJsonAst,
+} from '@angular-devkit/core';
+import {
+ Rule,
+ SchematicContext,
+ Tree,
+ UpdateRecorder,
+ apply,
+ chain,
+ mergeWith,
+ move,
+ template,
+ url,
+} from '@angular-devkit/schematics';
+import { Schema } from './schema';
+
+
+function appendPropertyInAstObject(
+ recorder: UpdateRecorder,
+ node: JsonAstObject,
+ propertyName: string,
+ value: JsonValue,
+ indent = 4,
+) {
+ const indentStr = '\n' + new Array(indent + 1).join(' ');
+
+ if (node.properties.length > 0) {
+ // Insert comma.
+ const last = node.properties[node.properties.length - 1];
+ recorder.insertRight(last.start.offset + last.text.replace(/\s+$/, '').length, ',');
+ }
+
+ recorder.insertLeft(
+ node.end.offset - 1,
+ ' '
+ + `"${propertyName}": ${JSON.stringify(value, null, 2).replace(/\n/g, indentStr)}`
+ + indentStr.slice(0, -2),
+ );
+}
+
+function addSchematicToCollectionJson(
+ collectionPath: Path,
+ schematicName: string,
+ description: JsonObject,
+): Rule {
+ return (tree: Tree, _context: SchematicContext) => {
+ const collectionJsonContent = tree.read(collectionPath);
+ if (!collectionJsonContent) {
+ throw new Error('Invalid collection path: ' + collectionPath);
+ }
+ const collectionJsonAst = parseJsonAst(collectionJsonContent.toString('utf-8'));
+ if (collectionJsonAst.kind !== 'object') {
+ throw new Error('Invalid collection content.');
+ }
+
+ for (const property of collectionJsonAst.properties) {
+ if (property.key.value == 'schematics') {
+ if (property.value.kind !== 'object') {
+ throw new Error('Invalid collection.json; schematics needs to be an object.');
+ }
+
+ const recorder = tree.beginUpdate(collectionPath);
+ appendPropertyInAstObject(recorder, property.value, schematicName, description);
+ tree.commitUpdate(recorder);
+
+ return tree;
+ }
+ }
+
+ throw new Error('Could not find the "schematics" property in collection.json.');
+ };
+}
+
+
+export default function (options: Schema): Rule {
+ const schematicsVersion = require('@angular-devkit/schematics/package.json').version;
+ const coreVersion = require('@angular-devkit/core/package.json').version;
+
+ // Verify if we need to create a full project, or just add a new schematic.
+ return (tree: Tree, context: SchematicContext) => {
+ let collectionPath: Path | undefined;
+ try {
+ const packageJsonContent = tree.read('/package.json');
+ if (packageJsonContent) {
+ const packageJson = JSON.parse(packageJsonContent.toString('utf-8'));
+ if ('schematics' in packageJson) {
+ const p = normalize(packageJson['schematics']);
+ if (tree.exists(p)) {
+ collectionPath = p;
+ }
+ }
+ }
+ } catch (_) {
+ }
+
+ let source = apply(url('./schematic-files'), [
+ template({
+ ...options as object,
+ coreVersion,
+ schematicsVersion,
+ dot: '.',
+ camelize,
+ dasherize,
+ }),
+ ]);
+
+ // Simply create a new schematic project.
+ if (!collectionPath) {
+ collectionPath = normalize('/' + options.name + '/src/collection.json');
+ source = apply(url('./project-files'), [
+ template({
+ ...options as object,
+ coreVersion,
+ schematicsVersion,
+ dot: '.',
+ camelize,
+ dasherize,
+ }),
+ mergeWith(source),
+ move(options.name),
+ ]);
+ }
+
+ return chain([
+ mergeWith(source),
+ addSchematicToCollectionJson(collectionPath, dasherize(options.name), {
+ description: 'A blank schematic.',
+ factory: './' + dasherize(options.name) + '/index#' + camelize(options.name),
+ }),
+ ])(tree, context);
+ };
+}
diff --git a/packages/schematics/schematics/blank/project-files/README.md b/packages/schematics/schematics/blank/project-files/README.md
new file mode 100644
index 0000000000..02a070966f
--- /dev/null
+++ b/packages/schematics/schematics/blank/project-files/README.md
@@ -0,0 +1,28 @@
+# Getting Started With Schematics
+
+This repository is a basic Schematic implementation that serves as a starting point to create and publish Schematics to NPM.
+
+### Testing
+
+To test locally, install `@angular-devkit/schematics` globally and use the `schematics` command line tool. That tool acts the same as the `generate` command of the Angular CLI, but also has a debug mode.
+
+Check the documentation with
+```bash
+schematics --help
+```
+
+### Unit Testing
+
+`npm run test` will run the unit tests, using Jasmine as a runner and test framework.
+
+### Publishing
+
+To publish, simply do:
+
+```bash
+npm run build
+npm publish
+```
+
+That's it!
+
\ No newline at end of file
diff --git a/packages/schematics/schematics/blank/project-files/__dot__gitignore b/packages/schematics/schematics/blank/project-files/__dot__gitignore
new file mode 100644
index 0000000000..82677b5884
--- /dev/null
+++ b/packages/schematics/schematics/blank/project-files/__dot__gitignore
@@ -0,0 +1,18 @@
+# Outputs
+src/**/*.js
+src/**/*.js.map
+src/**/*.d.ts
+
+# IDEs
+.idea/
+jsconfig.json
+.vscode/
+
+# Misc
+node_modules/
+npm-debug.log*
+yarn-error.log*
+
+# Mac OSX Finder files.
+**/.DS_Store
+.DS_Store
diff --git a/packages/schematics/schematics/blank/project-files/package.json b/packages/schematics/schematics/blank/project-files/package.json
new file mode 100644
index 0000000000..d7ee703dfa
--- /dev/null
+++ b/packages/schematics/schematics/blank/project-files/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "<%= dasherize(name) %>",
+ "version": "0.0.0",
+ "description": "A blank schematics",
+ "scripts": {
+ "build": "tsc -p tsconfig.json",
+ "test": "npm run build && jasmine **/*_spec.js"
+ },
+ "keywords": [
+ "schematics"
+ ],
+ "author": "<%= author %>",
+ "license": "MIT",
+ "schematics": "./src/collection.json",
+ "dependencies": {
+ "@angular-devkit/core": "^<%= coreVersion %>",
+ "@angular-devkit/schematics": "^<%= schematicsVersion %>",
+ "@types/jasmine": "^2.6.0",
+ "@types/node": "^8.0.31",
+ "jasmine": "^2.8.0",
+ "typescript": "^2.5.2"
+ }
+}
diff --git a/packages/schematics/schematics/blank/project-files/src/collection.json b/packages/schematics/schematics/blank/project-files/src/collection.json
new file mode 100644
index 0000000000..272c195ad4
--- /dev/null
+++ b/packages/schematics/schematics/blank/project-files/src/collection.json
@@ -0,0 +1,5 @@
+{
+ "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
+ "schematics": {
+ }
+}
diff --git a/packages/schematics/schematics/blank/project-files/tsconfig.json b/packages/schematics/schematics/blank/project-files/tsconfig.json
new file mode 100644
index 0000000000..e93f82906a
--- /dev/null
+++ b/packages/schematics/schematics/blank/project-files/tsconfig.json
@@ -0,0 +1,33 @@
+{
+ "compilerOptions": {
+ "baseUrl": "tsconfig",
+ "lib": [
+ "es2017",
+ "dom"
+ ],
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "noEmitOnError": true,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitAny": true,
+ "noImplicitThis": true,
+ "noUnusedParameters": true,
+ "noUnusedLocals": true,
+ "rootDir": "src/",
+ "skipDefaultLibCheck": true,
+ "skipLibCheck": true,
+ "sourceMap": true,
+ "strictNullChecks": true,
+ "target": "es6",
+ "types": [
+ "jasmine",
+ "node"
+ ]
+ },
+ "include": [
+ "src/**/*"
+ ],
+ "exclude": [
+ "src/*/files/**/*"
+ ]
+}
diff --git a/packages/schematics/schematics/blank/schema.d.ts b/packages/schematics/schematics/blank/schema.d.ts
new file mode 100644
index 0000000000..2413212c1b
--- /dev/null
+++ b/packages/schematics/schematics/blank/schema.d.ts
@@ -0,0 +1,18 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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
+ */
+
+export interface Schema {
+ /**
+ * The package name for the new schematic.
+ */
+ name: string;
+ /**
+ * Author for the new schematic.
+ */
+ author?: string;
+}
diff --git a/packages/schematics/schematics/blank/schema.json b/packages/schematics/schematics/blank/schema.json
new file mode 100644
index 0000000000..0fa45450e2
--- /dev/null
+++ b/packages/schematics/schematics/blank/schema.json
@@ -0,0 +1,19 @@
+{
+ "$schema": "http://json-schema.org/schema",
+ "id": "SchematicsSchematicSchema",
+ "title": "Schematic Options Schema",
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "The package name for the new schematic."
+ },
+ "author": {
+ "type": "string",
+ "description": "Author for the new schematic."
+ }
+ },
+ "required": [
+ "name"
+ ]
+}
diff --git a/packages/schematics/schematics/blank/schematic-files/src/__name@dasherize__/index.ts b/packages/schematics/schematics/blank/schematic-files/src/__name@dasherize__/index.ts
new file mode 100644
index 0000000000..0edb05fbe4
--- /dev/null
+++ b/packages/schematics/schematics/blank/schematic-files/src/__name@dasherize__/index.ts
@@ -0,0 +1,10 @@
+import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
+
+
+// You don't have to export the function as default. You can also have more than one rule factory
+// per file.
+export function <%= camelize(name) %>(options: any): Rule {
+ return (tree: Tree, _context: SchematicContext) => {
+ return tree;
+ };
+}
diff --git a/packages/schematics/schematics/blank/schematic-files/src/__name@dasherize__/index_spec.ts b/packages/schematics/schematics/blank/schematic-files/src/__name@dasherize__/index_spec.ts
new file mode 100644
index 0000000000..5a2becd0ff
--- /dev/null
+++ b/packages/schematics/schematics/blank/schematic-files/src/__name@dasherize__/index_spec.ts
@@ -0,0 +1,16 @@
+import { Tree } from '@angular-devkit/schematics';
+import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
+import * as path from 'path';
+
+
+const collectionPath = path.join(__dirname, '../collection.json');
+
+
+describe('<%= dasherize(name) %>', () => {
+ it('works', () => {
+ const runner = new SchematicTestRunner('schematics', collectionPath);
+ const tree = runner.runSchematic('my-schematic', {}, Tree.empty());
+
+ expect(tree.files).toEqual([]);
+ });
+});
diff --git a/packages/schematics/schematics/collection.json b/packages/schematics/schematics/collection.json
index e913df41d9..bc730f55ad 100644
--- a/packages/schematics/schematics/collection.json
+++ b/packages/schematics/schematics/collection.json
@@ -1,5 +1,10 @@
{
"schematics": {
+ "blank": {
+ "factory": "./blank/factory",
+ "schema": "./blank/schema.json",
+ "description": "Create an empty schematic project or add a blank schematic to the current project."
+ },
"schematic": {
"factory": "./schematic/factory",
"schema": "./schematic/schema.json",
From f0039a947662efb7fb87f7201c68a1602a8d9e77 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Fri, 17 Nov 2017 17:46:35 -0800
Subject: [PATCH 011/807] feat(@angular-devkit/schematics): move default
collection to @schematics/schematics
---
packages/angular_devkit/schematics/bin/schematics.ts | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/packages/angular_devkit/schematics/bin/schematics.ts b/packages/angular_devkit/schematics/bin/schematics.ts
index 44e4d78735..79a9e64e7a 100644
--- a/packages/angular_devkit/schematics/bin/schematics.ts
+++ b/packages/angular_devkit/schematics/bin/schematics.ts
@@ -61,8 +61,8 @@ function usage(exitCode = 0): never {
* return `{collection: 'collection-name', schematic: 'schematic-name'}`, or it will error out
* and show usage.
*
- * In the case where a collection name isn't part of the argument, the default is to use this
- * package (@schematics/angular) as the collection.
+ * In the case where a collection name isn't part of the argument, the default is to use the
+ * schematics package (@schematics/schematics) as the collection.
*
* This logic is entirely up to the tooling.
*
@@ -70,7 +70,7 @@ function usage(exitCode = 0): never {
* @return {{collection: string, schematic: (string)}}
*/
function parseSchematicName(str: string | null): { collection: string, schematic: string } {
- let collection = '@schematics/angular';
+ let collection = '@schematics/schematics';
if (!str || str === null) {
usage(1);
From 51e773aee80fe541b95f0e1233bac8ce7f756712 Mon Sep 17 00:00:00 2001
From: Mike Brocchi
Date: Thu, 28 Sep 2017 16:27:01 -0400
Subject: [PATCH 012/807] feat(@schematics/angular): Add universal schematic
---
packages/schematics/angular/collection.json | 5 +
.../__appDir__/__rootModuleFileName__ | 14 +
.../__main@stripTsExtension__.ts | 1 +
.../__sourceDir__/__tsconfigFileName__.json | 16 +
.../schematics/angular/universal/index.ts | 203 ++++++++
.../angular/universal/index_spec.ts | 110 +++++
.../schematics/angular/universal/schema.d.ts | 63 +++
.../schematics/angular/universal/schema.json | 78 +++
.../schematics/angular/utility/ast-utils.ts | 14 +
packages/schematics/angular/utility/config.ts | 461 ++++++++++++++++++
.../angular/utility/ng-ast-utils.ts | 45 ++
11 files changed, 1010 insertions(+)
create mode 100644 packages/schematics/angular/universal/files/__sourceDir__/__appDir__/__rootModuleFileName__
create mode 100644 packages/schematics/angular/universal/files/__sourceDir__/__main@stripTsExtension__.ts
create mode 100644 packages/schematics/angular/universal/files/__sourceDir__/__tsconfigFileName__.json
create mode 100644 packages/schematics/angular/universal/index.ts
create mode 100644 packages/schematics/angular/universal/index_spec.ts
create mode 100644 packages/schematics/angular/universal/schema.d.ts
create mode 100644 packages/schematics/angular/universal/schema.json
create mode 100644 packages/schematics/angular/utility/config.ts
create mode 100644 packages/schematics/angular/utility/ng-ast-utils.ts
diff --git a/packages/schematics/angular/collection.json b/packages/schematics/angular/collection.json
index e22d9ec5a4..3b6abcf597 100644
--- a/packages/schematics/angular/collection.json
+++ b/packages/schematics/angular/collection.json
@@ -58,6 +58,11 @@
"factory": "./service",
"description": "Create an Angular service.",
"schema": "./service/schema.json"
+ },
+ "universal": {
+ "factory": "./universal",
+ "description": "Create an Angular universal app.",
+ "schema": "./universal/schema.json"
}
}
}
diff --git a/packages/schematics/angular/universal/files/__sourceDir__/__appDir__/__rootModuleFileName__ b/packages/schematics/angular/universal/files/__sourceDir__/__appDir__/__rootModuleFileName__
new file mode 100644
index 0000000000..af9a56e17c
--- /dev/null
+++ b/packages/schematics/angular/universal/files/__sourceDir__/__appDir__/__rootModuleFileName__
@@ -0,0 +1,14 @@
+import { NgModule } from '@angular/core';
+import { ServerModule } from '@angular/platform-server';
+
+import { AppModule } from './app.module';
+import { AppComponent } from './app.component';
+
+@NgModule({
+ imports: [
+ AppModule,
+ ServerModule,
+ ],
+ bootstrap: [AppComponent],
+})
+export class <%= rootModuleClassName %> {}
diff --git a/packages/schematics/angular/universal/files/__sourceDir__/__main@stripTsExtension__.ts b/packages/schematics/angular/universal/files/__sourceDir__/__main@stripTsExtension__.ts
new file mode 100644
index 0000000000..0d766835a2
--- /dev/null
+++ b/packages/schematics/angular/universal/files/__sourceDir__/__main@stripTsExtension__.ts
@@ -0,0 +1 @@
+export { <%= rootModuleClassName %> } from './<%= appDir %>/<%= stripTsExtension(rootModuleFileName) %>';
diff --git a/packages/schematics/angular/universal/files/__sourceDir__/__tsconfigFileName__.json b/packages/schematics/angular/universal/files/__sourceDir__/__tsconfigFileName__.json
new file mode 100644
index 0000000000..afd34261c0
--- /dev/null
+++ b/packages/schematics/angular/universal/files/__sourceDir__/__tsconfigFileName__.json
@@ -0,0 +1,16 @@
+{
+ "extends": "../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../<%= outDir %>",
+ "baseUrl": "./",
+ "module": "commonjs",
+ "types": []
+ },
+ "exclude": [
+ "test.ts",
+ "**/*.spec.ts"
+ ],
+ "angularCompilerOptions": {
+ "entryModule": "<%= appDir %>/<%= stripTsExtension(rootModuleFileName) %>#<%= rootModuleClassName %>"
+ }
+}
diff --git a/packages/schematics/angular/universal/index.ts b/packages/schematics/angular/universal/index.ts
new file mode 100644
index 0000000000..8111658a79
--- /dev/null
+++ b/packages/schematics/angular/universal/index.ts
@@ -0,0 +1,203 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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 { normalize } from '@angular-devkit/core';
+import {
+ Rule,
+ SchematicContext,
+ SchematicsException,
+ Tree,
+ apply,
+ chain,
+ mergeWith,
+ template,
+ url,
+} from '@angular-devkit/schematics';
+import 'rxjs/add/operator/merge';
+import * as ts from 'typescript';
+import * as stringUtils from '../strings';
+import { findNode, getDecoratorMetadata, getSourceNodes } from '../utility/ast-utils';
+import { InsertChange } from '../utility/change';
+import { AppConfig, getAppFromConfig, getConfig } from '../utility/config';
+import { findBootstrapModuleCall } from '../utility/ng-ast-utils';
+import { Schema as UniversalOptions } from './schema';
+
+
+function updateConfigFile(options: UniversalOptions): Rule {
+ return (host: Tree) => {
+ const config = getConfig(host);
+ const clientApp = getAppFromConfig(config, options.clientApp);
+ if (clientApp === null) {
+ throw new SchematicsException('Client app not found.');
+ }
+ options.test = options.test || clientApp.test;
+ const serverApp: AppConfig = {
+ ...clientApp,
+ platform: 'server',
+ root: options.root,
+ outDir: options.outDir,
+ index: options.index,
+ main: options.main,
+ test: options.test,
+ tsconfig: options.tsconfigFileName,
+ testTsconfig: options.testTsconfigFileName,
+ };
+ if (!config.apps) {
+ config.apps = [];
+ }
+ config.apps.push(serverApp);
+
+ host.overwrite('/.angular-cli.json', JSON.stringify(config, null, 2));
+
+ return host;
+ };
+}
+
+function findBootstrapModulePath(host: Tree, mainPath: string): string {
+ const bootstrapCall = findBootstrapModuleCall(host, mainPath);
+ if (!bootstrapCall) {
+ throw new SchematicsException('Bootstrap call not found');
+ }
+
+ const bootstrapModule = bootstrapCall.arguments[0];
+
+ const mainBuffer = host.read(mainPath);
+ if (!mainBuffer) {
+ throw new SchematicsException(`Client app main file (${mainPath}) not found`);
+ }
+ const mainText = mainBuffer.toString('utf-8');
+ const source = ts.createSourceFile(mainPath, mainText, ts.ScriptTarget.Latest, true);
+ const allNodes = getSourceNodes(source);
+ const bootstrapModuleRelativePath = allNodes
+ .filter(node => node.kind === ts.SyntaxKind.ImportDeclaration)
+ .filter(imp => {
+ return findNode(imp, ts.SyntaxKind.Identifier, bootstrapModule.getText());
+ })
+ .map((imp: ts.ImportDeclaration) => {
+ const modulePathStringLiteral = imp.moduleSpecifier;
+
+ return modulePathStringLiteral.text;
+ })[0];
+
+ return bootstrapModuleRelativePath;
+}
+
+function findBrowserModuleImport(host: Tree, modulePath: string): ts.Node {
+ const moduleBuffer = host.read(modulePath);
+ if (!moduleBuffer) {
+ throw new SchematicsException(`Module file (${modulePath}) not found`);
+ }
+ const moduleFileText = moduleBuffer.toString('utf-8');
+
+ const source = ts.createSourceFile(modulePath, moduleFileText, ts.ScriptTarget.Latest, true);
+
+ const decoratorMetadata = getDecoratorMetadata(source, 'NgModule', '@angular/core')[0];
+ const browserModuleNode = findNode(decoratorMetadata, ts.SyntaxKind.Identifier, 'BrowserModule');
+
+ if (browserModuleNode === null) {
+ throw new SchematicsException(`Cannot find BrowserModule import in ${modulePath}`);
+ }
+
+ return browserModuleNode;
+}
+
+function wrapBootstrapCall(options: UniversalOptions): Rule {
+ return (host: Tree) => {
+ const config = getConfig(host);
+ const clientApp = getAppFromConfig(config, options.clientApp);
+ if (clientApp === null) {
+ throw new SchematicsException('Client app not found.');
+ }
+ const mainPath = normalize(`/${clientApp.root}/${clientApp.main}`);
+ let bootstrapCall: ts.Node | null = findBootstrapModuleCall(host, mainPath);
+ if (bootstrapCall === null) {
+ throw new SchematicsException('Bootstrap module not found.');
+ }
+
+ let bootstrapCallExpression: ts.Node | null = null;
+ let currentCall = bootstrapCall;
+ while (bootstrapCallExpression === null && currentCall.parent) {
+ currentCall = currentCall.parent;
+ if (currentCall.kind === ts.SyntaxKind.ExpressionStatement) {
+ bootstrapCallExpression = currentCall;
+ }
+ }
+ bootstrapCall = currentCall;
+
+ const recorder = host.beginUpdate(mainPath);
+ const beforeText = `document.addEventListener('DOMContentLoaded', () => {\n `;
+ const afterText = `\n});`;
+ recorder.insertLeft(bootstrapCall.getStart(), beforeText);
+ recorder.insertRight(bootstrapCall.getEnd(), afterText);
+ host.commitUpdate(recorder);
+ };
+}
+
+function addServerTransition(options: UniversalOptions): Rule {
+ return (host: Tree) => {
+ const config = getConfig(host);
+ const clientApp = getAppFromConfig(config, options.clientApp);
+ if (clientApp === null) {
+ throw new SchematicsException('Client app not found.');
+ }
+ const mainPath = normalize(`/${clientApp.root}/${clientApp.main}`);
+
+ const bootstrapModuleRelativePath = findBootstrapModulePath(host, mainPath);
+ const bootstrapModulePath = normalize(`/${clientApp.root}/${bootstrapModuleRelativePath}.ts`);
+
+ const browserModuleImport = findBrowserModuleImport(host, bootstrapModulePath);
+ const appId = options.appId;
+ const transitionCall = `.withServerTransition({ appId: '${appId}' })`;
+ const position = browserModuleImport.pos + browserModuleImport.getFullText().length;
+ const transitionCallChange = new InsertChange(
+ bootstrapModulePath, position, transitionCall);
+
+ const transitionCallRecorder = host.beginUpdate(bootstrapModulePath);
+ transitionCallRecorder.insertLeft(transitionCallChange.pos, transitionCallChange.toAdd);
+ host.commitUpdate(transitionCallRecorder);
+ };
+}
+
+function addDependencies(): Rule {
+ return (host: Tree) => {
+ const pkgPath = '/package.json';
+ const buffer = host.read(pkgPath);
+ if (buffer === null) {
+ throw new SchematicsException('Could not find package.json');
+ }
+
+ const pkg = JSON.parse(buffer.toString());
+
+ const ngCoreVersion = Object.keys(pkg.dependencies)
+ .filter((key: string) => key === '@angular/core')[0];
+ pkg.dependencies['@angular/platform-server'] = ngCoreVersion;
+
+ host.overwrite(pkgPath, JSON.stringify(pkg, null, 2));
+
+ return host;
+ };
+}
+
+export default function (options: UniversalOptions): Rule {
+ return (host: Tree, context: SchematicContext) => {
+ const templateSource = apply(url('./files'), [
+ template({
+ ...stringUtils,
+ ...options as object,
+ stripTsExtension: (s: string) => { return s.replace(/\.ts$/, ''); },
+ }),
+ ]);
+
+ return chain([
+ mergeWith(templateSource),
+ addDependencies(),
+ updateConfigFile(options),
+ wrapBootstrapCall(options),
+ addServerTransition(options),
+ ])(host, context);
+ };
+}
diff --git a/packages/schematics/angular/universal/index_spec.ts b/packages/schematics/angular/universal/index_spec.ts
new file mode 100644
index 0000000000..f1355a9a8b
--- /dev/null
+++ b/packages/schematics/angular/universal/index_spec.ts
@@ -0,0 +1,110 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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 } from '@angular-devkit/schematics';
+import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
+import * as path from 'path';
+import { Schema as ApplicationOptions } from '../application/schema';
+import { Schema as UniversalOptions } from './schema';
+
+
+describe('Universal Schematic', () => {
+ const schematicRunner = new SchematicTestRunner(
+ '@schematics/angular',
+ path.join(__dirname, '../collection.json'),
+ );
+ const defaultOptions: UniversalOptions = {
+ name: 'foo',
+ };
+
+ let appTree: Tree;
+
+ beforeEach(() => {
+ const appOptions: ApplicationOptions = {
+ directory: '',
+ name: 'app',
+ path: 'src',
+ prefix: '',
+ sourceDir: 'src',
+ inlineStyle: false,
+ inlineTemplate: false,
+ viewEncapsulation: 'None',
+ changeDetection: 'Default',
+ version: '1.2.3',
+ routing: false,
+ style: 'css',
+ skipTests: false,
+ minimal: false,
+ };
+ appTree = schematicRunner.runSchematic('application', appOptions);
+ });
+
+ it('should create a root module file', () => {
+ const tree = schematicRunner.runSchematic('universal', defaultOptions, appTree);
+ const filePath = '/src/app/app.server.module.ts';
+ const file = tree.files.filter(f => f === filePath)[0];
+ expect(file).toBeDefined();
+ });
+
+ it('should create a main file', () => {
+ const tree = schematicRunner.runSchematic('universal', defaultOptions, appTree);
+ const filePath = '/src/main.server.ts';
+ const file = tree.files.filter(f => f === filePath)[0];
+ expect(file).toBeDefined();
+ const contents = tree.read(filePath);
+ expect(contents).toMatch(/export { AppServerModule } from '\.\/app\/app\.server\.module'/);
+ });
+
+ it('should create a tsconfig file', () => {
+ const tree = schematicRunner.runSchematic('universal', defaultOptions, appTree);
+ const filePath = '/src/tsconfig.server.json';
+ const file = tree.files.filter(f => f === filePath)[0];
+ expect(file).toBeDefined();
+ const contents = tree.read(filePath);
+ expect(contents).toMatch(/\"outDir\": \"\.\.\/dist-server\/\"/);
+ });
+
+ it('should add dependency: @angular/platform-server', () => {
+ const tree = schematicRunner.runSchematic('universal', defaultOptions, appTree);
+ const filePath = '/package.json';
+ const contents = tree.read(filePath);
+ expect(contents).toMatch(/\"@angular\/platform-server\": \"/);
+ });
+
+ it('should update .angular-cli.json with a server app', () => {
+ const tree = schematicRunner.runSchematic('universal', defaultOptions, appTree);
+ const filePath = '/.angular-cli.json';
+ const contents = tree.read(filePath) || new Buffer('');
+
+ const config = JSON.parse(contents.toString());
+ expect(config.apps.length).toEqual(2);
+ const app = config.apps[1];
+ expect(app.platform).toEqual('server');
+ expect(app.root).toEqual('src');
+ expect(app.outDir).toEqual('dist-server/');
+ expect(app.index).toEqual('index.html');
+ expect(app.main).toEqual('main.server.ts');
+ expect(app.test).toEqual('test.ts');
+ expect(app.tsconfig).toEqual('tsconfig.server');
+ expect(app.testTsconfig).toEqual('tsconfig.spec');
+ expect(app.environmentSource).toEqual('environments/environment.ts');
+ });
+
+ it('should add a server transition to BrowerModule import', () => {
+ const tree = schematicRunner.runSchematic('universal', defaultOptions, appTree);
+ const filePath = '/src/app/app.module.ts';
+ const contents = tree.read(filePath);
+ expect(contents).toMatch(/BrowserModule\.withServerTransition\({ appId: 'serverApp' }\)/);
+ });
+
+ it('should wrap the bootstrap call in a DOMContentLoaded event handler', () => {
+ const tree = schematicRunner.runSchematic('universal', defaultOptions, appTree);
+ const filePath = '/src/main.ts';
+ const contents = tree.read(filePath);
+ expect(contents).toMatch(/document.addEventListener\('DOMContentLoaded', \(\) => {/);
+ });
+});
diff --git a/packages/schematics/angular/universal/schema.d.ts b/packages/schematics/angular/universal/schema.d.ts
new file mode 100644
index 0000000000..86fc582004
--- /dev/null
+++ b/packages/schematics/angular/universal/schema.d.ts
@@ -0,0 +1,63 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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
+ */
+
+export interface Schema {
+ /**
+ * Name of the universal app
+ */
+ name?: string;
+ /**
+ * Name or index of related client app.
+ */
+ clientApp?: string;
+ /**
+ * The appId to use withServerTransition.
+ */
+ appId?: string;
+ /**
+ * The output directory for build results.
+ */
+ outDir?: string;
+ /**
+ * The root directory of the app.
+ */
+ root?: string;
+ /**
+ * Name of the index file
+ */
+ index?: string;
+ /**
+ * The name of the main entry-point file.
+ */
+ main?: string;
+ /**
+ * The name of the test entry-point file.
+ */
+ test?: string;
+ /**
+ * The name of the TypeScript configuration file.
+ */
+ tsconfigFileName?: string;
+ /**
+ * The name of the TypeScript configuration file for tests.
+ */
+ testTsconfigFileName?: string;
+ /**
+ * The name of the applicatino directory.
+ */
+ appDir?: string;
+ /**
+ * The name of the root module file
+ */
+ rootModuleFileName?: string;
+ /**
+ * The name of the root module class.
+ */
+ rootModuleClassName?: string;
+ sourceDir?: string;
+}
diff --git a/packages/schematics/angular/universal/schema.json b/packages/schematics/angular/universal/schema.json
new file mode 100644
index 0000000000..fea4be93ed
--- /dev/null
+++ b/packages/schematics/angular/universal/schema.json
@@ -0,0 +1,78 @@
+{
+ "$schema": "http://json-schema.org/schema",
+ "id": "SchematicsAngularUniversalApp",
+ "title": "Angular Universal App Options Schema",
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string",
+ "description": "Name of the universal app"
+ },
+ "clientApp": {
+ "type": "string",
+ "description": "Name or index of related client app.",
+ "default": "0"
+ },
+ "appId": {
+ "type": "string",
+ "description": "The appId to use withServerTransition.",
+ "default": "serverApp"
+ },
+ "outDir": {
+ "type": "string",
+ "description": "The output directory for build results.",
+ "default": "dist-server/"
+ },
+ "root": {
+ "type": "string",
+ "description": "The root directory of the app.",
+ "default": "src"
+ },
+ "index": {
+ "type": "string",
+ "description": "Name of the index file",
+ "default": "index.html"
+ },
+ "main": {
+ "type": "string",
+ "description": "The name of the main entry-point file.",
+ "default": "main.server.ts"
+ },
+ "test": {
+ "type": "string",
+ "description": "The name of the test entry-point file."
+ },
+ "tsconfigFileName": {
+ "type": "string",
+ "default": "tsconfig.server",
+ "description": "The name of the TypeScript configuration file."
+ },
+ "testTsconfigFileName": {
+ "type": "string",
+ "description": "The name of the TypeScript configuration file for tests.",
+ "default": "tsconfig.spec"
+ },
+ "appDir": {
+ "type": "string",
+ "description": "The name of the applicatino directory.",
+ "default": "app"
+ },
+ "rootModuleFileName": {
+ "type": "string",
+ "description": "The name of the root module file",
+ "default": "app.server.module.ts"
+ },
+ "rootModuleClassName": {
+ "type": "string",
+ "description": "The name of the root module class.",
+ "default": "AppServerModule"
+ },
+ "sourceDir": {
+ "type": "string",
+ "default": "src",
+ "alias": "sd"
+ }
+ },
+ "required": [
+ ]
+}
diff --git a/packages/schematics/angular/utility/ast-utils.ts b/packages/schematics/angular/utility/ast-utils.ts
index 99f50af774..ec08ee6081 100644
--- a/packages/schematics/angular/utility/ast-utils.ts
+++ b/packages/schematics/angular/utility/ast-utils.ts
@@ -69,6 +69,20 @@ export function getSourceNodes(sourceFile: ts.SourceFile): ts.Node[] {
return result;
}
+export function findNode(node: ts.Node, kind: ts.SyntaxKind, text: string): ts.Node | null {
+ if (node.kind === kind && node.getText() === text) {
+ // throw new Error(node.getText());
+ return node;
+ }
+
+ let foundNode: ts.Node | null = null;
+ ts.forEachChild(node, childNode => {
+ foundNode = foundNode || findNode(childNode, kind, text);
+ });
+
+ return foundNode;
+}
+
/**
* Helper for sorting nodes.
diff --git a/packages/schematics/angular/utility/config.ts b/packages/schematics/angular/utility/config.ts
new file mode 100644
index 0000000000..2c626bbfb2
--- /dev/null
+++ b/packages/schematics/angular/utility/config.ts
@@ -0,0 +1,461 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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 { SchematicsException, Tree } from '@angular-devkit/schematics';
+
+
+// The interfaces below are generated from the Angular CLI configuration schema
+// https://github.com/angular/angular-cli/blob/master/packages/@angular/cli/lib/config/schema.json
+export interface AppConfig {
+ /**
+ * Name of the app.
+ */
+ name?: string;
+ /**
+ * Directory where app files are placed.
+ */
+ appRoot?: string;
+ /**
+ * The root directory of the app.
+ */
+ root?: string;
+ /**
+ * The output directory for build results.
+ */
+ outDir?: string;
+ /**
+ * List of application assets.
+ */
+ assets?: (string | {
+ /**
+ * The pattern to match.
+ */
+ glob?: string;
+ /**
+ * The dir to search within.
+ */
+ input?: string;
+ /**
+ * The output path (relative to the outDir).
+ */
+ output?: string;
+ })[];
+ /**
+ * URL where files will be deployed.
+ */
+ deployUrl?: string;
+ /**
+ * Base url for the application being built.
+ */
+ baseHref?: string;
+ /**
+ * The runtime platform of the app.
+ */
+ platform?: ('browser' | 'server');
+ /**
+ * The name of the start HTML file.
+ */
+ index?: string;
+ /**
+ * The name of the main entry-point file.
+ */
+ main?: string;
+ /**
+ * The name of the polyfills file.
+ */
+ polyfills?: string;
+ /**
+ * The name of the test entry-point file.
+ */
+ test?: string;
+ /**
+ * The name of the TypeScript configuration file.
+ */
+ tsconfig?: string;
+ /**
+ * The name of the TypeScript configuration file for unit tests.
+ */
+ testTsconfig?: string;
+ /**
+ * The prefix to apply to generated selectors.
+ */
+ prefix?: string;
+ /**
+ * Experimental support for a service worker from @angular/service-worker.
+ */
+ serviceWorker?: boolean;
+ /**
+ * Global styles to be included in the build.
+ */
+ styles?: (string | {
+ input?: string;
+ [name: string]: any; // tslint:disable-line:no-any
+ })[];
+ /**
+ * Options to pass to style preprocessors
+ */
+ stylePreprocessorOptions?: {
+ /**
+ * Paths to include. Paths will be resolved to project root.
+ */
+ includePaths?: string[];
+ };
+ /**
+ * Global scripts to be included in the build.
+ */
+ scripts?: (string | {
+ input: string;
+ [name: string]: any; // tslint:disable-line:no-any
+ })[];
+ /**
+ * Source file for environment config.
+ */
+ environmentSource?: string;
+ /**
+ * Name and corresponding file for environment config.
+ */
+ environments?: {
+ [name: string]: any; // tslint:disable-line:no-any
+ };
+}
+
+export interface CliConfig {
+ $schema?: string;
+ /**
+ * The global configuration of the project.
+ */
+ project?: {
+ /**
+ * The name of the project.
+ */
+ name?: string;
+ /**
+ * Whether or not this project was ejected.
+ */
+ ejected?: boolean;
+ };
+ /**
+ * Properties of the different applications in this project.
+ */
+ apps?: AppConfig[];
+ /**
+ * Configuration for end-to-end tests.
+ */
+ e2e?: {
+ protractor?: {
+ /**
+ * Path to the config file.
+ */
+ config?: string;
+ };
+ };
+ /**
+ * Properties to be passed to TSLint.
+ */
+ lint?: {
+ /**
+ * File glob(s) to lint.
+ */
+ files?: (string | string[]);
+ /**
+ * Location of the tsconfig.json project file.
+ * Will also use as files to lint if 'files' property not present.
+ */
+ project: string;
+ /**
+ * Location of the tslint.json configuration.
+ */
+ tslintConfig?: string;
+ /**
+ * File glob(s) to ignore.
+ */
+ exclude?: (string | string[]);
+ }[];
+ /**
+ * Configuration for unit tests.
+ */
+ test?: {
+ karma?: {
+ /**
+ * Path to the karma config file.
+ */
+ config?: string;
+ };
+ codeCoverage?: {
+ /**
+ * Globs to exclude from code coverage.
+ */
+ exclude?: string[];
+ };
+ };
+ /**
+ * Specify the default values for generating.
+ */
+ defaults?: {
+ /**
+ * The file extension to be used for style files.
+ */
+ styleExt?: string;
+ /**
+ * How often to check for file updates.
+ */
+ poll?: number;
+ /**
+ * Use lint to fix files after generation
+ */
+ lintFix?: boolean;
+ /**
+ * Options for generating a class.
+ */
+ class?: {
+ /**
+ * Specifies if a spec file is generated.
+ */
+ spec?: boolean;
+ };
+ /**
+ * Options for generating a component.
+ */
+ component?: {
+ /**
+ * Flag to indicate if a dir is created.
+ */
+ flat?: boolean;
+ /**
+ * Specifies if a spec file is generated.
+ */
+ spec?: boolean;
+ /**
+ * Specifies if the style will be in the ts file.
+ */
+ inlineStyle?: boolean;
+ /**
+ * Specifies if the template will be in the ts file.
+ */
+ inlineTemplate?: boolean;
+ /**
+ * Specifies the view encapsulation strategy.
+ */
+ viewEncapsulation?: ('Emulated' | 'Native' | 'None');
+ /**
+ * Specifies the change detection strategy.
+ */
+ changeDetection?: ('Default' | 'OnPush');
+ };
+ /**
+ * Options for generating a directive.
+ */
+ directive?: {
+ /**
+ * Flag to indicate if a dir is created.
+ */
+ flat?: boolean;
+ /**
+ * Specifies if a spec file is generated.
+ */
+ spec?: boolean;
+ };
+ /**
+ * Options for generating a guard.
+ */
+ guard?: {
+ /**
+ * Flag to indicate if a dir is created.
+ */
+ flat?: boolean;
+ /**
+ * Specifies if a spec file is generated.
+ */
+ spec?: boolean;
+ };
+ /**
+ * Options for generating an interface.
+ */
+ interface?: {
+ /**
+ * Prefix to apply to interface names. (i.e. I)
+ */
+ prefix?: string;
+ };
+ /**
+ * Options for generating a module.
+ */
+ module?: {
+ /**
+ * Flag to indicate if a dir is created.
+ */
+ flat?: boolean;
+ /**
+ * Specifies if a spec file is generated.
+ */
+ spec?: boolean;
+ };
+ /**
+ * Options for generating a pipe.
+ */
+ pipe?: {
+ /**
+ * Flag to indicate if a dir is created.
+ */
+ flat?: boolean;
+ /**
+ * Specifies if a spec file is generated.
+ */
+ spec?: boolean;
+ };
+ /**
+ * Options for generating a service.
+ */
+ service?: {
+ /**
+ * Flag to indicate if a dir is created.
+ */
+ flat?: boolean;
+ /**
+ * Specifies if a spec file is generated.
+ */
+ spec?: boolean;
+ };
+ /**
+ * Properties to be passed to the build command.
+ */
+ build?: {
+ /**
+ * Output sourcemaps.
+ */
+ sourcemaps?: boolean;
+ /**
+ * Base url for the application being built.
+ */
+ baseHref?: string;
+ /**
+ * The ssl key used by the server.
+ */
+ progress?: boolean;
+ /**
+ * Enable and define the file watching poll time period (milliseconds).
+ */
+ poll?: number;
+ /**
+ * Delete output path before build.
+ */
+ deleteOutputPath?: boolean;
+ /**
+ * Do not use the real path when resolving modules.
+ */
+ preserveSymlinks?: boolean;
+ /**
+ * Show circular dependency warnings on builds.
+ */
+ showCircularDependencies?: boolean;
+ /**
+ * Use a separate bundle containing code used across multiple bundles.
+ */
+ commonChunk?: boolean;
+ /**
+ * Use file name for lazy loaded chunks.
+ */
+ namedChunks?: boolean;
+ };
+ /**
+ * Properties to be passed to the serve command.
+ */
+ serve?: {
+ /**
+ * The port the application will be served on.
+ */
+ port?: number;
+ /**
+ * The host the application will be served on.
+ */
+ host?: string;
+ /**
+ * Enables ssl for the application.
+ */
+ ssl?: boolean;
+ /**
+ * The ssl key used by the server.
+ */
+ sslKey?: string;
+ /**
+ * The ssl certificate used by the server.
+ */
+ sslCert?: string;
+ /**
+ * Proxy configuration file.
+ */
+ proxyConfig?: string;
+ };
+ /**
+ * Properties about schematics.
+ */
+ schematics?: {
+ /**
+ * The schematics collection to use.
+ */
+ collection?: string;
+ /**
+ * The new app schematic.
+ */
+ newApp?: string;
+ };
+ };
+ /**
+ * Specify which package manager tool to use.
+ */
+ packageManager?: ('npm' | 'cnpm' | 'yarn' | 'default');
+ /**
+ * Allow people to disable console warnings.
+ */
+ warnings?: {
+ /**
+ * Show a warning when the user enabled the --hmr option.
+ */
+ hmrWarning?: boolean;
+ /**
+ * Show a warning when the node version is incompatible.
+ */
+ nodeDeprecation?: boolean;
+ /**
+ * Show a warning when the user installed angular-cli.
+ */
+ packageDeprecation?: boolean;
+ /**
+ * Show a warning when the global version is newer than the local one.
+ */
+ versionMismatch?: boolean;
+ /**
+ * Show a warning when the TypeScript version is incompatible
+ */
+ typescriptMismatch?: boolean;
+ };
+}
+
+export const configPath = '/.angular-cli.json';
+
+export function getConfig(host: Tree): CliConfig {
+ const configBuffer = host.read(configPath);
+ if (configBuffer === null) {
+ throw new SchematicsException('Could not find .angular-cli.json');
+ }
+
+ const config = JSON.parse(configBuffer.toString());
+
+ return config;
+}
+
+export function getAppFromConfig(config: CliConfig, appIndexOrName = '0'): AppConfig | null {
+ if (!config.apps) {
+ return null;
+ }
+
+ if (parseInt(appIndexOrName) >= 0) {
+ return config.apps[parseInt(appIndexOrName)];
+ }
+
+ return config.apps.filter((app) => app.name === appIndexOrName)[0];
+}
diff --git a/packages/schematics/angular/utility/ng-ast-utils.ts b/packages/schematics/angular/utility/ng-ast-utils.ts
new file mode 100644
index 0000000000..e3351cd39a
--- /dev/null
+++ b/packages/schematics/angular/utility/ng-ast-utils.ts
@@ -0,0 +1,45 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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 { SchematicsException, Tree } from '@angular-devkit/schematics';
+import * as ts from 'typescript';
+import { findNode, getSourceNodes } from '../utility/ast-utils';
+
+export function findBootstrapModuleCall(host: Tree, mainPath: string): ts.CallExpression | null {
+ const mainBuffer = host.read(mainPath);
+ if (!mainBuffer) {
+ throw new SchematicsException(`Main file (${mainPath}) not found`);
+ }
+ const mainText = mainBuffer.toString('utf-8');
+ const source = ts.createSourceFile(mainPath, mainText, ts.ScriptTarget.Latest, true);
+
+ const allNodes = getSourceNodes(source);
+
+ let bootstrapCall: ts.CallExpression | null = null;
+
+ for (const node of allNodes) {
+
+ let bootstrapCallNode: ts.Node | null = null;
+ bootstrapCallNode = findNode(node, ts.SyntaxKind.Identifier, 'bootstrapModule');
+
+ // Walk up the parent until CallExpression is found.
+ while (bootstrapCallNode && bootstrapCallNode.parent
+ && bootstrapCallNode.parent.kind !== ts.SyntaxKind.CallExpression) {
+
+ bootstrapCallNode = bootstrapCallNode.parent;
+ }
+
+ if (bootstrapCallNode !== null &&
+ bootstrapCallNode.parent !== undefined &&
+ bootstrapCallNode.parent.kind === ts.SyntaxKind.CallExpression) {
+ bootstrapCall = bootstrapCallNode.parent as ts.CallExpression;
+ break;
+ }
+ }
+
+ return bootstrapCall;
+}
From bcf8d197f2f55d3f874a700b9712c74605188677 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Fri, 27 Oct 2017 15:55:21 -0700
Subject: [PATCH 013/807] refactor(@angular-devkit/core): add a namespace for
logging to core
---
bin/devkit-admin | 3 ++-
.../angular_devkit/core/node/cli-logger.ts | 10 ++++----
packages/angular_devkit/core/src/index.ts | 11 +++++----
.../schematics/src/engine/engine.ts | 4 ++--
.../schematics/src/engine/interface.ts | 4 ++--
.../schematics/src/engine/schematic_spec.ts | 4 ++--
.../testing/schematic-test-runner.ts | 8 +++----
.../schematic/files/src/my-schematic/index.ts | 2 +-
scripts/build.ts | 24 +++++++++----------
scripts/lint.ts | 6 ++---
scripts/packages.ts | 4 ++--
scripts/publish.ts | 6 ++---
scripts/release.ts | 8 +++----
scripts/serialize.ts | 4 ++--
scripts/templates.ts | 4 ++--
scripts/test.ts | 4 ++--
scripts/validate-commits.ts | 6 ++---
scripts/validate.ts | 4 ++--
.../aio-app/src/app/shared/ga.service.ts | 4 ++--
19 files changed, 62 insertions(+), 58 deletions(-)
diff --git a/bin/devkit-admin b/bin/devkit-admin
index 0a92a656be..8cadae582b 100755
--- a/bin/devkit-admin
+++ b/bin/devkit-admin
@@ -33,7 +33,7 @@ process.chdir(path.join(__dirname, '..'));
// This might get awkward, so we fallback to console if there was an error.
let logger = null;
try {
- logger = new (require('@angular-devkit/core').IndentLogger)('root');
+ logger = new (require('@angular-devkit/core').logging.IndentLogger)('root');
require('rxjs/add/operator/filter');
logger
@@ -65,6 +65,7 @@ try {
warn: console.warn.bind(console),
error: console.error.bind(console),
fatal: x => { console.error(x); process.exit(100); },
+ createChild: () => logger,
};
}
diff --git a/packages/angular_devkit/core/node/cli-logger.ts b/packages/angular_devkit/core/node/cli-logger.ts
index bb25c719db..1d8ef77a1f 100644
--- a/packages/angular_devkit/core/node/cli-logger.ts
+++ b/packages/angular_devkit/core/node/cli-logger.ts
@@ -5,19 +5,19 @@
* 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 { IndentLogger, LogEntry, Logger, terminal } from '@angular-devkit/core';
+import { logging, terminal } from '@angular-devkit/core';
import 'rxjs/add/operator/filter';
/**
* A Logger that sends information to STDOUT and STDERR.
*/
-export function createConsoleLogger(verbose = false): Logger {
- const logger = new IndentLogger('cling');
+export function createConsoleLogger(verbose = false): logging.Logger {
+ const logger = new logging.IndentLogger('cling');
logger
- .filter((entry: LogEntry) => (entry.level != 'debug' || verbose))
- .subscribe((entry: LogEntry) => {
+ .filter(entry => (entry.level != 'debug' || verbose))
+ .subscribe(entry => {
let color: (s: string) => string = x => terminal.dim(terminal.white(x));
let output = process.stdout;
switch (entry.level) {
diff --git a/packages/angular_devkit/core/src/index.ts b/packages/angular_devkit/core/src/index.ts
index 29b2abf854..d64907491b 100644
--- a/packages/angular_devkit/core/src/index.ts
+++ b/packages/angular_devkit/core/src/index.ts
@@ -5,12 +5,15 @@
* 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 * as logging from './logger';
+import * as terminal from './terminal';
+
export * from './exception/exception';
export * from './json';
-export * from './logger';
-import * as terminal from './terminal';
export * from './utils';
export * from './virtual-fs';
-
-export { terminal };
+export {
+ logging,
+ terminal,
+};
diff --git a/packages/angular_devkit/schematics/src/engine/engine.ts b/packages/angular_devkit/schematics/src/engine/engine.ts
index ff1df1a927..94377a3b2d 100644
--- a/packages/angular_devkit/schematics/src/engine/engine.ts
+++ b/packages/angular_devkit/schematics/src/engine/engine.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 { BaseException, NullLogger } from '@angular-devkit/core';
+import { BaseException, logging } from '@angular-devkit/core';
import { CollectionDescription, TypedSchematicContext } from '@angular-devkit/schematics';
import 'rxjs/add/operator/map';
import { Url } from 'url';
@@ -84,7 +84,7 @@ export class SchematicEngine {
readonly debug: boolean;
readonly engine: Engine;
- readonly logger: LoggerApi;
+ readonly logger: logging.LoggerApi;
readonly schematic: Schematic;
readonly strategy: MergeStrategy;
}
diff --git a/packages/angular_devkit/schematics/src/engine/schematic_spec.ts b/packages/angular_devkit/schematics/src/engine/schematic_spec.ts
index 46abdb7589..b6f77c9103 100644
--- a/packages/angular_devkit/schematics/src/engine/schematic_spec.ts
+++ b/packages/angular_devkit/schematics/src/engine/schematic_spec.ts
@@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
// tslint:disable:non-null-operator
-import { NullLogger } from '@angular-devkit/core';
+import { logging } from '@angular-devkit/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/toArray';
import 'rxjs/add/operator/toPromise';
@@ -28,7 +28,7 @@ type SchematicT = {
const context = {
debug: false,
- logger: new NullLogger(),
+ logger: new logging.NullLogger(),
strategy: MergeStrategy.Default,
};
const engine: Engine = {
diff --git a/packages/angular_devkit/schematics/testing/schematic-test-runner.ts b/packages/angular_devkit/schematics/testing/schematic-test-runner.ts
index ac0186394c..ec2df1a81e 100644
--- a/packages/angular_devkit/schematics/testing/schematic-test-runner.ts
+++ b/packages/angular_devkit/schematics/testing/schematic-test-runner.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 { Logger, schema } from '@angular-devkit/core';
+import { logging, schema } from '@angular-devkit/core';
import {
Collection,
DelegateTree,
@@ -36,12 +36,12 @@ export class SchematicTestRunner {
private _engineHost = new NodeModulesTestEngineHost();
private _engine: SchematicEngine<{}, {}> = new SchematicEngine(this._engineHost);
private _collection: Collection<{}, {}>;
- private _logger: Logger;
+ private _logger: logging.Logger;
private _registry: schema.JsonSchemaRegistry;
constructor(private _collectionName: string, collectionPath: string) {
this._engineHost.registerCollection(_collectionName, collectionPath);
- this._logger = new Logger('test');
+ this._logger = new logging.Logger('test');
this._registry = new schema.JsonSchemaRegistry();
this._engineHost.registerOptionsTransform((
@@ -66,7 +66,7 @@ export class SchematicTestRunner {
this._collection = this._engine.createCollection(this._collectionName);
}
- get logger() { return this._logger; }
+ get logger(): logging.Logger { return this._logger; }
runSchematicAsync(
schematicName: string,
diff --git a/packages/schematics/schematics/schematic/files/src/my-schematic/index.ts b/packages/schematics/schematics/schematic/files/src/my-schematic/index.ts
index 2e790735cf..d3462e6f57 100644
--- a/packages/schematics/schematics/schematic/files/src/my-schematic/index.ts
+++ b/packages/schematics/schematics/schematic/files/src/my-schematic/index.ts
@@ -6,7 +6,7 @@ import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
export function mySchematic(options: any): Rule {
return (tree: Tree, context: SchematicContext) => {
// Show the options for this Schematics.
- // The logger here is at the discretion of the tooling. It can be ignored or only showing
+ // The logging here is at the discretion of the tooling. It can be ignored or only showing
// info/warnings/errors. If you use console.log() there is not guarantee it will be
// propagated to a user in any way (for example, an IDE running this schematic might
// have a logging window but no support for console.log).
diff --git a/scripts/build.ts b/scripts/build.ts
index 9a01cda110..96b91f248d 100644
--- a/scripts/build.ts
+++ b/scripts/build.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 { JsonObject, Logger } from '@angular-devkit/core';
+import { JsonObject, logging } from '@angular-devkit/core';
import * as fs from 'fs';
import * as glob from 'glob';
import * as path from 'path';
@@ -63,7 +63,7 @@ function _copy(from: string, to: string) {
}
-function _recursiveCopy(from: string, to: string, logger: Logger) {
+function _recursiveCopy(from: string, to: string, logger: logging.Logger) {
if (!fs.existsSync(from)) {
logger.error(`File "${from}" does not exist.`);
process.exit(4);
@@ -93,7 +93,7 @@ function _rimraf(p: string) {
}
-function _clean(logger: Logger) {
+function _clean(logger: logging.Logger) {
logger.info('Cleaning...');
logger.info(' Removing dist/...');
_rimraf(path.join(__dirname, '../dist'));
@@ -128,7 +128,7 @@ function _sortPackages() {
}
-function _build(logger: Logger) {
+function _build(logger: logging.Logger) {
logger.info('Building...');
const tsConfigPath = path.relative(process.cwd(), path.join(__dirname, '../tsconfig.json'));
try {
@@ -141,14 +141,14 @@ function _build(logger: Logger) {
}
-export default function(argv: { local?: boolean }, logger: Logger) {
+export default function(argv: { local?: boolean }, logger: logging.Logger) {
_clean(logger);
const sortedPackages = _sortPackages();
_build(logger);
logger.info('Moving packages to dist/');
- const packageLogger = new Logger('packages', logger);
+ const packageLogger = logger.createChild('packages');
for (const packageName of sortedPackages) {
packageLogger.info(packageName);
const pkg = packages[packageName];
@@ -157,13 +157,13 @@ export default function(argv: { local?: boolean }, logger: Logger) {
}
logger.info('Copying resources...');
- const resourceLogger = new Logger('resources', logger);
+ const resourceLogger = logger.createChild('resources');
for (const packageName of sortedPackages) {
resourceLogger.info(packageName);
const pkg = packages[packageName];
const pkgJson = pkg.packageJson;
const files = glob.sync(path.join(pkg.root, '**/*'), { dot: true, nodir: true });
- const subSubLogger = new Logger(packageName, resourceLogger);
+ const subSubLogger = resourceLogger.createChild(packageName);
subSubLogger.info(`${files.length} files total...`);
const resources = files
.map((fileName) => path.relative(pkg.root, fileName))
@@ -221,7 +221,7 @@ export default function(argv: { local?: boolean }, logger: Logger) {
}
logger.info('Removing spec files...');
- const specLogger = new Logger('specfiles', logger);
+ const specLogger = logger.createChild('specfiles');
for (const packageName of sortedPackages) {
specLogger.info(packageName);
const pkg = packages[packageName];
@@ -231,7 +231,7 @@ export default function(argv: { local?: boolean }, logger: Logger) {
}
logger.info('Building ejs templates...');
- const templateLogger = new Logger('templates', logger);
+ const templateLogger = logger.createChild('templates');
const templateCompiler = require('@angular-devkit/core').template;
for (const packageName of sortedPackages) {
templateLogger.info(packageName);
@@ -257,7 +257,7 @@ export default function(argv: { local?: boolean }, logger: Logger) {
logger.info('Setting versions...');
- const versionLogger = new Logger('versions', logger);
+ const versionLogger = logger.createChild('versions');
for (const packageName of sortedPackages) {
versionLogger.info(packageName);
const pkg = packages[packageName];
@@ -289,7 +289,7 @@ export default function(argv: { local?: boolean }, logger: Logger) {
}
logger.info('Tarring all packages...');
- const tarLogger = new Logger('license', logger);
+ const tarLogger = logger.createChild('license');
Object.keys(packages).forEach(pkgName => {
const pkg = packages[pkgName];
tarLogger.info(`${pkgName} => ${pkg.tar}`);
diff --git a/scripts/lint.ts b/scripts/lint.ts
index ffecff84f7..a0fed2b2be 100644
--- a/scripts/lint.ts
+++ b/scripts/lint.ts
@@ -5,14 +5,14 @@
* 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 { Logger } from '@angular-devkit/core';
+import { logging } from '@angular-devkit/core';
import { ParsedArgs } from 'minimist';
import * as path from 'path';
import { Configuration, ILinterOptions, Linter, findFormatter } from 'tslint';
import * as ts from 'typescript';
-function _buildRules(logger: Logger) {
+function _buildRules(logger: logging.Logger) {
const tsConfigPath = path.join(__dirname, '../rules/tsconfig.json');
const configFile = ts.readConfigFile(tsConfigPath, ts.sys.readFile);
@@ -36,7 +36,7 @@ function _buildRules(logger: Logger) {
}
-export default function (options: ParsedArgs, logger: Logger) {
+export default function (options: ParsedArgs, logger: logging.Logger) {
_buildRules(logger);
const lintOptions: ILinterOptions = {
diff --git a/scripts/packages.ts b/scripts/packages.ts
index c9a8141a1c..cb681e56ee 100644
--- a/scripts/packages.ts
+++ b/scripts/packages.ts
@@ -5,12 +5,12 @@
* 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 { Logger } from '@angular-devkit/core';
+import { logging } from '@angular-devkit/core';
const { packages } = require('../lib/packages');
-export default function(_: {}, logger: Logger) {
+export default function(_: {}, logger: logging.Logger) {
logger.info(JSON.stringify(packages, null, 2));
}
diff --git a/scripts/publish.ts b/scripts/publish.ts
index 96e4156176..379d47d6b1 100644
--- a/scripts/publish.ts
+++ b/scripts/publish.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 { Logger } from '@angular-devkit/core';
+import { logging } from '@angular-devkit/core';
import * as stream from 'stream';
import { packages } from '../lib/packages';
@@ -16,10 +16,10 @@ class NullStream extends stream.Writable {
}
-export default function (_: {}, logger: Logger) {
+export default function (_: {}, logger: logging.Logger) {
logger.info('Building...');
const build = require('./build').default;
- build({}, new Logger('build', logger));
+ build({}, logger.createChild('build'));
return new Promise((resolve, reject) => {
const loadOptions = { progress: false, logstream: new NullStream() };
diff --git a/scripts/release.ts b/scripts/release.ts
index 84e6cba5d3..48910217a9 100644
--- a/scripts/release.ts
+++ b/scripts/release.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 { Logger } from '@angular-devkit/core';
+import { logging } from '@angular-devkit/core';
import * as fs from 'fs';
import * as path from 'path';
import * as semver from 'semver';
@@ -16,7 +16,7 @@ import { packages } from '../lib/packages';
const monorepo = require('../.monorepo.json');
-function _showVersions(logger: Logger) {
+function _showVersions(logger: logging.Logger) {
for (const pkgName of Object.keys(packages)) {
const pkg = packages[pkgName];
@@ -36,7 +36,7 @@ function _showVersions(logger: Logger) {
}
-function _upgrade(release: string, logger: Logger) {
+function _upgrade(release: string, logger: logging.Logger) {
for (const pkg of Object.keys(packages)) {
const hash = packages[pkg].hash;
const version = packages[pkg].version;
@@ -107,7 +107,7 @@ function _upgrade(release: string, logger: Logger) {
}
-export default function(args: { _: string[], 'dry-run'?: boolean }, logger: Logger) {
+export default function(args: { _: string[], 'dry-run'?: boolean }, logger: logging.Logger) {
const maybeRelease = args._.shift();
const dryRun = args['dry-run'] !== undefined;
switch (maybeRelease) {
diff --git a/scripts/serialize.ts b/scripts/serialize.ts
index a034f9a8c5..ae95794bfb 100644
--- a/scripts/serialize.ts
+++ b/scripts/serialize.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 { Logger, classify } from '@angular-devkit/core';
+import { classify, logging } from '@angular-devkit/core';
import { SchemaClassFactory } from '@ngtools/json-schema';
import * as fs from 'fs';
@@ -34,7 +34,7 @@ export function buildSchema(inFile: string, mimetype: string): string {
}
-export default function(opts: { _: string[], mimetype?: string }, logger: Logger) {
+export default function(opts: { _: string[], mimetype?: string }, logger: logging.Logger) {
const inFile = opts._[0] as string;
const outFile = opts._[1] as string;
const mimetype = opts.mimetype || 'text/x.dts';
diff --git a/scripts/templates.ts b/scripts/templates.ts
index 4287157114..3fa6bf6741 100644
--- a/scripts/templates.ts
+++ b/scripts/templates.ts
@@ -5,12 +5,12 @@
* 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 { Logger } from '@angular-devkit/core';
+import { logging } from '@angular-devkit/core';
import * as fs from 'fs';
import * as path from 'path';
import { packages } from '../lib/packages';
-export default function(_options: {}, logger: Logger) {
+export default function(_options: {}, logger: logging.Logger) {
const monorepo = require('../.monorepo.json');
logger.info('Building README...');
diff --git a/scripts/test.ts b/scripts/test.ts
index 072e38d881..e60c61f664 100644
--- a/scripts/test.ts
+++ b/scripts/test.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 { Logger } from '@angular-devkit/core';
+import { logging } from '@angular-devkit/core';
import * as glob from 'glob';
import * as Istanbul from 'istanbul';
import 'jasmine';
@@ -205,7 +205,7 @@ glob.sync('packages/**/*.spec.ts')
console.error(`Invalid spec file name: ${path}. You're using the old convention.`);
});
-export default function (args: ParsedArgs, logger: Logger) {
+export default function (args: ParsedArgs, logger: logging.Logger) {
let regex = 'packages/**/*_spec.ts';
if (args.glob) {
regex = `packages/**/${args.glob}/**/*_spec.ts`;
diff --git a/scripts/validate-commits.ts b/scripts/validate-commits.ts
index d70ea25d27..0cb13f571f 100644
--- a/scripts/validate-commits.ts
+++ b/scripts/validate-commits.ts
@@ -5,12 +5,12 @@
* 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 { Logger } from '@angular-devkit/core';
+import { logging } from '@angular-devkit/core';
import { execSync } from 'child_process';
import { packages } from '../lib/packages';
-export default function (_: {}, logger: Logger) {
+export default function (_: {}, logger: logging.Logger) {
logger.info('Getting merge base...');
const prNumber = process.env['CIRCLE_PR_NUMBER'] || '';
@@ -46,7 +46,7 @@ export default function (_: {}, logger: Logger) {
.filter(x => !!x) as [string, string][];
logger.info(`Found ${commits.length} commits...`);
- const output = new Logger('check', logger);
+ const output = logger.createChild('check');
let invalidCount = 0;
function _invalid(sha: string, message: string, error: string) {
diff --git a/scripts/validate.ts b/scripts/validate.ts
index b1ec591c6a..f3e20eada8 100644
--- a/scripts/validate.ts
+++ b/scripts/validate.ts
@@ -5,12 +5,12 @@
* 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 { Logger, tags } from '@angular-devkit/core';
+import { logging, tags } from '@angular-devkit/core';
import { execSync } from 'child_process';
import templates from './templates';
import validateCommits from './validate-commits';
-export default function (options: { verbose: boolean }, logger: Logger) {
+export default function (options: { verbose: boolean }, logger: logging.Logger) {
let error = false;
logger.info('Running templates validation...');
diff --git a/tests/@angular_devkit/build_optimizer/webpack/aio-app/src/app/shared/ga.service.ts b/tests/@angular_devkit/build_optimizer/webpack/aio-app/src/app/shared/ga.service.ts
index c9563f9cf8..07040a06e4 100644
--- a/tests/@angular_devkit/build_optimizer/webpack/aio-app/src/app/shared/ga.service.ts
+++ b/tests/@angular_devkit/build_optimizer/webpack/aio-app/src/app/shared/ga.service.ts
@@ -46,13 +46,13 @@ export class GaService {
// Then send queued commands to either real or e2e test ga();
// after waiting to allow possible e2e test to replace global ga function
ga(() => setTimeout(() => {
- // this.logger.log('GA fn:', window['ga'].toString());
+ // this.logging.log('GA fn:', window['ga'].toString());
this.ga = window['ga'];
gaQueue.forEach((command) => this.ga.apply(null, command));
}, GaService.initializeDelay));
} else {
- // delegate `ga` calls to the logger if no ga installed
+ // delegate `ga` calls to the logging if no ga installed
this.ga = (...rest: any[]) => { this.logger.log('ga:', rest); };
}
}
From 3a620e2bd3d9549fce7e8c479e5f9b866dcd7a3a Mon Sep 17 00:00:00 2001
From: Minko Gechev
Date: Wed, 22 Nov 2017 17:24:41 -0800
Subject: [PATCH 014/807] feat(@schematics/angular): update codelyzer and add
rules (#257)
Codelyzer@^4.0.0 is out! It introduces few new rules such as:
- `angular-whitespace` - checks whether we have presence of whitespace
in the template to make it more readable, for instance
in `{{ expr }}`, `check-interpolation` will check if `expr` is
surrounded by whitespace. This rule also introduces auto fixes.
- `no-output-on-prefix` - warns if outputs are prefixed with `on` this
is based on
https://angular.io/guide/styleguide#dont-prefix-output-properties.
Tell me what you think about `angular-whitespace` and let me know if it
is too opinionated. As part of `angular-whitespace` we're planning a few
more features.
---
packages/schematics/angular/application/files/package.json | 2 +-
packages/schematics/angular/application/files/tslint.json | 5 +++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/packages/schematics/angular/application/files/package.json b/packages/schematics/angular/application/files/package.json
index 79d69c0a5c..6f4211b0e5 100644
--- a/packages/schematics/angular/application/files/package.json
+++ b/packages/schematics/angular/application/files/package.json
@@ -33,7 +33,7 @@
"@types/jasmine": "~2.5.53",
"@types/jasminewd2": "~2.0.2",
"@types/node": "~6.0.60",
- "codelyzer": "~3.2.0",
+ "codelyzer": "^4.0.1",
"jasmine-core": "~2.6.2",
"jasmine-spec-reporter": "~4.1.0",
"karma": "~1.7.0",
diff --git a/packages/schematics/angular/application/files/tslint.json b/packages/schematics/angular/application/files/tslint.json
index d9af7070a6..1f8ed16bed 100644
--- a/packages/schematics/angular/application/files/tslint.json
+++ b/packages/schematics/angular/application/files/tslint.json
@@ -127,6 +127,8 @@
"<%= prefix %>",
"kebab-case"
],
+ "angular-whitespace": [true, "check-interpolation"],
+ "no-output-on-prefix": true,
"use-input-property-decorator": true,
"use-output-property-decorator": true,
"use-host-property-decorator": true,
@@ -135,7 +137,6 @@
"use-life-cycle-interface": true,
"use-pipe-transform-interface": true,
"component-class-suffix": true,
- "directive-class-suffix": true,
- "invoke-injectable": true
+ "directive-class-suffix": true
}
}
From f70b5607ac341202963d2cc1c6aa941d705811ed Mon Sep 17 00:00:00 2001
From: Mike Brocchi
Date: Thu, 2 Nov 2017 17:05:31 -0400
Subject: [PATCH 015/807] feat(@schematics/angular): Add appShell schematic
---
.../schematics/angular/app-shell/index.ts | 290 ++++++++++++++++++
.../angular/app-shell/index_spec.ts | 164 ++++++++++
.../schematics/angular/app-shell/schema.d.ts | 71 +++++
.../schematics/angular/app-shell/schema.json | 90 ++++++
packages/schematics/angular/collection.json | 6 +
.../schematics/angular/universal/index.ts | 55 +---
.../angular/universal/index_spec.ts | 4 +-
.../schematics/angular/utility/ast-utils.ts | 77 +++--
.../angular/utility/ast-utils_spec.ts | 83 ++++-
packages/schematics/angular/utility/config.ts | 6 +-
.../angular/utility/ng-ast-utils.ts | 39 +++
11 files changed, 820 insertions(+), 65 deletions(-)
create mode 100644 packages/schematics/angular/app-shell/index.ts
create mode 100644 packages/schematics/angular/app-shell/index_spec.ts
create mode 100644 packages/schematics/angular/app-shell/schema.d.ts
create mode 100644 packages/schematics/angular/app-shell/schema.json
diff --git a/packages/schematics/angular/app-shell/index.ts b/packages/schematics/angular/app-shell/index.ts
new file mode 100644
index 0000000000..a3fe909ce9
--- /dev/null
+++ b/packages/schematics/angular/app-shell/index.ts
@@ -0,0 +1,290 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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 { normalize } from '@angular-devkit/core';
+import {
+ Rule,
+ SchematicContext,
+ SchematicsException,
+ Tree,
+ chain,
+ schematic,
+} from '@angular-devkit/schematics';
+import 'rxjs/add/operator/merge';
+import * as ts from 'typescript';
+import {
+ addImportToModule,
+ addSymbolToNgModuleMetadata,
+ findNode,
+ getDecoratorMetadata,
+ getSourceNodes,
+ isImported,
+} from '../utility/ast-utils';
+import { InsertChange } from '../utility/change';
+import { AppConfig, getAppFromConfig, getConfig } from '../utility/config';
+import { getAppModulePath } from '../utility/ng-ast-utils';
+import { insertImport } from '../utility/route-utils';
+import { Schema as AppShellOptions } from './schema';
+
+
+// Helper functions. (possible refactors to utils)
+function getSourceFile(host: Tree, path: string): ts.SourceFile {
+ const buffer = host.read(path);
+ if (!buffer) {
+ throw new SchematicsException(`Could not find bootstrapped module.`);
+ }
+ const content = buffer.toString();
+ const source = ts.createSourceFile(path, content, ts.ScriptTarget.Latest, true);
+
+ return source;
+}
+
+function getServerModulePath(host: Tree, app: AppConfig): string | null {
+ const mainPath = `/${app.root}/${app.main}`;
+ const mainSource = getSourceFile(host, mainPath);
+ const allNodes = getSourceNodes(mainSource);
+ const expNode = allNodes.filter(node => node.kind === ts.SyntaxKind.ExportDeclaration)[0];
+ if (!expNode) {
+ return null;
+ }
+ const relativePath = ( expNode).moduleSpecifier;
+ const modulePath = normalize(`/${app.root}/${relativePath.text}.ts`);
+
+ return modulePath;
+}
+// end helper functions.
+
+function addUniversalApp(options: AppShellOptions): Rule {
+ return (host: Tree, context: SchematicContext) => {
+ // Copy options.
+ const universalOptions = {
+ ...options,
+ name: options.universalApp,
+ };
+
+ // Delete non-universal options.
+ delete universalOptions.universalApp;
+ delete universalOptions.route;
+
+ return schematic('universal', universalOptions)(host, context);
+ };
+}
+
+function addAppShellConfig(options: AppShellOptions): Rule {
+ return (host: Tree) => {
+ const config = getConfig(host);
+ const app = getAppFromConfig(config, options.clientApp || '0');
+
+ if (!app) {
+ throw new SchematicsException(`Client app (${options.clientApp}) could not be found.`);
+ }
+
+ if (!options.route) {
+ throw new SchematicsException(`Route is not defined`);
+ }
+
+ app.appShell = {
+ app: options.universalApp,
+ route: options.route,
+ };
+
+ host.overwrite('/.angular-cli.json', JSON.stringify(config, null, 2));
+
+ return host;
+ };
+}
+
+function addRouterModule(options: AppShellOptions): Rule {
+ return (host: Tree) => {
+ const config = getConfig(host);
+ const app = getAppFromConfig(config, options.clientApp || '0');
+ if (app === null) {
+ throw new SchematicsException('Client app not found.');
+ }
+ const modulePath = getAppModulePath(host, app);
+ const moduleSource = getSourceFile(host, modulePath);
+ const changes = addImportToModule(moduleSource, modulePath, 'RouterModule', '@angular/router');
+ const recorder = host.beginUpdate(modulePath);
+ changes.forEach((change: InsertChange) => {
+ recorder.insertLeft(change.pos, change.toAdd);
+ });
+ host.commitUpdate(recorder);
+
+ return host;
+ };
+}
+
+function getMetadataProperty(metadata: ts.Node, propertyName: string): ts.PropertyAssignment {
+ const properties = (metadata as ts.ObjectLiteralExpression).properties;
+ const property = properties
+ .filter(prop => prop.kind === ts.SyntaxKind.PropertyAssignment)
+ .filter((prop: ts.PropertyAssignment) => {
+ const name = prop.name;
+ switch (name.kind) {
+ case ts.SyntaxKind.Identifier:
+ return (name as ts.Identifier).getText() === propertyName;
+ case ts.SyntaxKind.StringLiteral:
+ return (name as ts.StringLiteral).text === propertyName;
+ }
+
+ return false;
+ })[0];
+
+ return property as ts.PropertyAssignment;
+}
+
+function addRouterOutlet(options: AppShellOptions): Rule {
+ return (host: Tree) => {
+ const routerOutletMarkup = ``;
+
+ const config = getConfig(host);
+ const app = getAppFromConfig(config, options.clientApp || '0');
+ if (app === null) {
+ throw new SchematicsException('Client app not found.');
+ }
+ const modulePath = getAppModulePath(host, app);
+ // const modulePath = getAppModulePath(host, options);
+ const moduleSource = getSourceFile(host, modulePath);
+
+ const metadataNode = getDecoratorMetadata(moduleSource, 'NgModule', '@angular/core')[0];
+ const bootstrapProperty = getMetadataProperty(metadataNode, 'bootstrap');
+
+ const arrLiteral = ( bootstrapProperty)
+ .initializer as ts.ArrayLiteralExpression;
+
+ const componentSymbol = arrLiteral.elements[0].getText();
+
+ const relativePath = getSourceNodes(moduleSource)
+ .filter(node => node.kind === ts.SyntaxKind.ImportDeclaration)
+ .filter(imp => {
+ return findNode(imp, ts.SyntaxKind.Identifier, componentSymbol);
+ })
+ .map((imp: ts.ImportDeclaration) => {
+ const pathStringLiteral = imp.moduleSpecifier;
+
+ return pathStringLiteral.text;
+ })[0];
+
+ const dirEntry = host.getDir(modulePath);
+ const dir = dirEntry.parent ? dirEntry.parent.path : '/';
+ const compPath = normalize(`/${dir}/${relativePath}.ts`);
+
+ const compSource = getSourceFile(host, compPath);
+ const compMetadata = getDecoratorMetadata(compSource, 'Component', '@angular/core')[0];
+ const templateProp = getMetadataProperty(compMetadata, 'template');
+ const templateUrlProp = getMetadataProperty(compMetadata, 'templateUrl');
+
+ if (templateProp) {
+ if (!//.test(templateProp.initializer.getText())) {
+ const recorder = host.beginUpdate(compPath);
+ recorder.insertRight(templateProp.initializer.getEnd() - 1, routerOutletMarkup);
+ host.commitUpdate(recorder);
+ }
+ } else {
+ const templateUrl = (templateUrlProp.initializer as ts.StringLiteral).text;
+ const dirEntry = host.getDir(compPath);
+ const dir = dirEntry.parent ? dirEntry.parent.path : '/';
+ const templatePath = normalize(`/${dir}/${templateUrl}`);
+ const buffer = host.read(templatePath);
+ if (buffer) {
+ const content = buffer.toString();
+ if (!//.test(content)) {
+ const recorder = host.beginUpdate(templatePath);
+ recorder.insertRight(buffer.length, routerOutletMarkup);
+ host.commitUpdate(recorder);
+ }
+ }
+ }
+
+ return host;
+ };
+}
+
+function addServerRoutes(options: AppShellOptions): Rule {
+ return (host: Tree) => {
+ const config = getConfig(host);
+ const app = getAppFromConfig(config, options.universalApp);
+ if (app === null) {
+ throw new SchematicsException('Universal/server app not found.');
+ }
+ const modulePath = getServerModulePath(host, app);
+ if (modulePath === null) {
+ throw new SchematicsException('Universal/server app not found.');
+ }
+ let moduleSource = getSourceFile(host, modulePath);
+ if (!isImported(moduleSource, 'Routes', '@angular/router')) {
+ const routesChange = insertImport(moduleSource,
+ modulePath,
+ 'Routes',
+ '@angular/router') as InsertChange;
+ if (routesChange.toAdd) {
+ const recorder = host.beginUpdate(modulePath);
+ recorder.insertLeft(routesChange.pos, routesChange.toAdd);
+ host.commitUpdate(recorder);
+ }
+ moduleSource = getSourceFile(host, modulePath);
+ const imports = getSourceNodes(moduleSource)
+ .filter(node => node.kind === ts.SyntaxKind.ImportDeclaration)
+ .sort((a, b) => a.getStart() - b.getStart());
+ const insertPosition = imports[imports.length - 1].getEnd();
+ const routeText =
+ `\n\nconst routes: Routes = [ { path: '${options.route}', component: AppShellComponent }];`;
+ const routeRecorder = host.beginUpdate(modulePath);
+ routeRecorder.insertRight(insertPosition, routeText);
+ host.commitUpdate(routeRecorder);
+ }
+ moduleSource = getSourceFile(host, modulePath);
+
+ if (!isImported(moduleSource, 'RouterModule', '@angular/router')) {
+ const routerModuleChange = insertImport(moduleSource,
+ modulePath,
+ 'RouterModule',
+ '@angular/router') as InsertChange;
+
+ if (routerModuleChange.toAdd) {
+ const recorder = host.beginUpdate(modulePath);
+ recorder.insertLeft(routerModuleChange.pos, routerModuleChange.toAdd);
+ host.commitUpdate(recorder);
+ }
+ const metadataChange = addSymbolToNgModuleMetadata(
+ moduleSource, modulePath, 'imports', 'RouterModule.forRoot(routes)');
+
+ if (metadataChange) {
+ const recorder = host.beginUpdate(modulePath);
+ metadataChange.forEach((change: InsertChange) => {
+ recorder.insertRight(change.pos, change.toAdd);
+ });
+ host.commitUpdate(recorder);
+ }
+ }
+
+ return host;
+ };
+}
+
+function addShellComponent(options: AppShellOptions): Rule {
+ return (host: Tree, context: SchematicContext) => {
+
+ const componentOptions = {
+ name: 'app-shell',
+ module: options.rootModuleFileName,
+ };
+
+ return schematic('component', componentOptions)(host, context);
+ };
+}
+
+export default function (options: AppShellOptions): Rule {
+ return chain([
+ addUniversalApp(options),
+ addAppShellConfig(options),
+ addRouterModule(options),
+ addRouterOutlet(options),
+ addServerRoutes(options),
+ addShellComponent(options),
+ ]);
+}
diff --git a/packages/schematics/angular/app-shell/index_spec.ts b/packages/schematics/angular/app-shell/index_spec.ts
new file mode 100644
index 0000000000..d869c7913e
--- /dev/null
+++ b/packages/schematics/angular/app-shell/index_spec.ts
@@ -0,0 +1,164 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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 } from '@angular-devkit/schematics';
+import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
+import * as path from 'path';
+import { Schema as ApplicationOptions } from '../application/schema';
+import { Schema as AppShellOptions } from './schema';
+
+
+describe('App Shell Schematic', () => {
+ const schematicRunner = new SchematicTestRunner(
+ '@schematics/angular',
+ path.join(__dirname, '../collection.json'),
+ );
+ const defaultOptions: AppShellOptions = {
+ name: 'foo',
+ universalApp: 'universal',
+ };
+
+ let appTree: Tree;
+ beforeEach(() => {
+ const appOptions: ApplicationOptions = {
+ directory: '',
+ name: 'app',
+ path: 'src',
+ prefix: '',
+ sourceDir: 'src',
+ inlineStyle: false,
+ inlineTemplate: false,
+ viewEncapsulation: 'None',
+ changeDetection: 'Default',
+ version: '1.2.3',
+ routing: false,
+ style: 'css',
+ skipTests: false,
+ minimal: false,
+ };
+ appTree = schematicRunner.runSchematic('application', appOptions);
+ });
+
+ it('should add a universal app', () => {
+ const tree = schematicRunner.runSchematic('appShell', defaultOptions, appTree);
+ const filePath = '/src/app/app.server.module.ts';
+ const file = tree.files.filter(f => f === filePath)[0];
+ expect(file).toBeDefined();
+ });
+
+ it('should add app shell configuration', () => {
+ const tree = schematicRunner.runSchematic('appShell', defaultOptions, appTree);
+ const filePath = '/.angular-cli.json';
+ const content = tree.read(filePath) || new Buffer('');
+ const config = JSON.parse(content.toString());
+ const app = config.apps[0];
+ expect(app.appShell).toBeDefined();
+ expect(app.appShell.app).toEqual('universal');
+ expect(app.appShell.route).toEqual('shell');
+ });
+
+ it('should add router module to client app module', () => {
+ const tree = schematicRunner.runSchematic('appShell', defaultOptions, appTree);
+ const filePath = '/src/app/app.module.ts';
+ const content = tree.read(filePath) || new Buffer('');
+ expect(content.toString()).toMatch(/import { RouterModule } from \'@angular\/router\';/);
+ });
+
+ describe('Add router-outlet', () => {
+ function makeInlineTemplate(tree: Tree, template?: string): void {
+ template = template || `
+
+ App works!
+
`;
+ const newText = `
+ import { Component, OnInit } from '@angular/core';
+
+ @Component({
+ selector: ''
+ template: \`
+ ${template}
+ \`,
+ styleUrls: ['./app.component.css']
+ })
+ export class AppComponent implements OnInit {
+
+ constructor() { }
+
+ ngOnInit() {
+ }
+
+ }
+
+ `;
+ tree.overwrite('/src/app/app.component.ts', newText);
+ tree.delete('/src/app/app.component.html');
+ }
+
+ it('should add the router outlet (external template)', () => {
+ const tree = schematicRunner.runSchematic('appShell', defaultOptions, appTree);
+ const content = tree.read('/src/app/app.component.html') || new Buffer('');
+ expect(content.toString()).toMatch(/<\/router\-outlet>/g);
+ });
+
+ it('should not re-add the router outlet (external template)', () => {
+ const htmlPath = '/src/app/app.component.html';
+ appTree.overwrite(htmlPath, '');
+ const tree = schematicRunner.runSchematic('appShell', defaultOptions, appTree);
+
+ const content = tree.read(htmlPath) || new Buffer('');
+ const matches = content.toString().match(/<\/router\-outlet>/g);
+ const numMatches = matches ? matches.length : 0;
+ expect(numMatches).toEqual(1);
+ });
+
+ it('should add the router outlet (inline template)', () => {
+ makeInlineTemplate(appTree);
+ const tree = schematicRunner.runSchematic('appShell', defaultOptions, appTree);
+ const content = tree.read('/src/app/app.component.ts') || new Buffer('');
+ expect(content.toString()).toMatch(/<\/router\-outlet>/g);
+ });
+
+ it('should not re-add the router outlet (inline template)', () => {
+ makeInlineTemplate(appTree, '');
+ const tree = schematicRunner.runSchematic('appShell', defaultOptions, appTree);
+ const content = tree.read('/src/app/app.component.ts') || new Buffer('');
+ const matches = content.toString().match(/<\/router\-outlet>/g);
+ const numMatches = matches ? matches.length : 0;
+ expect(numMatches).toEqual(1);
+ });
+ });
+
+ it('should add router imports to server module', () => {
+ const tree = schematicRunner.runSchematic('appShell', defaultOptions, appTree);
+ const filePath = '/src/app/app.server.module.ts';
+ const content = tree.read(filePath) || new Buffer('');
+ // tslint:disable-next-line:max-line-length
+ expect(content.toString()).toMatch(/import { Routes, RouterModule } from \'@angular\/router\';/);
+ });
+
+ it('should define a server route', () => {
+ const tree = schematicRunner.runSchematic('appShell', defaultOptions, appTree);
+ const filePath = '/src/app/app.server.module.ts';
+ const content = tree.read(filePath) || new Buffer('');
+ expect(content.toString()).toMatch(/const routes: Routes = \[/);
+ });
+
+ it('should import RouterModule with forRoot', () => {
+ const tree = schematicRunner.runSchematic('appShell', defaultOptions, appTree);
+ const filePath = '/src/app/app.server.module.ts';
+ const content = tree.read(filePath) || new Buffer('');
+ // tslint:disable-next-line:max-line-length
+ expect(content.toString()).toMatch(/const routes: Routes = \[ { path: 'shell', component: AppShellComponent }\];/);
+ });
+
+ it('should create the shell component', () => {
+ const tree = schematicRunner.runSchematic('appShell', defaultOptions, appTree);
+ expect(tree.exists('/src/app/app-shell/app-shell.component.ts'));
+ const content = tree.read('/src/app/app.server.module.ts') || new Buffer('');
+ expect(content.toString()).toMatch(/app\-shell\.component/);
+ });
+});
diff --git a/packages/schematics/angular/app-shell/schema.d.ts b/packages/schematics/angular/app-shell/schema.d.ts
new file mode 100644
index 0000000000..628e324838
--- /dev/null
+++ b/packages/schematics/angular/app-shell/schema.d.ts
@@ -0,0 +1,71 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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
+ */
+
+export interface Schema {
+ /**
+ * Name or index of related client app.
+ */
+ clientApp?: string;
+ /**
+ * Name or index of related universal app.
+ */
+ universalApp: string;
+ /**
+ * Route path used to produce the app shell.
+ */
+ route?: string;
+ /**
+ * Name of the universal app
+ */
+ name?: string;
+ /**
+ * The appId to use withServerTransition.
+ */
+ appId?: string;
+ /**
+ * The output directory for build results.
+ */
+ outDir?: string;
+ /**
+ * The root directory of the app.
+ */
+ root?: string;
+ /**
+ * Name of the index file
+ */
+ index?: string;
+ /**
+ * The name of the main entry-point file.
+ */
+ main?: string;
+ /**
+ * The name of the test entry-point file.
+ */
+ test?: string;
+ /**
+ * The name of the TypeScript configuration file.
+ */
+ tsconfigFileName?: string;
+ /**
+ * The name of the TypeScript configuration file for tests.
+ */
+ testTsconfigFileName?: string;
+ /**
+ * The name of the applicatino directory.
+ */
+ appDir?: string;
+ /**
+ * The name of the root module file
+ */
+ rootModuleFileName?: string;
+ /**
+ * The name of the root module class.
+ */
+ rootModuleClassName?: string;
+ sourceDir?: string;
+}
diff --git a/packages/schematics/angular/app-shell/schema.json b/packages/schematics/angular/app-shell/schema.json
new file mode 100644
index 0000000000..27e8718eda
--- /dev/null
+++ b/packages/schematics/angular/app-shell/schema.json
@@ -0,0 +1,90 @@
+{
+ "$schema": "http://json-schema.org/schema",
+ "id": "SchematicsAngularAppShell",
+ "title": "Angular AppShell Options Schema",
+ "type": "object",
+ "properties": {
+ "clientApp": {
+ "type": "string",
+ "description": "Name or index of related client app."
+ },
+ "universalApp": {
+ "type": "string",
+ "description": "Name or index of related universal app."
+ },
+ "route": {
+ "type": "string",
+ "description": "Route path used to produce the app shell.",
+ "default": "shell"
+ },
+
+
+
+ "name": {
+ "type": "string",
+ "description": "Name of the universal app"
+ },
+ "appId": {
+ "type": "string",
+ "description": "The appId to use withServerTransition.",
+ "default": "serverApp"
+ },
+ "outDir": {
+ "type": "string",
+ "description": "The output directory for build results.",
+ "default": "dist-server/"
+ },
+ "root": {
+ "type": "string",
+ "description": "The root directory of the app.",
+ "default": "src"
+ },
+ "index": {
+ "type": "string",
+ "description": "Name of the index file",
+ "default": "index.html"
+ },
+ "main": {
+ "type": "string",
+ "description": "The name of the main entry-point file.",
+ "default": "main.server.ts"
+ },
+ "test": {
+ "type": "string",
+ "description": "The name of the test entry-point file."
+ },
+ "tsconfigFileName": {
+ "type": "string",
+ "default": "tsconfig.server",
+ "description": "The name of the TypeScript configuration file."
+ },
+ "testTsconfigFileName": {
+ "type": "string",
+ "description": "The name of the TypeScript configuration file for tests.",
+ "default": "tsconfig.spec"
+ },
+ "appDir": {
+ "type": "string",
+ "description": "The name of the applicatino directory.",
+ "default": "app"
+ },
+ "rootModuleFileName": {
+ "type": "string",
+ "description": "The name of the root module file",
+ "default": "app.server.module.ts"
+ },
+ "rootModuleClassName": {
+ "type": "string",
+ "description": "The name of the root module class.",
+ "default": "AppServerModule"
+ },
+ "sourceDir": {
+ "type": "string",
+ "default": "src",
+ "alias": "sd"
+ }
+ },
+ "required": [
+ "universalApp"
+ ]
+}
diff --git a/packages/schematics/angular/collection.json b/packages/schematics/angular/collection.json
index 3b6abcf597..1230c6a1db 100644
--- a/packages/schematics/angular/collection.json
+++ b/packages/schematics/angular/collection.json
@@ -63,6 +63,12 @@
"factory": "./universal",
"description": "Create an Angular universal app.",
"schema": "./universal/schema.json"
+ },
+ "appShell": {
+ "aliases": [ "app-shell" ],
+ "factory": "./app-shell",
+ "description": "Create an app shell.",
+ "schema": "./app-shell/schema.json"
}
}
}
diff --git a/packages/schematics/angular/universal/index.ts b/packages/schematics/angular/universal/index.ts
index 8111658a79..12fb034654 100644
--- a/packages/schematics/angular/universal/index.ts
+++ b/packages/schematics/angular/universal/index.ts
@@ -20,21 +20,27 @@ import {
import 'rxjs/add/operator/merge';
import * as ts from 'typescript';
import * as stringUtils from '../strings';
-import { findNode, getDecoratorMetadata, getSourceNodes } from '../utility/ast-utils';
+import { findNode, getDecoratorMetadata } from '../utility/ast-utils';
import { InsertChange } from '../utility/change';
import { AppConfig, getAppFromConfig, getConfig } from '../utility/config';
-import { findBootstrapModuleCall } from '../utility/ng-ast-utils';
+import { findBootstrapModuleCall, findBootstrapModulePath } from '../utility/ng-ast-utils';
import { Schema as UniversalOptions } from './schema';
function updateConfigFile(options: UniversalOptions): Rule {
return (host: Tree) => {
const config = getConfig(host);
- const clientApp = getAppFromConfig(config, options.clientApp);
+ const clientApp = getAppFromConfig(config, options.clientApp || '0');
if (clientApp === null) {
throw new SchematicsException('Client app not found.');
}
options.test = options.test || clientApp.test;
+
+ const tsCfg = options.tsconfigFileName && options.tsconfigFileName.endsWith('.json')
+ ? options.tsconfigFileName : `${options.tsconfigFileName}.json`;
+ const testTsCfg = options.testTsconfigFileName && options.testTsconfigFileName.endsWith('.json')
+ ? options.testTsconfigFileName : `${options.testTsconfigFileName}.json`;
+
const serverApp: AppConfig = {
...clientApp,
platform: 'server',
@@ -43,9 +49,12 @@ function updateConfigFile(options: UniversalOptions): Rule {
index: options.index,
main: options.main,
test: options.test,
- tsconfig: options.tsconfigFileName,
- testTsconfig: options.testTsconfigFileName,
+ tsconfig: tsCfg,
+ testTsconfig: testTsCfg,
};
+ if (options.name) {
+ serverApp.name = options.name;
+ }
if (!config.apps) {
config.apps = [];
}
@@ -57,35 +66,6 @@ function updateConfigFile(options: UniversalOptions): Rule {
};
}
-function findBootstrapModulePath(host: Tree, mainPath: string): string {
- const bootstrapCall = findBootstrapModuleCall(host, mainPath);
- if (!bootstrapCall) {
- throw new SchematicsException('Bootstrap call not found');
- }
-
- const bootstrapModule = bootstrapCall.arguments[0];
-
- const mainBuffer = host.read(mainPath);
- if (!mainBuffer) {
- throw new SchematicsException(`Client app main file (${mainPath}) not found`);
- }
- const mainText = mainBuffer.toString('utf-8');
- const source = ts.createSourceFile(mainPath, mainText, ts.ScriptTarget.Latest, true);
- const allNodes = getSourceNodes(source);
- const bootstrapModuleRelativePath = allNodes
- .filter(node => node.kind === ts.SyntaxKind.ImportDeclaration)
- .filter(imp => {
- return findNode(imp, ts.SyntaxKind.Identifier, bootstrapModule.getText());
- })
- .map((imp: ts.ImportDeclaration) => {
- const modulePathStringLiteral = imp.moduleSpecifier;
-
- return modulePathStringLiteral.text;
- })[0];
-
- return bootstrapModuleRelativePath;
-}
-
function findBrowserModuleImport(host: Tree, modulePath: string): ts.Node {
const moduleBuffer = host.read(modulePath);
if (!moduleBuffer) {
@@ -108,7 +88,7 @@ function findBrowserModuleImport(host: Tree, modulePath: string): ts.Node {
function wrapBootstrapCall(options: UniversalOptions): Rule {
return (host: Tree) => {
const config = getConfig(host);
- const clientApp = getAppFromConfig(config, options.clientApp);
+ const clientApp = getAppFromConfig(config, options.clientApp || '0');
if (clientApp === null) {
throw new SchematicsException('Client app not found.');
}
@@ -140,7 +120,7 @@ function wrapBootstrapCall(options: UniversalOptions): Rule {
function addServerTransition(options: UniversalOptions): Rule {
return (host: Tree) => {
const config = getConfig(host);
- const clientApp = getAppFromConfig(config, options.clientApp);
+ const clientApp = getAppFromConfig(config, options.clientApp || '0');
if (clientApp === null) {
throw new SchematicsException('Client app not found.');
}
@@ -172,8 +152,7 @@ function addDependencies(): Rule {
const pkg = JSON.parse(buffer.toString());
- const ngCoreVersion = Object.keys(pkg.dependencies)
- .filter((key: string) => key === '@angular/core')[0];
+ const ngCoreVersion = pkg.dependencies['@angular/core'];
pkg.dependencies['@angular/platform-server'] = ngCoreVersion;
host.overwrite(pkgPath, JSON.stringify(pkg, null, 2));
diff --git a/packages/schematics/angular/universal/index_spec.ts b/packages/schematics/angular/universal/index_spec.ts
index f1355a9a8b..fedf211a30 100644
--- a/packages/schematics/angular/universal/index_spec.ts
+++ b/packages/schematics/angular/universal/index_spec.ts
@@ -89,8 +89,8 @@ describe('Universal Schematic', () => {
expect(app.index).toEqual('index.html');
expect(app.main).toEqual('main.server.ts');
expect(app.test).toEqual('test.ts');
- expect(app.tsconfig).toEqual('tsconfig.server');
- expect(app.testTsconfig).toEqual('tsconfig.spec');
+ expect(app.tsconfig).toEqual('tsconfig.server.json');
+ expect(app.testTsconfig).toEqual('tsconfig.spec.json');
expect(app.environmentSource).toEqual('environments/environment.ts');
});
diff --git a/packages/schematics/angular/utility/ast-utils.ts b/packages/schematics/angular/utility/ast-utils.ts
index ec08ee6081..2f34665f5c 100644
--- a/packages/schematics/angular/utility/ast-utils.ts
+++ b/packages/schematics/angular/utility/ast-utils.ts
@@ -233,10 +233,13 @@ export function getDecoratorMetadata(source: ts.SourceFile, identifier: string,
.map(expr => expr.arguments[0] as ts.ObjectLiteralExpression);
}
-
-function _addSymbolToNgModuleMetadata(source: ts.SourceFile,
- ngModulePath: string, metadataField: string,
- symbolName: string, importPath: string): Change[] {
+export function addSymbolToNgModuleMetadata(
+ source: ts.SourceFile,
+ ngModulePath: string,
+ metadataField: string,
+ symbolName: string,
+ importPath: string | null = null,
+): Change[] {
const nodes = getDecoratorMetadata(source, 'NgModule', '@angular/core');
let node: any = nodes[0]; // tslint:disable-line:no-any
@@ -287,13 +290,15 @@ function _addSymbolToNgModuleMetadata(source: ts.SourceFile,
toInsert = `, ${metadataField}: [${symbolName}]`;
}
}
- const newMetadataProperty = new InsertChange(ngModulePath, position, toInsert);
- const newMetadataImport = insertImport(source,
- ngModulePath, symbolName.replace(/\..*$/, ''), importPath);
-
- return [newMetadataProperty, newMetadataImport];
+ if (importPath !== null) {
+ return [
+ new InsertChange(ngModulePath, position, toInsert),
+ insertImport(source, ngModulePath, symbolName.replace(/\..*$/, ''), importPath),
+ ];
+ } else {
+ return [new InsertChange(ngModulePath, position, toInsert)];
+ }
}
-
const assignment = matchingProperties[0] as ts.PropertyAssignment;
// If it's not an array, nothing we can do really.
@@ -358,11 +363,14 @@ function _addSymbolToNgModuleMetadata(source: ts.SourceFile,
toInsert = `, ${symbolName}`;
}
}
- const insert = new InsertChange(ngModulePath, position, toInsert);
- const importInsert: Change = insertImport(source,
- ngModulePath, symbolName.replace(/\..*$/, ''), importPath);
+ if (importPath !== null) {
+ return [
+ new InsertChange(ngModulePath, position, toInsert),
+ insertImport(source, ngModulePath, symbolName.replace(/\..*$/, ''), importPath),
+ ];
+ }
- return [insert, importInsert];
+ return [new InsertChange(ngModulePath, position, toInsert)];
}
/**
@@ -372,19 +380,18 @@ function _addSymbolToNgModuleMetadata(source: ts.SourceFile,
export function addDeclarationToModule(source: ts.SourceFile,
modulePath: string, classifiedName: string,
importPath: string): Change[] {
- return _addSymbolToNgModuleMetadata(source, modulePath, 'declarations', classifiedName,
- importPath);
+ return addSymbolToNgModuleMetadata(
+ source, modulePath, 'declarations', classifiedName, importPath);
}
/**
- * Custom function to insert a declaration (component, pipe, directive)
- * into NgModule declarations. It also imports the component.
+ * Custom function to insert an NgModule into NgModule imports. It also imports the module.
*/
export function addImportToModule(source: ts.SourceFile,
modulePath: string, classifiedName: string,
importPath: string): Change[] {
- return _addSymbolToNgModuleMetadata(source, modulePath, 'imports', classifiedName, importPath);
+ return addSymbolToNgModuleMetadata(source, modulePath, 'imports', classifiedName, importPath);
}
/**
@@ -393,7 +400,7 @@ export function addImportToModule(source: ts.SourceFile,
export function addProviderToModule(source: ts.SourceFile,
modulePath: string, classifiedName: string,
importPath: string): Change[] {
- return _addSymbolToNgModuleMetadata(source, modulePath, 'providers', classifiedName, importPath);
+ return addSymbolToNgModuleMetadata(source, modulePath, 'providers', classifiedName, importPath);
}
/**
@@ -402,7 +409,7 @@ export function addProviderToModule(source: ts.SourceFile,
export function addExportToModule(source: ts.SourceFile,
modulePath: string, classifiedName: string,
importPath: string): Change[] {
- return _addSymbolToNgModuleMetadata(source, modulePath, 'exports', classifiedName, importPath);
+ return addSymbolToNgModuleMetadata(source, modulePath, 'exports', classifiedName, importPath);
}
/**
@@ -411,5 +418,31 @@ export function addExportToModule(source: ts.SourceFile,
export function addBootstrapToModule(source: ts.SourceFile,
modulePath: string, classifiedName: string,
importPath: string): Change[] {
- return _addSymbolToNgModuleMetadata(source, modulePath, 'bootstrap', classifiedName, importPath);
+ return addSymbolToNgModuleMetadata(source, modulePath, 'bootstrap', classifiedName, importPath);
+}
+
+/**
+ * Determine if an import already exists.
+ */
+export function isImported(source: ts.SourceFile,
+ classifiedName: string,
+ importPath: string): boolean {
+ const allNodes = getSourceNodes(source);
+ const matchingNodes = allNodes
+ .filter(node => node.kind === ts.SyntaxKind.ImportDeclaration)
+ .filter((imp: ts.ImportDeclaration) => imp.moduleSpecifier.kind === ts.SyntaxKind.StringLiteral)
+ .filter((imp: ts.ImportDeclaration) => {
+ return ( imp.moduleSpecifier).text === importPath;
+ })
+ .filter((imp: ts.ImportDeclaration) => {
+ if (!imp.importClause) {
+ return false;
+ }
+ const nodes = findNodes(imp.importClause, ts.SyntaxKind.ImportSpecifier)
+ .filter(n => n.getText() === classifiedName);
+
+ return nodes.length > 0;
+ });
+
+ return matchingNodes.length > 0;
}
diff --git a/packages/schematics/angular/utility/ast-utils_spec.ts b/packages/schematics/angular/utility/ast-utils_spec.ts
index 9220d9af52..87cb4b0063 100644
--- a/packages/schematics/angular/utility/ast-utils_spec.ts
+++ b/packages/schematics/angular/utility/ast-utils_spec.ts
@@ -11,7 +11,7 @@ import { VirtualTree } from '@angular-devkit/schematics';
import * as ts from 'typescript';
import { Change, InsertChange } from '../utility/change';
import { getFileContent } from '../utility/test';
-import { addExportToModule } from './ast-utils';
+import { addExportToModule, addSymbolToNgModuleMetadata } from './ast-utils';
function getTsSource(path: string, content: string): ts.SourceFile {
@@ -65,11 +65,90 @@ describe('ast utils', () => {
});
it('should add export to module if not indented', () => {
- moduleContent = tags.stripIndent`${moduleContent}`;
+ moduleContent = tags.stripIndents`${moduleContent}`;
const source = getTsSource(modulePath, moduleContent);
const changes = addExportToModule(source, modulePath, 'FooComponent', './foo.component');
const output = applyChanges(modulePath, moduleContent, changes);
expect(output).toMatch(/import { FooComponent } from '.\/foo.component';/);
expect(output).toMatch(/exports: \[FooComponent\]/);
});
+
+ it('should add metadata', () => {
+ const source = getTsSource(modulePath, moduleContent);
+ const changes = addSymbolToNgModuleMetadata(source, modulePath, 'imports', 'HelloWorld');
+ expect(changes).not.toBeNull();
+
+ const output = applyChanges(modulePath, moduleContent, changes || []);
+ expect(output).toMatch(/imports: [\s\S]+,\n\s+HelloWorld\n\s+\]/m);
+ });
+
+ it('should add metadata (comma)', () => {
+ const moduleContent = `
+ import { BrowserModule } from '@angular/platform-browser';
+ import { NgModule } from '@angular/core';
+
+ @NgModule({
+ declarations: [
+ AppComponent
+ ],
+ imports: [
+ BrowserModule,
+ ],
+ providers: [],
+ bootstrap: [AppComponent]
+ })
+ export class AppModule { }
+ `;
+ const source = getTsSource(modulePath, moduleContent);
+ const changes = addSymbolToNgModuleMetadata(source, modulePath, 'imports', 'HelloWorld');
+ expect(changes).not.toBeNull();
+
+ const output = applyChanges(modulePath, moduleContent, changes || []);
+ expect(output).toMatch(/imports: [\s\S]+,\n\s+HelloWorld,\n\s+\]/m);
+ });
+
+ it('should add metadata (missing)', () => {
+ const moduleContent = `
+ import { BrowserModule } from '@angular/platform-browser';
+ import { NgModule } from '@angular/core';
+
+ @NgModule({
+ declarations: [
+ AppComponent
+ ],
+ providers: [],
+ bootstrap: [AppComponent]
+ })
+ export class AppModule { }
+ `;
+ const source = getTsSource(modulePath, moduleContent);
+ const changes = addSymbolToNgModuleMetadata(source, modulePath, 'imports', 'HelloWorld');
+ expect(changes).not.toBeNull();
+
+ const output = applyChanges(modulePath, moduleContent, changes || []);
+ expect(output).toMatch(/imports: \[HelloWorld]\r?\n/m);
+ });
+
+ it('should add metadata (empty)', () => {
+ const moduleContent = `
+ import { BrowserModule } from '@angular/platform-browser';
+ import { NgModule } from '@angular/core';
+
+ @NgModule({
+ declarations: [
+ AppComponent
+ ],
+ providers: [],
+ imports: [],
+ bootstrap: [AppComponent]
+ })
+ export class AppModule { }
+ `;
+ const source = getTsSource(modulePath, moduleContent);
+ const changes = addSymbolToNgModuleMetadata(source, modulePath, 'imports', 'HelloWorld');
+ expect(changes).not.toBeNull();
+
+ const output = applyChanges(modulePath, moduleContent, changes || []);
+ expect(output).toMatch(/imports: \[HelloWorld],\r?\n/m);
+ });
});
diff --git a/packages/schematics/angular/utility/config.ts b/packages/schematics/angular/utility/config.ts
index 2c626bbfb2..f80490dcd7 100644
--- a/packages/schematics/angular/utility/config.ts
+++ b/packages/schematics/angular/utility/config.ts
@@ -121,6 +121,10 @@ export interface AppConfig {
environments?: {
[name: string]: any; // tslint:disable-line:no-any
};
+ appShell?: {
+ app: string;
+ route: string;
+ };
}
export interface CliConfig {
@@ -448,7 +452,7 @@ export function getConfig(host: Tree): CliConfig {
return config;
}
-export function getAppFromConfig(config: CliConfig, appIndexOrName = '0'): AppConfig | null {
+export function getAppFromConfig(config: CliConfig, appIndexOrName: string): AppConfig | null {
if (!config.apps) {
return null;
}
diff --git a/packages/schematics/angular/utility/ng-ast-utils.ts b/packages/schematics/angular/utility/ng-ast-utils.ts
index e3351cd39a..67cb3e619f 100644
--- a/packages/schematics/angular/utility/ng-ast-utils.ts
+++ b/packages/schematics/angular/utility/ng-ast-utils.ts
@@ -5,9 +5,11 @@
* 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 { normalize } from '@angular-devkit/core';
import { SchematicsException, Tree } from '@angular-devkit/schematics';
import * as ts from 'typescript';
import { findNode, getSourceNodes } from '../utility/ast-utils';
+import { AppConfig } from '../utility/config';
export function findBootstrapModuleCall(host: Tree, mainPath: string): ts.CallExpression | null {
const mainBuffer = host.read(mainPath);
@@ -43,3 +45,40 @@ export function findBootstrapModuleCall(host: Tree, mainPath: string): ts.CallEx
return bootstrapCall;
}
+
+export function findBootstrapModulePath(host: Tree, mainPath: string): string {
+ const bootstrapCall = findBootstrapModuleCall(host, mainPath);
+ if (!bootstrapCall) {
+ throw new SchematicsException('Bootstrap call not found');
+ }
+
+ const bootstrapModule = bootstrapCall.arguments[0];
+
+ const mainBuffer = host.read(mainPath);
+ if (!mainBuffer) {
+ throw new SchematicsException(`Client app main file (${mainPath}) not found`);
+ }
+ const mainText = mainBuffer.toString('utf-8');
+ const source = ts.createSourceFile(mainPath, mainText, ts.ScriptTarget.Latest, true);
+ const allNodes = getSourceNodes(source);
+ const bootstrapModuleRelativePath = allNodes
+ .filter(node => node.kind === ts.SyntaxKind.ImportDeclaration)
+ .filter(imp => {
+ return findNode(imp, ts.SyntaxKind.Identifier, bootstrapModule.getText());
+ })
+ .map((imp: ts.ImportDeclaration) => {
+ const modulePathStringLiteral = imp.moduleSpecifier;
+
+ return modulePathStringLiteral.text;
+ })[0];
+
+ return bootstrapModuleRelativePath;
+}
+
+export function getAppModulePath(host: Tree, app: AppConfig) {
+ const mainPath = normalize(`/${app.root}/${app.main}`);
+ const moduleRelativePath = findBootstrapModulePath(host, mainPath);
+ const modulePath = normalize(`/${app.root}/${moduleRelativePath}.ts`);
+
+ return modulePath;
+}
From 3ac5865358492c9405f388e917d794ab15b8dc51 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Wed, 22 Nov 2017 18:04:18 -0800
Subject: [PATCH 016/807] fix(@schematics/angular): use a single recorder
Recorders are meant to be reused. Unless the refactor needs the new AST, we should
reuse the recorder for modulePath.
---
.../schematics/angular/app-shell/index.ts | 22 +++++++++----------
.../angular/app-shell/index_spec.ts | 6 +++--
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/packages/schematics/angular/app-shell/index.ts b/packages/schematics/angular/app-shell/index.ts
index a3fe909ce9..21e0d22d02 100644
--- a/packages/schematics/angular/app-shell/index.ts
+++ b/packages/schematics/angular/app-shell/index.ts
@@ -215,53 +215,51 @@ function addServerRoutes(options: AppShellOptions): Rule {
if (modulePath === null) {
throw new SchematicsException('Universal/server app not found.');
}
+
let moduleSource = getSourceFile(host, modulePath);
if (!isImported(moduleSource, 'Routes', '@angular/router')) {
+ const recorder = host.beginUpdate(modulePath);
const routesChange = insertImport(moduleSource,
modulePath,
'Routes',
'@angular/router') as InsertChange;
if (routesChange.toAdd) {
- const recorder = host.beginUpdate(modulePath);
recorder.insertLeft(routesChange.pos, routesChange.toAdd);
- host.commitUpdate(recorder);
}
- moduleSource = getSourceFile(host, modulePath);
+
const imports = getSourceNodes(moduleSource)
.filter(node => node.kind === ts.SyntaxKind.ImportDeclaration)
.sort((a, b) => a.getStart() - b.getStart());
const insertPosition = imports[imports.length - 1].getEnd();
const routeText =
`\n\nconst routes: Routes = [ { path: '${options.route}', component: AppShellComponent }];`;
- const routeRecorder = host.beginUpdate(modulePath);
- routeRecorder.insertRight(insertPosition, routeText);
- host.commitUpdate(routeRecorder);
+ recorder.insertRight(insertPosition, routeText);
+ host.commitUpdate(recorder);
}
- moduleSource = getSourceFile(host, modulePath);
+ moduleSource = getSourceFile(host, modulePath);
if (!isImported(moduleSource, 'RouterModule', '@angular/router')) {
+ const recorder = host.beginUpdate(modulePath);
const routerModuleChange = insertImport(moduleSource,
modulePath,
'RouterModule',
'@angular/router') as InsertChange;
if (routerModuleChange.toAdd) {
- const recorder = host.beginUpdate(modulePath);
recorder.insertLeft(routerModuleChange.pos, routerModuleChange.toAdd);
- host.commitUpdate(recorder);
}
+
const metadataChange = addSymbolToNgModuleMetadata(
moduleSource, modulePath, 'imports', 'RouterModule.forRoot(routes)');
-
if (metadataChange) {
- const recorder = host.beginUpdate(modulePath);
metadataChange.forEach((change: InsertChange) => {
recorder.insertRight(change.pos, change.toAdd);
});
- host.commitUpdate(recorder);
}
+ host.commitUpdate(recorder);
}
+
return host;
};
}
diff --git a/packages/schematics/angular/app-shell/index_spec.ts b/packages/schematics/angular/app-shell/index_spec.ts
index d869c7913e..ad21a49604 100644
--- a/packages/schematics/angular/app-shell/index_spec.ts
+++ b/packages/schematics/angular/app-shell/index_spec.ts
@@ -151,8 +151,10 @@ describe('App Shell Schematic', () => {
const tree = schematicRunner.runSchematic('appShell', defaultOptions, appTree);
const filePath = '/src/app/app.server.module.ts';
const content = tree.read(filePath) || new Buffer('');
- // tslint:disable-next-line:max-line-length
- expect(content.toString()).toMatch(/const routes: Routes = \[ { path: 'shell', component: AppShellComponent }\];/);
+ expect(content.toString())
+ .toMatch(/const routes: Routes = \[ { path: 'shell', component: AppShellComponent }\];/);
+ expect(content.toString())
+ .toMatch(/ServerModule,\r?\n\s*RouterModule\.forRoot\(routes\),/);
});
it('should create the shell component', () => {
From 3510fa3da9acaab36b7c451d40ec6c7806abc57d Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Wed, 22 Nov 2017 18:59:50 -0800
Subject: [PATCH 017/807] release: patch
---
.monorepo.json | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/.monorepo.json b/.monorepo.json
index eb8999ccd2..f85370bbc5 100644
--- a/.monorepo.json
+++ b/.monorepo.json
@@ -42,8 +42,8 @@
},
"packages": {
"@_/benchmark": {
- "version": "0.0.16",
- "hash": "b1f9f2d8e1eca2a865d39263f0ca5a38"
+ "version": "0.0.17",
+ "hash": "37ed7e417435c92dbf301e7b26ea37ca"
},
"@angular-devkit/build-optimizer": {
"name": "Build Optimizer",
@@ -58,8 +58,8 @@
},
"@angular-devkit/core": {
"name": "Core",
- "version": "0.0.20",
- "hash": "4b3f535f049fba6c9d9f729f3b68e73c"
+ "version": "0.0.21",
+ "hash": "de94633f78fdf7133aa7d096d2c63904"
},
"@angular-devkit/schematics": {
"name": "Schematics",
@@ -69,20 +69,20 @@
"url": "https://github.com/angular/devkit/blob/master/packages/angular_devkit/schematics/README.md"
}
],
- "version": "0.0.36",
- "hash": "cbde94934c9c70852e98edb46bc88e2d"
+ "version": "0.0.37",
+ "hash": "13281876c53fce8f7da980aa95f667b9"
},
"@schematics/angular": {
"name": "Angular Schematics",
"section": "Schematics",
- "version": "0.1.5",
- "hash": "83b90a55d09282a91f4da4f53d39ad3c"
+ "version": "0.1.6",
+ "hash": "2ba6e051a1fd9f07fd8f2ff37f83664b"
},
"@schematics/schematics": {
"name": "Schematics Schematics",
- "version": "0.0.6",
+ "version": "0.0.7",
"section": "Schematics",
- "hash": "570c076f9bd85e7acb061adf921ed1a6"
+ "hash": "263a5203aeb7bc7ed9cdbd207e3b251e"
}
}
}
From 61e578bceb9164454231a1cc698826754be125e1 Mon Sep 17 00:00:00 2001
From: Mike Brocchi
Date: Wed, 22 Nov 2017 22:56:01 -0500
Subject: [PATCH 018/807] fix(@schematics/angular): Update new app component
template for linting rules
---
.../angular/application/other-files/app.component.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/schematics/angular/application/other-files/app.component.html b/packages/schematics/angular/application/other-files/app.component.html
index 0001f4d4e6..45d45d0889 100644
--- a/packages/schematics/angular/application/other-files/app.component.html
+++ b/packages/schematics/angular/application/other-files/app.component.html
@@ -1,7 +1,7 @@
- Welcome to {{title}}!
+ Welcome to {{ title }}!
From 049c1b167f7150ba4b43b537a5f3c0c41036a98f Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Wed, 22 Nov 2017 21:52:42 -0800
Subject: [PATCH 019/807] release: patch
---
.monorepo.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.monorepo.json b/.monorepo.json
index f85370bbc5..69a02a2619 100644
--- a/.monorepo.json
+++ b/.monorepo.json
@@ -75,8 +75,8 @@
"@schematics/angular": {
"name": "Angular Schematics",
"section": "Schematics",
- "version": "0.1.6",
- "hash": "2ba6e051a1fd9f07fd8f2ff37f83664b"
+ "version": "0.1.7",
+ "hash": "7105f8c10221f1cc790725b050b61163"
},
"@schematics/schematics": {
"name": "Schematics Schematics",
From 8e07970d3dbb2382964705283f6e83299370eee8 Mon Sep 17 00:00:00 2001
From: Charles Lyding <19598772+clydin@users.noreply.github.com>
Date: Fri, 24 Nov 2017 16:28:57 -0500
Subject: [PATCH 020/807] refactor(@angular-devkit/build-optimizer): use TS2.6
and remove old helpers
---
.../build_optimizer/package.json | 2 +-
.../src/transforms/prefix-classes.ts | 78 +++++--------------
.../src/transforms/wrap-enums.ts | 22 +-----
3 files changed, 23 insertions(+), 79 deletions(-)
diff --git a/packages/angular_devkit/build_optimizer/package.json b/packages/angular_devkit/build_optimizer/package.json
index 23807ad81f..a986fb2541 100644
--- a/packages/angular_devkit/build_optimizer/package.json
+++ b/packages/angular_devkit/build_optimizer/package.json
@@ -14,7 +14,7 @@
"dependencies": {
"loader-utils": "^1.1.0",
"source-map": "^0.5.6",
- "typescript": "^2.3.3",
+ "typescript": "~2.6.1",
"webpack-sources": "^1.0.1"
}
}
diff --git a/packages/angular_devkit/build_optimizer/src/transforms/prefix-classes.ts b/packages/angular_devkit/build_optimizer/src/transforms/prefix-classes.ts
index ab534f3572..a5402a696b 100644
--- a/packages/angular_devkit/build_optimizer/src/transforms/prefix-classes.ts
+++ b/packages/angular_devkit/build_optimizer/src/transforms/prefix-classes.ts
@@ -46,7 +46,7 @@ export function getPrefixClassesTransformer(): ts.TransformerFactory => {
// Add pure comment to downleveled classes.
- if (isVariableStatement(node) && isDownleveledClass(node)) {
+ if (ts.isVariableStatement(node) && isDownleveledClass(node)) {
const varDecl = node.declarationList.declarations[0];
const varInitializer = varDecl.initializer as ts.Expression;
@@ -87,54 +87,10 @@ export function getPrefixClassesTransformer(): ts.TransformerFactory 1) {
+ if (!ts.isCallExpression(potentialClass) || potentialClass.arguments.length > 1) {
return false;
}
let wrapperBody: ts.Block;
- if (isFunctionExpression(potentialClass.expression)) {
+ if (ts.isFunctionExpression(potentialClass.expression)) {
wrapperBody = potentialClass.expression.body;
- } else if (isArrowFunction(potentialClass.expression)
- && isBlock(potentialClass.expression.body)) {
+ } else if (ts.isArrowFunction(potentialClass.expression)
+ && ts.isBlock(potentialClass.expression.body)) {
wrapperBody = potentialClass.expression.body;
} else {
return false;
@@ -192,7 +148,7 @@ function isDownleveledClass(node: ts.Node): boolean {
// find return statement - may not be last statement
let returnStatement: ts.ReturnStatement | undefined;
for (let i = functionStatements.length - 1; i > 0; i--) {
- if (isReturnStatement(functionStatements[i])) {
+ if (ts.isReturnStatement(functionStatements[i])) {
returnStatement = functionStatements[i] as ts.ReturnStatement;
break;
}
@@ -200,13 +156,13 @@ function isDownleveledClass(node: ts.Node): boolean {
if (returnStatement == undefined
|| returnStatement.expression == undefined
- || !isIdentifier(returnStatement.expression)) {
+ || !ts.isIdentifier(returnStatement.expression)) {
return false;
}
if (functionExpression.parameters.length === 0) {
// potential non-extended class or wrapped es2015 class
- return (isFunctionDeclaration(firstStatement) || isClassDeclaration(firstStatement))
+ return (ts.isFunctionDeclaration(firstStatement) || ts.isClassDeclaration(firstStatement))
&& firstStatement.name !== undefined
&& firstStatement.name.text === className
&& returnStatement.expression.text === firstStatement.name.text;
@@ -218,7 +174,8 @@ function isDownleveledClass(node: ts.Node): boolean {
const functionParameter = functionExpression.parameters[0];
- if (!isIdentifier(functionParameter.name) || functionParameter.name.text !== superParameterName) {
+ if (!ts.isIdentifier(functionParameter.name)
+ || functionParameter.name.text !== superParameterName) {
return false;
}
@@ -226,13 +183,14 @@ function isDownleveledClass(node: ts.Node): boolean {
return false;
}
- if (!isExpressionStatement(firstStatement) || !isCallExpression(firstStatement.expression)) {
+ if (!ts.isExpressionStatement(firstStatement)
+ || !ts.isCallExpression(firstStatement.expression)) {
return false;
}
const extendCallExpression = firstStatement.expression;
- if (!isIdentifier(extendCallExpression.expression)
+ if (!ts.isIdentifier(extendCallExpression.expression)
|| !extendCallExpression.expression.text.endsWith(extendsHelperName)) {
return false;
}
@@ -243,13 +201,13 @@ function isDownleveledClass(node: ts.Node): boolean {
const lastArgument = extendCallExpression.arguments[extendCallExpression.arguments.length - 1];
- if (!isIdentifier(lastArgument) || lastArgument.text !== functionParameter.name.text) {
+ if (!ts.isIdentifier(lastArgument) || lastArgument.text !== functionParameter.name.text) {
return false;
}
const secondStatement = functionStatements[1];
- return isFunctionDeclaration(secondStatement)
+ return ts.isFunctionDeclaration(secondStatement)
&& secondStatement.name !== undefined
&& className.endsWith(secondStatement.name.text)
&& returnStatement.expression.text === secondStatement.name.text;
diff --git a/packages/angular_devkit/build_optimizer/src/transforms/wrap-enums.ts b/packages/angular_devkit/build_optimizer/src/transforms/wrap-enums.ts
index 8026591250..267c246a4a 100644
--- a/packages/angular_devkit/build_optimizer/src/transforms/wrap-enums.ts
+++ b/packages/angular_devkit/build_optimizer/src/transforms/wrap-enums.ts
@@ -29,20 +29,6 @@ function isBlockLike(node: ts.Node): node is ts.BlockLike {
|| node.kind === ts.SyntaxKind.SourceFile;
}
-// NOTE: 'isXXXX' helper functions can be replaced with native TS helpers with TS 2.4+
-
-function isVariableStatement(node: ts.Node): node is ts.VariableStatement {
- return node.kind === ts.SyntaxKind.VariableStatement;
-}
-
-function isIdentifier(node: ts.Node): node is ts.Identifier {
- return node.kind === ts.SyntaxKind.Identifier;
-}
-
-function isObjectLiteralExpression(node: ts.Node): node is ts.ObjectLiteralExpression {
- return node.kind === ts.SyntaxKind.ObjectLiteralExpression;
-}
-
export function getWrapEnumsTransformer(): ts.TransformerFactory {
return (context: ts.TransformationContext): ts.Transformer => {
const transformer: ts.Transformer = (sf: ts.SourceFile) => {
@@ -104,11 +90,11 @@ function visitBlockStatements(
// * have only one declaration
// * have an identifer as a declaration name
if (oIndex < statements.length - 1
- && isVariableStatement(currentStatement)
+ && ts.isVariableStatement(currentStatement)
&& currentStatement.declarationList.declarations.length === 1) {
const variableDeclaration = currentStatement.declarationList.declarations[0];
- if (isIdentifier(variableDeclaration.name)) {
+ if (ts.isIdentifier(variableDeclaration.name)) {
const name = variableDeclaration.name.text;
if (!variableDeclaration.initializer) {
@@ -129,7 +115,7 @@ function visitBlockStatements(
oIndex++;
continue;
}
- } else if (isObjectLiteralExpression(variableDeclaration.initializer)
+ } else if (ts.isObjectLiteralExpression(variableDeclaration.initializer)
&& variableDeclaration.initializer.properties.length === 0) {
const nextStatements = statements.slice(oIndex + 1);
const enumStatements = findTs2_2EnumStatements(name, nextStatements);
@@ -149,7 +135,7 @@ function visitBlockStatements(
oIndex += enumStatements.length;
continue;
}
- } else if (isObjectLiteralExpression(variableDeclaration.initializer)
+ } else if (ts.isObjectLiteralExpression(variableDeclaration.initializer)
&& variableDeclaration.initializer.properties.length !== 0) {
const literalPropertyCount = variableDeclaration.initializer.properties.length;
const nextStatements = statements.slice(oIndex + 1);
From 14422040b724b66e960260b0c2217ef770926604 Mon Sep 17 00:00:00 2001
From: Charles Lyding <19598772+clydin@users.noreply.github.com>
Date: Fri, 24 Nov 2017 19:48:06 -0500
Subject: [PATCH 021/807] refactor(@angular-devkit/build-optimizer): leverage
TS2.6 in tslib pass
---
.../src/transforms/import-tslib.ts | 79 +++++--------------
1 file changed, 19 insertions(+), 60 deletions(-)
diff --git a/packages/angular_devkit/build_optimizer/src/transforms/import-tslib.ts b/packages/angular_devkit/build_optimizer/src/transforms/import-tslib.ts
index 9880900f42..4e5e2bf282 100644
--- a/packages/angular_devkit/build_optimizer/src/transforms/import-tslib.ts
+++ b/packages/angular_devkit/build_optimizer/src/transforms/import-tslib.ts
@@ -30,30 +30,33 @@ export function getImportTslibTransformer(): ts.TransformerFactory {
- // Check if node is a TS helper declaration.
- if (isTsHelper(node)) {
- // Replace node with import for that helper.
- return ts.visitEachChild(createTslibImport(node, useRequire), visitor, context);
+ // Check if node is a TS helper declaration and replace with import if yes
+ if (ts.isVariableStatement(node)) {
+ const declarations = node.declarationList.declarations;
+
+ if (declarations.length === 1 && ts.isIdentifier(declarations[0].name)) {
+ // NOTE: the replace is unnecessary with TS2.5+; tests currently run with TS2.4
+ const name = (declarations[0].name as ts.Identifier).text.replace(/^___/, '__');
+
+ if (isHelperName(name)) {
+ // TODO: maybe add a few more checks, like checking the first part of the assignment.
+
+ return createTslibImport(name, useRequire);
+ }
+ }
}
- // Otherwise return node as is.
return ts.visitEachChild(node, visitor, context);
};
- return ts.visitNode(sf, visitor);
+ return ts.visitEachChild(sf, visitor, context);
};
return transformer;
};
}
-function createTslibImport(node: ts.Node, useRequire = false): ts.Node {
- const name = getVariableStatementName(node);
-
- if (!name) {
- return node;
- }
-
+function createTslibImport(name: string, useRequire = false): ts.Node {
if (useRequire) {
// Use `var __helper = /*@__PURE__*/ require("tslib").__helper`.
const requireCall = ts.createCall(ts.createIdentifier('require'), undefined,
@@ -69,11 +72,7 @@ function createTslibImport(node: ts.Node, useRequire = false): ts.Node {
// Use `import { __helper } from "tslib"`.
const namedImports = ts.createNamedImports([ts.createImportSpecifier(undefined,
ts.createIdentifier(name))]);
- // typescript@2.4 is needed for a fix to the function parameter types of ts.createImportClause.
- // https://github.com/Microsoft/TypeScript/pull/15999
- // Hiding it from lint until we upgrade.
- // tslint:disable-next-line:no-any
- const importClause = (ts.createImportClause as any)(undefined, namedImports);
+ const importClause = ts.createImportClause(undefined, namedImports);
const newNode = ts.createImportDeclaration(undefined, undefined, importClause,
ts.createLiteral('tslib'));
@@ -81,25 +80,7 @@ function createTslibImport(node: ts.Node, useRequire = false): ts.Node {
}
}
-function isTsHelper(node: ts.Node): boolean {
- if (node.kind !== ts.SyntaxKind.VariableStatement) {
- return false;
- }
- const varStmt = node as ts.VariableStatement;
- if (varStmt.declarationList.declarations.length > 1) {
- return false;
- }
- const varDecl = varStmt.declarationList.declarations[0];
- if (varDecl.name.kind !== ts.SyntaxKind.Identifier) {
- return false;
- }
-
- const name = getVariableStatementName(node);
-
- if (!name) {
- return false;
- }
-
+function isHelperName(name: string): boolean {
// TODO: there are more helpers than these, should we replace them all?
const tsHelpers = [
'__extends',
@@ -108,27 +89,5 @@ function isTsHelper(node: ts.Node): boolean {
'__param',
];
- if (tsHelpers.indexOf(name) === -1) {
- return false;
- }
-
- // TODO: maybe add a few more checks, like checking the first part of the assignment.
-
- return true;
-}
-
-function getVariableStatementName(node: ts.Node) {
- const varStmt = node as ts.VariableStatement;
- if (varStmt.declarationList.declarations.length > 1) {
- return null;
- }
- const varDecl = varStmt.declarationList.declarations[0];
- if (varDecl.name.kind !== ts.SyntaxKind.Identifier) {
- return null;
- }
-
- const name = (varDecl.name as ts.Identifier).text;
-
- // node.getText() on a name that starts with two underscores will return three instead.
- return name.replace(/^___/, '__');
+ return tsHelpers.indexOf(name) !== -1;
}
From fbd4d419105f878021fa6a1fa11827587674b960 Mon Sep 17 00:00:00 2001
From: Charles Lyding <19598772+clydin@users.noreply.github.com>
Date: Fri, 24 Nov 2017 20:19:38 -0500
Subject: [PATCH 022/807] test(@angular-devkit/build-optimizer): update
comments for TS2.6
---
.../build_optimizer/src/transforms/prefix-classes_spec.ts | 6 +++---
.../build_optimizer/src/transforms/wrap-enums_spec.ts | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/packages/angular_devkit/build_optimizer/src/transforms/prefix-classes_spec.ts b/packages/angular_devkit/build_optimizer/src/transforms/prefix-classes_spec.ts
index 2944b19eac..c0a3cae25c 100644
--- a/packages/angular_devkit/build_optimizer/src/transforms/prefix-classes_spec.ts
+++ b/packages/angular_devkit/build_optimizer/src/transforms/prefix-classes_spec.ts
@@ -151,7 +151,7 @@ describe('prefix-classes', () => {
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
- it('prefix TS 2.5 downlevel class', () => {
+ it('prefix TS 2.5 - 2.6 downlevel class', () => {
const input = tags.stripIndent`
var BasicTestCase = /** @class */ (function () {
function BasicTestCase() {
@@ -171,7 +171,7 @@ describe('prefix-classes', () => {
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
- it('prefix TS 2.5 downlevel class with static variable', () => {
+ it('prefix TS 2.5 - 2.6 downlevel class with static variable', () => {
const input = tags.stripIndent`
var StaticTestCase = /** @class */ (function () {
function StaticTestCase() {
@@ -193,7 +193,7 @@ describe('prefix-classes', () => {
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
- it('prefix TS 2.5 downlevel class with extends', () => {
+ it('prefix TS 2.5 - 2.6 downlevel class with extends', () => {
const input = tags.stripIndent`
var ExtendedClass = /** @class */ (function (_super) {
__extends(ExtendedClass, _super);
diff --git a/packages/angular_devkit/build_optimizer/src/transforms/wrap-enums_spec.ts b/packages/angular_devkit/build_optimizer/src/transforms/wrap-enums_spec.ts
index 5f41c7aef1..e4d7f3780e 100644
--- a/packages/angular_devkit/build_optimizer/src/transforms/wrap-enums_spec.ts
+++ b/packages/angular_devkit/build_optimizer/src/transforms/wrap-enums_spec.ts
@@ -37,7 +37,7 @@ describe('wrap-enums', () => {
expect(tags.oneLine`${transform(input)}`).toEqual(tags.oneLine`${output}`);
});
- it('wraps ts 2.3 enums in IIFE', () => {
+ it('wraps ts 2.3 - 2.6 enums in IIFE', () => {
const input = tags.stripIndent`
export var ChangeDetectionStrategy;
(function (ChangeDetectionStrategy) {
From 7f1ffadc42288842d7d2535c48728f02b9287242 Mon Sep 17 00:00:00 2001
From: Trotyl Yu
Date: Wed, 1 Nov 2017 03:17:21 -0500
Subject: [PATCH 023/807] docs(@schematics/angular): adjust statement of
Zone.js prolyfill
---
.../schematics/angular/application/files/__path__/polyfills.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/schematics/angular/application/files/__path__/polyfills.ts b/packages/schematics/angular/application/files/__path__/polyfills.ts
index 20d40751a6..5db51b0179 100644
--- a/packages/schematics/angular/application/files/__path__/polyfills.ts
+++ b/packages/schematics/angular/application/files/__path__/polyfills.ts
@@ -55,7 +55,7 @@ import 'core-js/es7/reflect';
/***************************************************************************************************
- * Zone JS is required by Angular itself.
+ * Zone JS is required by default for Angular itself.
*/
import 'zone.js/dist/zone'; // Included with Angular CLI.
From b2fd67e8f0410d64c94bbd84d26dc40f6507b4a8 Mon Sep 17 00:00:00 2001
From: cexbrayat
Date: Thu, 16 Nov 2017 17:51:27 -0500
Subject: [PATCH 024/807] fix(@schematics/angular): remove Intl polyfill
---
.../angular/application/files/__path__/polyfills.ts | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/packages/schematics/angular/application/files/__path__/polyfills.ts b/packages/schematics/angular/application/files/__path__/polyfills.ts
index 5db51b0179..d68672ffe4 100644
--- a/packages/schematics/angular/application/files/__path__/polyfills.ts
+++ b/packages/schematics/angular/application/files/__path__/polyfills.ts
@@ -64,13 +64,3 @@ import 'zone.js/dist/zone'; // Included with Angular CLI.
/***************************************************************************************************
* APPLICATION IMPORTS
*/
-
-/**
- * Date, currency, decimal and percent pipes.
- * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10
- */
-// import 'intl'; // Run `npm install --save intl`.
-/**
- * Need to import at least one locale-data with intl.
- */
-// import 'intl/locale-data/jsonp/en';
From 1b0f96c99da6022238f96949e1f3715d78d1c129 Mon Sep 17 00:00:00 2001
From: cexbrayat
Date: Fri, 24 Nov 2017 16:49:18 -0500
Subject: [PATCH 025/807] fix(@schematics/angular): typos in universal schema
---
packages/schematics/angular/app-shell/schema.d.ts | 2 +-
packages/schematics/angular/app-shell/schema.json | 2 +-
packages/schematics/angular/universal/schema.d.ts | 2 +-
packages/schematics/angular/universal/schema.json | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/packages/schematics/angular/app-shell/schema.d.ts b/packages/schematics/angular/app-shell/schema.d.ts
index 628e324838..c814cd9379 100644
--- a/packages/schematics/angular/app-shell/schema.d.ts
+++ b/packages/schematics/angular/app-shell/schema.d.ts
@@ -56,7 +56,7 @@ export interface Schema {
*/
testTsconfigFileName?: string;
/**
- * The name of the applicatino directory.
+ * The name of the application directory.
*/
appDir?: string;
/**
diff --git a/packages/schematics/angular/app-shell/schema.json b/packages/schematics/angular/app-shell/schema.json
index 27e8718eda..ae7a214373 100644
--- a/packages/schematics/angular/app-shell/schema.json
+++ b/packages/schematics/angular/app-shell/schema.json
@@ -65,7 +65,7 @@
},
"appDir": {
"type": "string",
- "description": "The name of the applicatino directory.",
+ "description": "The name of the application directory.",
"default": "app"
},
"rootModuleFileName": {
diff --git a/packages/schematics/angular/universal/schema.d.ts b/packages/schematics/angular/universal/schema.d.ts
index 86fc582004..33b023c73f 100644
--- a/packages/schematics/angular/universal/schema.d.ts
+++ b/packages/schematics/angular/universal/schema.d.ts
@@ -48,7 +48,7 @@ export interface Schema {
*/
testTsconfigFileName?: string;
/**
- * The name of the applicatino directory.
+ * The name of the application directory.
*/
appDir?: string;
/**
diff --git a/packages/schematics/angular/universal/schema.json b/packages/schematics/angular/universal/schema.json
index fea4be93ed..87c26fd161 100644
--- a/packages/schematics/angular/universal/schema.json
+++ b/packages/schematics/angular/universal/schema.json
@@ -54,7 +54,7 @@
},
"appDir": {
"type": "string",
- "description": "The name of the applicatino directory.",
+ "description": "The name of the application directory.",
"default": "app"
},
"rootModuleFileName": {
From 6fd6690c923f06ebc4a51ecbd5495b9479ccacb1 Mon Sep 17 00:00:00 2001
From: WilliamKoza
Date: Mon, 27 Nov 2017 17:21:01 +0100
Subject: [PATCH 026/807] feat(@schematics/angular): add deprecation rule
---
packages/schematics/angular/application/files/tslint.json | 3 +++
1 file changed, 3 insertions(+)
diff --git a/packages/schematics/angular/application/files/tslint.json b/packages/schematics/angular/application/files/tslint.json
index 1f8ed16bed..f1a84a4087 100644
--- a/packages/schematics/angular/application/files/tslint.json
+++ b/packages/schematics/angular/application/files/tslint.json
@@ -11,6 +11,9 @@
"check-space"
],
"curly": true,
+ "deprecation": {
+ "severity": "warn"
+ },
"eofline": true,
"forin": true,
"import-blacklist": [
From 203f9568c5ff7b18b457f2faf72eb4aa4995ce63 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Sun, 29 Oct 2017 11:45:34 -0700
Subject: [PATCH 027/807] feat(@angular-devkit/core): add support for color and
no-color
And namespace the terminal.
---
.../angular_devkit/core/src/terminal/caps.ts | 189 ++++++++++++++++++
.../core/src/terminal/{ansi.ts => colors.ts} | 0
.../angular_devkit/core/src/terminal/index.ts | 5 +-
.../angular_devkit/core/src/terminal/text.ts | 39 ++++
scripts/benchmark.ts | 6 +-
5 files changed, 235 insertions(+), 4 deletions(-)
create mode 100644 packages/angular_devkit/core/src/terminal/caps.ts
rename packages/angular_devkit/core/src/terminal/{ansi.ts => colors.ts} (100%)
create mode 100644 packages/angular_devkit/core/src/terminal/text.ts
diff --git a/packages/angular_devkit/core/src/terminal/caps.ts b/packages/angular_devkit/core/src/terminal/caps.ts
new file mode 100644
index 0000000000..b93095d7a3
--- /dev/null
+++ b/packages/angular_devkit/core/src/terminal/caps.ts
@@ -0,0 +1,189 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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 ReadableStream = NodeJS.ReadableStream;
+import WriteStream = NodeJS.WriteStream;
+import Socket = NodeJS.Socket;
+
+
+/**
+ * Node specific stuff.
+ */
+declare const process: {
+ env: { [name: string]: string };
+ platform: string;
+ versions: {
+ node: string;
+ };
+
+ stdin: ReadableStream;
+ stdout: WriteStream;
+ stderr: WriteStream;
+};
+declare const os: {
+ release: () => string;
+};
+
+
+const _env = (typeof process == 'object' && process.env) || {};
+const _platform = (typeof process == 'object' && process.platform) || '';
+const _versions = (typeof process == 'object' && process.versions) || { node: '' };
+const _os = (typeof os == 'object' && os) || { release: () => '' };
+
+const streamMap = new WeakMap<{}, StreamCapabilities>();
+
+
+export interface StreamCapabilities {
+ readable: boolean;
+ writable: boolean;
+
+ /**
+ * Supports text. This should be true for any streams.
+ */
+ text: boolean;
+
+ /**
+ * Supports colors (16 colors).
+ */
+ colors: boolean;
+
+ /**
+ * Supports 256 colors.
+ */
+ color256: boolean;
+
+ /**
+ * Supports 16 millions (3x8-bit channels) colors.
+ */
+ color16m: boolean;
+
+ /**
+ * Height of the terminal. If the stream is not tied to a terminal, will be null.
+ */
+ rows: number | null;
+
+ /**
+ * Width of the terminal. If the stream is not tied to a terminal, will be null.
+ */
+ columns: number | null;
+}
+
+
+const ciVars = ['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'];
+
+
+function _getColorLevel(stream: Socket): number {
+ if (stream && !stream.isTTY) {
+ return 0;
+ }
+
+ if (_platform.startsWith('win32')) {
+ // Node.js 7.5.0 is the first version of Node.js to include a patch to
+ // libuv that enables 256 color output on Windows. Anything earlier and it
+ // won't work. However, here we target Node.js 8 at minimum as it is an LTS
+ // release, and Node.js 7 is not. Windows 10 build 10586 is the first Windows
+ // release that supports 256 colors.
+ const osRelease = _os.release().split('.');
+ if (Number(_versions.node.split('.')[0]) >= 8
+ && Number(osRelease[0]) >= 10
+ && Number(osRelease[2]) >= 10586) {
+ return 2;
+ }
+
+ return 1;
+ }
+
+ if ('CI' in _env) {
+ if (ciVars.some(sign => sign in _env) || _env.CI_NAME === 'codeship') {
+ return 1;
+ }
+
+ return 0;
+ }
+
+ if ('TEAMCITY_VERSION' in _env) {
+ return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(_env.TEAMCITY_VERSION) ? 1 : 0;
+ }
+
+ if ('TERM_PROGRAM' in _env) {
+ const version = parseInt((_env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);
+
+ switch (_env.TERM_PROGRAM) {
+ case 'iTerm.app':
+ return version >= 3 ? 3 : 2;
+ case 'Hyper':
+ return 3;
+ case 'Apple_Terminal':
+ return 2;
+
+ // No default
+ }
+ }
+
+ if (/-256(color)?$/i.test(_env.TERM)) {
+ return 2;
+ }
+
+ if (/^screen|^xterm|^vt100|^rxvt|color|ansi|cygwin|linux/i.test(_env.TERM)) {
+ return 1;
+ }
+
+ if ('COLORTERM' in _env) {
+ return 1;
+ }
+
+ if (_env.TERM === 'dumb') {
+ return 0;
+ }
+
+ return 0;
+}
+
+
+function _getRows() {
+ return process.stdout.rows || null;
+}
+function _getColumns() {
+ return process.stdout.columns || null;
+}
+
+
+function _createCapabilities(stream: Socket, isTerminalStream: boolean): StreamCapabilities {
+ const level = _getColorLevel(stream);
+
+ return {
+ readable: stream.readable,
+ writable: stream.writable,
+ text: true,
+
+ colors: level > 0,
+ color256: level > 1,
+ color16m: level > 2,
+
+ rows: isTerminalStream ? _getRows() : null,
+ columns: isTerminalStream ? _getColumns() : null,
+ };
+}
+
+
+export function getCapabilities(
+ stream: Socket,
+ isTerminalStream = !!stream.isTTY,
+): StreamCapabilities {
+ let maybeCaps = streamMap.get(stream);
+ if (!maybeCaps) {
+ maybeCaps = _createCapabilities(stream, isTerminalStream);
+ streamMap.set(stream, maybeCaps);
+ }
+
+ return maybeCaps;
+}
+
+
+export const stdin = getCapabilities(process.stdin as Socket);
+export const stdout = getCapabilities(process.stdout);
+export const stderr = getCapabilities(process.stderr);
diff --git a/packages/angular_devkit/core/src/terminal/ansi.ts b/packages/angular_devkit/core/src/terminal/colors.ts
similarity index 100%
rename from packages/angular_devkit/core/src/terminal/ansi.ts
rename to packages/angular_devkit/core/src/terminal/colors.ts
diff --git a/packages/angular_devkit/core/src/terminal/index.ts b/packages/angular_devkit/core/src/terminal/index.ts
index 02e84c1016..e4bcae6655 100644
--- a/packages/angular_devkit/core/src/terminal/index.ts
+++ b/packages/angular_devkit/core/src/terminal/index.ts
@@ -5,4 +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
*/
-export * from './ansi';
+export * from './text';
+
+import * as colors from './colors';
+export { colors };
diff --git a/packages/angular_devkit/core/src/terminal/text.ts b/packages/angular_devkit/core/src/terminal/text.ts
new file mode 100644
index 0000000000..bf4f9e7eba
--- /dev/null
+++ b/packages/angular_devkit/core/src/terminal/text.ts
@@ -0,0 +1,39 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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 * as caps from './caps';
+import * as ansi from './colors';
+
+
+export const reset = caps.stdout.colors ? ansi.reset : (x: string) => x;
+export const bold = caps.stdout.colors ? ansi.bold : (x: string) => x;
+export const dim = caps.stdout.colors ? ansi.dim : (x: string) => x;
+export const italic = caps.stdout.colors ? ansi.italic : (x: string) => x;
+export const underline = caps.stdout.colors ? ansi.underline : (x: string) => x;
+export const inverse = caps.stdout.colors ? ansi.inverse : (x: string) => x;
+export const hidden = caps.stdout.colors ? ansi.hidden : (x: string) => x;
+export const strikethrough = caps.stdout.colors ? ansi.strikethrough : (x: string) => x;
+
+export const black = caps.stdout.colors ? ansi.black : (x: string) => x;
+export const red = caps.stdout.colors ? ansi.red : (x: string) => x;
+export const green = caps.stdout.colors ? ansi.green : (x: string) => x;
+export const yellow = caps.stdout.colors ? ansi.yellow : (x: string) => x;
+export const blue = caps.stdout.colors ? ansi.blue : (x: string) => x;
+export const magenta = caps.stdout.colors ? ansi.magenta : (x: string) => x;
+export const cyan = caps.stdout.colors ? ansi.cyan : (x: string) => x;
+export const white = caps.stdout.colors ? ansi.white : (x: string) => x;
+export const grey = caps.stdout.colors ? ansi.gray : (x: string) => x;
+export const gray = caps.stdout.colors ? ansi.gray : (x: string) => x;
+
+export const bgBlack = caps.stdout.colors ? ansi.bgBlack : (x: string) => x;
+export const bgRed = caps.stdout.colors ? ansi.bgRed : (x: string) => x;
+export const bgGreen = caps.stdout.colors ? ansi.bgGreen : (x: string) => x;
+export const bgYellow = caps.stdout.colors ? ansi.bgYellow : (x: string) => x;
+export const bgBlue = caps.stdout.colors ? ansi.bgBlue : (x: string) => x;
+export const bgMagenta = caps.stdout.colors ? ansi.bgMagenta : (x: string) => x;
+export const bgCyan = caps.stdout.colors ? ansi.bgCyan : (x: string) => x;
+export const bgWhite = caps.stdout.colors ? ansi.bgWhite : (x: string) => x;
diff --git a/scripts/benchmark.ts b/scripts/benchmark.ts
index 819bb055a7..9bf91eb164 100644
--- a/scripts/benchmark.ts
+++ b/scripts/benchmark.ts
@@ -8,7 +8,7 @@
import { tags, terminal } from '@angular-devkit/core';
import * as glob from 'glob';
import 'jasmine';
-import {SpecReporter as JasmineSpecReporter } from 'jasmine-spec-reporter';
+import { SpecReporter as JasmineSpecReporter } from 'jasmine-spec-reporter';
import { join, relative } from 'path';
@@ -84,7 +84,7 @@ class BenchmarkReporter extends JasmineSpecReporter implements jasmine.CustomRep
const baseAverage = pad(Math.floor(stat.base.average));
const baseAverageMult = pad(precision(stat.average / stat.base.average), multPad);
- console.log(terminal.yellow(tags.indentBy(6)`
+ console.log(terminal.colors.yellow(tags.indentBy(6)`
fastest: ${fastest}
(base) ${baseFastest}
slowest: ${slowest}
@@ -93,7 +93,7 @@ class BenchmarkReporter extends JasmineSpecReporter implements jasmine.CustomRep
average: ${average} (${baseAverage}) (${baseAverageMult}x)
`));
} else {
- console.log(terminal.yellow(tags.indentBy(6)`
+ console.log(terminal.colors.yellow(tags.indentBy(6)`
fastest: ${fastest}
slowest: ${slowest}
mean: ${mean}
From 732502b801716bba84823f05b014f2357951d99d Mon Sep 17 00:00:00 2001
From: Charles Lyding <19598772+clydin@users.noreply.github.com>
Date: Wed, 29 Nov 2017 12:47:01 -0500
Subject: [PATCH 028/807] refactor(@angular-devkit/build-optimizer): optimize
purify plugin
---
.../build_optimizer/src/purify/purify.ts | 54 +++++++------------
.../src/purify/webpack-plugin.ts | 8 +--
2 files changed, 23 insertions(+), 39 deletions(-)
diff --git a/packages/angular_devkit/build_optimizer/src/purify/purify.ts b/packages/angular_devkit/build_optimizer/src/purify/purify.ts
index 1603e0ccff..17cf99b501 100644
--- a/packages/angular_devkit/build_optimizer/src/purify/purify.ts
+++ b/packages/angular_devkit/build_optimizer/src/purify/purify.ts
@@ -11,10 +11,9 @@ import { RawSource, ReplaceSource } from 'webpack-sources';
// This matches a comment left by the build-optimizer that contains pure import paths
const importCommentRegex = /\/\*\* PURE_IMPORTS_START (\S+) PURE_IMPORTS_END \*\//mg;
-// Replacements are meant to be used with Webpack's ReplaceSource.
-export interface Replacement {
- start: number;
- end: number;
+// Insertion are meant to be used with Webpack's ReplaceSource.
+export interface Insert {
+ pos: number;
content: string;
}
@@ -25,48 +24,33 @@ export function purifyReplacements(content: string) {
return [];
}
- const replacements: Replacement[] = [];
- const addReplacement = (start: number, length: number, content: string) =>
- replacements.push({
- start,
- end: start + length - 1,
- content,
- });
+ const inserts: Insert[] = [];
/* Prefix safe imports with pure */
- content.replace(
- new RegExp(`(_(${pureImportMatches})__ = )(__webpack_require__\\(\\S+\\);)`, 'mg'),
- (match, p1, _p2, p3, offset) => {
- const newContent = `${p1}/*@__PURE__*/${p3}`;
- addReplacement(offset, match.length, newContent);
-
- return newContent;
- },
+ const regex = new RegExp(
+ `(_(${pureImportMatches})__(_default)? = )(__webpack_require__(\\.\\w)?\\(\\S+\\);)`,
+ 'mg',
);
- /* Prefix default safe imports with pure */
- content.replace(
- new RegExp(
- `(_(${pureImportMatches})___default = )(__webpack_require__\\.\\w\\(\\S+\\);)`, 'mg',
- ),
- (match, p1, _p2, p3, offset) => {
- const newContent = `${p1}/*@__PURE__*/${p3}`;
- addReplacement(offset, match.length, newContent);
-
- return newContent;
- },
- );
+ let match;
+ // tslint:disable-next-line:no-conditional-assignment
+ while (match = regex.exec(content)) {
+ inserts.push({
+ pos: match.index + match[1].length,
+ content: '/*@__PURE__*/',
+ });
+ }
- return replacements;
+ return inserts;
}
export function purify(content: string) {
const rawSource = new RawSource(content);
const replaceSource = new ReplaceSource(rawSource, 'file.js');
- const replacements = purifyReplacements(content);
- replacements.forEach((replacement) => {
- replaceSource.replace(replacement.start, replacement.end, replacement.content);
+ const inserts = purifyReplacements(content);
+ inserts.forEach((insert) => {
+ replaceSource.insert(insert.pos, insert.content);
});
return replaceSource.source();
diff --git a/packages/angular_devkit/build_optimizer/src/purify/webpack-plugin.ts b/packages/angular_devkit/build_optimizer/src/purify/webpack-plugin.ts
index 3a9df69c24..3744951fc0 100644
--- a/packages/angular_devkit/build_optimizer/src/purify/webpack-plugin.ts
+++ b/packages/angular_devkit/build_optimizer/src/purify/webpack-plugin.ts
@@ -24,12 +24,12 @@ export class PurifyPlugin {
chunk.files
.filter((fileName: string) => fileName.endsWith('.js'))
.forEach((fileName: string) => {
- const replacements = purifyReplacements(compilation.assets[fileName].source());
+ const inserts = purifyReplacements(compilation.assets[fileName].source());
- if (replacements.length > 0) {
+ if (inserts.length > 0) {
const replaceSource = new ReplaceSource(compilation.assets[fileName], fileName);
- replacements.forEach((replacement) => {
- replaceSource.replace(replacement.start, replacement.end, replacement.content);
+ inserts.forEach((insert) => {
+ replaceSource.insert(insert.pos, insert.content);
});
compilation.assets[fileName] = replaceSource;
}
From 1baa17da8f53a508d97ac8590e64811672254477 Mon Sep 17 00:00:00 2001
From: Mike Brocchi
Date: Mon, 27 Nov 2017 15:07:19 -0500
Subject: [PATCH 029/807] fix(@schematics/angular): Make app-shell messages
consistent
Fixes #289
---
packages/schematics/angular/app-shell/index.ts | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/packages/schematics/angular/app-shell/index.ts b/packages/schematics/angular/app-shell/index.ts
index 21e0d22d02..6f782c5ed8 100644
--- a/packages/schematics/angular/app-shell/index.ts
+++ b/packages/schematics/angular/app-shell/index.ts
@@ -32,6 +32,12 @@ import { Schema as AppShellOptions } from './schema';
// Helper functions. (possible refactors to utils)
+function formatMissingAppMsg(label: string, nameOrIndex: string | undefined): string {
+ const nameOrIndexText = nameOrIndex ? ` (${nameOrIndex})` : '';
+
+ return `${label} app ${nameOrIndexText} not found.`;
+}
+
function getSourceFile(host: Tree, path: string): ts.SourceFile {
const buffer = host.read(path);
if (!buffer) {
@@ -80,7 +86,7 @@ function addAppShellConfig(options: AppShellOptions): Rule {
const app = getAppFromConfig(config, options.clientApp || '0');
if (!app) {
- throw new SchematicsException(`Client app (${options.clientApp}) could not be found.`);
+ throw new SchematicsException(formatMissingAppMsg('Client', options.clientApp));
}
if (!options.route) {
@@ -103,7 +109,7 @@ function addRouterModule(options: AppShellOptions): Rule {
const config = getConfig(host);
const app = getAppFromConfig(config, options.clientApp || '0');
if (app === null) {
- throw new SchematicsException('Client app not found.');
+ throw new SchematicsException(formatMissingAppMsg('Client', options.clientApp));
}
const modulePath = getAppModulePath(host, app);
const moduleSource = getSourceFile(host, modulePath);
@@ -144,10 +150,9 @@ function addRouterOutlet(options: AppShellOptions): Rule {
const config = getConfig(host);
const app = getAppFromConfig(config, options.clientApp || '0');
if (app === null) {
- throw new SchematicsException('Client app not found.');
+ throw new SchematicsException(formatMissingAppMsg('Client', options.clientApp));
}
const modulePath = getAppModulePath(host, app);
- // const modulePath = getAppModulePath(host, options);
const moduleSource = getSourceFile(host, modulePath);
const metadataNode = getDecoratorMetadata(moduleSource, 'NgModule', '@angular/core')[0];
@@ -209,11 +214,11 @@ function addServerRoutes(options: AppShellOptions): Rule {
const config = getConfig(host);
const app = getAppFromConfig(config, options.universalApp);
if (app === null) {
- throw new SchematicsException('Universal/server app not found.');
+ throw new SchematicsException(formatMissingAppMsg('Universal/server', options.universalApp));
}
const modulePath = getServerModulePath(host, app);
if (modulePath === null) {
- throw new SchematicsException('Universal/server app not found.');
+ throw new SchematicsException('Universal/server module not found.');
}
let moduleSource = getSourceFile(host, modulePath);
From 88926a5bc97238156e475a53fb4839616024beb5 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Wed, 29 Nov 2017 13:47:16 -0800
Subject: [PATCH 030/807] release: patch
---
.monorepo.json | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/.monorepo.json b/.monorepo.json
index 69a02a2619..8ece71d665 100644
--- a/.monorepo.json
+++ b/.monorepo.json
@@ -42,8 +42,8 @@
},
"packages": {
"@_/benchmark": {
- "version": "0.0.17",
- "hash": "37ed7e417435c92dbf301e7b26ea37ca"
+ "version": "0.0.18",
+ "hash": "b1f9f2d8e1eca2a865d39263f0ca5a38"
},
"@angular-devkit/build-optimizer": {
"name": "Build Optimizer",
@@ -53,13 +53,13 @@
"url": "https://github.com/angular/devkit/blob/master/packages/angular_devkit/build_optimizer/README.md"
}
],
- "version": "0.0.33",
- "hash": "df3997c8bdd86950215dba78d3163629"
+ "version": "0.0.34",
+ "hash": "bf3b25ed5f8c6b5f4c3de1fc20c3b317"
},
"@angular-devkit/core": {
"name": "Core",
- "version": "0.0.21",
- "hash": "de94633f78fdf7133aa7d096d2c63904"
+ "version": "0.0.22",
+ "hash": "d3c7e8bba4e1e14a68df2076622af5f8"
},
"@angular-devkit/schematics": {
"name": "Schematics",
@@ -69,20 +69,20 @@
"url": "https://github.com/angular/devkit/blob/master/packages/angular_devkit/schematics/README.md"
}
],
- "version": "0.0.37",
- "hash": "13281876c53fce8f7da980aa95f667b9"
+ "version": "0.0.38",
+ "hash": "6093295e780664be85d7db21f79d240c"
},
"@schematics/angular": {
"name": "Angular Schematics",
"section": "Schematics",
- "version": "0.1.7",
- "hash": "7105f8c10221f1cc790725b050b61163"
+ "version": "0.1.8",
+ "hash": "d3cbbd52d81c87a986fe67dc70a94535"
},
"@schematics/schematics": {
"name": "Schematics Schematics",
- "version": "0.0.7",
+ "version": "0.0.8",
"section": "Schematics",
- "hash": "263a5203aeb7bc7ed9cdbd207e3b251e"
+ "hash": "669881de32b42cff03ad6cd2fe62cdd1"
}
}
}
From b1e569d5c3d0d0b1b28b0db760dbf438b9cabb46 Mon Sep 17 00:00:00 2001
From: Filipe Silva
Date: Thu, 30 Nov 2017 15:50:21 +0000
Subject: [PATCH 031/807] ci: use npm5 on circleci
---
.circleci/config.yml | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 6351df6d38..1287d14523 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -3,7 +3,7 @@ version: 2
_defaults: &defaults
working_directory: ~/ng
docker:
- - image: angular/ngcontainer
+ - image: angular/ngcontainer:0.0.5
_post_checkout: &post_checkout
post: git pull --ff-only origin "refs/pull/${CI_PULL_REQUEST//*pull\//}/merge"
@@ -17,7 +17,7 @@ jobs:
- restore_cache:
key: angular_devkit-{{ checksum "package-lock.json" }}
- - run: npm install --quiet
+ - run: npm install --no-save
- run: npm run lint
validate:
@@ -27,7 +27,7 @@ jobs:
- restore_cache:
key: angular_devkit-{{ checksum "package-lock.json" }}
- - run: npm install --quiet
+ - run: npm install --no-save
- run: npm run validate
test:
@@ -38,7 +38,7 @@ jobs:
- restore_cache:
key: angular_devkit-{{ checksum "package-lock.json" }}
- - run: npm install --quiet
+ - run: npm install --no-save
- run: npm run test -- --code-coverage --full
integration:
@@ -53,7 +53,7 @@ jobs:
- restore_cache:
key: angular_devkit-integration-aio-{{ checksum "tests/@angular_devkit/build_optimizer/webpack/aio-app/package-lock.json" }}
- - run: npm install --quiet
+ - run: npm install --no-save
- run: xvfb-run -a npm run integration
- save_cache:
From 12b7eef5f3bc0039ab7b6253812fbcb58f734075 Mon Sep 17 00:00:00 2001
From: Cyrille Tuzi
Date: Thu, 23 Nov 2017 09:14:57 +0100
Subject: [PATCH 032/807] fix(@schematics/angular): revert breaking
angular-whitespace new lint rule
While updating to Codelyzer 4.0, #257 also added a new `angular-whitespace` rule.
This must be reverted because :
- it is a breaking change : existing project are now failing on lint ;
- it is opinionated (it is not in official Angular style guide) and so should not be forced ;
- it is the contrary of what is done in the official Angular doc and in the style guide itself.
---
packages/schematics/angular/application/files/tslint.json | 1 -
1 file changed, 1 deletion(-)
diff --git a/packages/schematics/angular/application/files/tslint.json b/packages/schematics/angular/application/files/tslint.json
index f1a84a4087..2fa7b03a40 100644
--- a/packages/schematics/angular/application/files/tslint.json
+++ b/packages/schematics/angular/application/files/tslint.json
@@ -130,7 +130,6 @@
"<%= prefix %>",
"kebab-case"
],
- "angular-whitespace": [true, "check-interpolation"],
"no-output-on-prefix": true,
"use-input-property-decorator": true,
"use-output-property-decorator": true,
From 40da86e46bdb2076f32684ab145a47a348c14f19 Mon Sep 17 00:00:00 2001
From: Mike Brocchi
Date: Mon, 4 Dec 2017 12:41:38 -0500
Subject: [PATCH 033/807] test: Add TreeSymbol to DelegateTree
---
packages/angular_devkit/schematics/src/tree/delegate.ts | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/packages/angular_devkit/schematics/src/tree/delegate.ts b/packages/angular_devkit/schematics/src/tree/delegate.ts
index dda329d4b6..5e51ac7b15 100644
--- a/packages/angular_devkit/schematics/src/tree/delegate.ts
+++ b/packages/angular_devkit/schematics/src/tree/delegate.ts
@@ -12,6 +12,7 @@ import {
FileVisitor,
MergeStrategy,
Tree,
+ TreeSymbol,
UpdateRecorder,
} from './interface';
@@ -48,4 +49,8 @@ export class DelegateTree implements Tree {
return this._other.apply(action, strategy);
}
get actions(): Action[] { return this._other.actions; }
+
+ [TreeSymbol]() {
+ return this;
+ }
}
From 0dc37d871ed9e949aa8422d3fe430e1c5ffd0abc Mon Sep 17 00:00:00 2001
From: Mike Brocchi
Date: Mon, 4 Dec 2017 11:15:55 -0500
Subject: [PATCH 034/807] fix(@schematics/angular): Use existing universal app
if it exists.
Fixes #295
---
packages/schematics/angular/app-shell/index.ts | 10 ++++++++++
.../schematics/angular/app-shell/index_spec.ts | 17 +++++++++++++++++
2 files changed, 27 insertions(+)
diff --git a/packages/schematics/angular/app-shell/index.ts b/packages/schematics/angular/app-shell/index.ts
index 6f782c5ed8..8bb63fd4bc 100644
--- a/packages/schematics/angular/app-shell/index.ts
+++ b/packages/schematics/angular/app-shell/index.ts
@@ -66,6 +66,16 @@ function getServerModulePath(host: Tree, app: AppConfig): string | null {
function addUniversalApp(options: AppShellOptions): Rule {
return (host: Tree, context: SchematicContext) => {
+ const config = getConfig(host);
+ const appConfig = getAppFromConfig(config, options.universalApp);
+
+ if (appConfig && appConfig.platform === 'server') {
+ return host;
+ } else if (appConfig && appConfig.platform !== 'server') {
+ throw new SchematicsException(
+ `Invalid platform for universal app (${options.universalApp}), value must be "server".`);
+ }
+
// Copy options.
const universalOptions = {
...options,
diff --git a/packages/schematics/angular/app-shell/index_spec.ts b/packages/schematics/angular/app-shell/index_spec.ts
index ad21a49604..6aab9054c5 100644
--- a/packages/schematics/angular/app-shell/index_spec.ts
+++ b/packages/schematics/angular/app-shell/index_spec.ts
@@ -50,6 +50,23 @@ describe('App Shell Schematic', () => {
expect(file).toBeDefined();
});
+ it('should use an existing universal app', () => {
+ const universalOptions = {
+ name: defaultOptions.universalApp,
+ };
+
+ let tree: Tree = schematicRunner.runSchematic('universal', universalOptions, appTree);
+ const filePath = '/.angular-cli.json';
+ let content = tree.read(filePath) || new Buffer('');
+ let config = JSON.parse(content.toString());
+ const appCount = config.apps.length;
+
+ tree = schematicRunner.runSchematic('appShell', defaultOptions, tree);
+ content = tree.read(filePath) || new Buffer('');
+ config = JSON.parse(content.toString());
+ expect(config.apps.length).toBe(appCount);
+ });
+
it('should add app shell configuration', () => {
const tree = schematicRunner.runSchematic('appShell', defaultOptions, appTree);
const filePath = '/.angular-cli.json';
From 0b84c8a6aed9b4613cc4221c1bcfeab05645e236 Mon Sep 17 00:00:00 2001
From: Alex Rickabaugh
Date: Thu, 30 Nov 2017 15:42:30 -0800
Subject: [PATCH 035/807] fix(@schematics/angular): add ServiceWorkerModule in
dev mode, but disabled
---
.../schematics/angular/application/other-files/app.module.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/schematics/angular/application/other-files/app.module.ts b/packages/schematics/angular/application/other-files/app.module.ts
index 956d1df715..2ba765db55 100644
--- a/packages/schematics/angular/application/other-files/app.module.ts
+++ b/packages/schematics/angular/application/other-files/app.module.ts
@@ -15,7 +15,7 @@ import { environment } from '../environments/environment';<% } %>
imports: [
BrowserModule<% if (routing) { %>,
AppRoutingModule<% } %><% if (serviceWorker) { %>,
- environment.production ? ServiceWorkerModule.register('/ngsw-worker.js') : []<% } %>
+ ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production })<% } %>
],
providers: [],
bootstrap: [AppComponent]
From 466f237aae3c0ddfb219241bc3408a3a4d484ae2 Mon Sep 17 00:00:00 2001
From: Mike Brocchi
Date: Thu, 30 Nov 2017 15:17:10 -0500
Subject: [PATCH 036/807] fix(@schematics/angular): App shell requires
router-outlet
Fixes #298
---
.../schematics/angular/app-shell/index.ts | 154 ++++++++++--------
.../angular/app-shell/index_spec.ts | 53 +++---
2 files changed, 111 insertions(+), 96 deletions(-)
diff --git a/packages/schematics/angular/app-shell/index.ts b/packages/schematics/angular/app-shell/index.ts
index 8bb63fd4bc..6a629639e1 100644
--- a/packages/schematics/angular/app-shell/index.ts
+++ b/packages/schematics/angular/app-shell/index.ts
@@ -62,8 +62,94 @@ function getServerModulePath(host: Tree, app: AppConfig): string | null {
return modulePath;
}
+
+interface TemplateInfo {
+ templateProp?: ts.PropertyAssignment;
+ templateUrlProp?: ts.PropertyAssignment;
+}
+
+function getComponentTemplateInfo(host: Tree, componentPath: string): TemplateInfo {
+ const compSource = getSourceFile(host, componentPath);
+ const compMetadata = getDecoratorMetadata(compSource, 'Component', '@angular/core')[0];
+
+ return {
+ templateProp: getMetadataProperty(compMetadata, 'template'),
+ templateUrlProp: getMetadataProperty(compMetadata, 'templateUrl'),
+ };
+}
+
+function getComponentTemplate(host: Tree, compPath: string, tmplInfo: TemplateInfo): string {
+ let template = '';
+
+ if (tmplInfo.templateProp) {
+ template = tmplInfo.templateProp.getFullText();
+ } else if (tmplInfo.templateUrlProp) {
+ const templateUrl = (tmplInfo.templateUrlProp.initializer as ts.StringLiteral).text;
+ const dirEntry = host.getDir(compPath);
+ const dir = dirEntry.parent ? dirEntry.parent.path : '/';
+ const templatePath = normalize(`/${dir}/${templateUrl}`);
+ const buffer = host.read(templatePath);
+ if (buffer) {
+ template = buffer.toString();
+ }
+ }
+
+ return template;
+}
+
+function getBootstrapComponentPath(host: Tree, appConfig: AppConfig): string {
+ const modulePath = getAppModulePath(host, appConfig);
+ const moduleSource = getSourceFile(host, modulePath);
+
+ const metadataNode = getDecoratorMetadata(moduleSource, 'NgModule', '@angular/core')[0];
+ const bootstrapProperty = getMetadataProperty(metadataNode, 'bootstrap');
+
+ const arrLiteral = ( bootstrapProperty)
+ .initializer as ts.ArrayLiteralExpression;
+
+ const componentSymbol = arrLiteral.elements[0].getText();
+
+ const relativePath = getSourceNodes(moduleSource)
+ .filter(node => node.kind === ts.SyntaxKind.ImportDeclaration)
+ .filter(imp => {
+ return findNode(imp, ts.SyntaxKind.Identifier, componentSymbol);
+ })
+ .map((imp: ts.ImportDeclaration) => {
+ const pathStringLiteral = imp.moduleSpecifier;
+
+ return pathStringLiteral.text;
+ })[0];
+
+ const dirEntry = host.getDir(modulePath);
+ const dir = dirEntry.parent ? dirEntry.parent.path : '/';
+ const compPath = normalize(`/${dir}/${relativePath}.ts`);
+
+ return compPath;
+}
// end helper functions.
+function validateProject(options: AppShellOptions): Rule {
+ return (host: Tree, context: SchematicContext) => {
+ const routerOutletCheckRegex = /([\s\S]*?)<\/router\-outlet>/;
+
+ const config = getConfig(host);
+ const app = getAppFromConfig(config, options.clientApp || '0');
+ if (app === null) {
+ throw new SchematicsException(formatMissingAppMsg('Client', options.clientApp));
+ }
+
+ const componentPath = getBootstrapComponentPath(host, app);
+ const tmpl = getComponentTemplateInfo(host, componentPath);
+ const template = getComponentTemplate(host, componentPath, tmpl);
+ if (!routerOutletCheckRegex.test(template)) {
+ const errorMsg =
+ `Prerequisite for app shell is to define a router-outlet in your root component.`;
+ context.logger.error(errorMsg);
+ throw new SchematicsException(errorMsg);
+ }
+ };
+}
+
function addUniversalApp(options: AppShellOptions): Rule {
return (host: Tree, context: SchematicContext) => {
const config = getConfig(host);
@@ -153,72 +239,6 @@ function getMetadataProperty(metadata: ts.Node, propertyName: string): ts.Proper
return property as ts.PropertyAssignment;
}
-function addRouterOutlet(options: AppShellOptions): Rule {
- return (host: Tree) => {
- const routerOutletMarkup = ``;
-
- const config = getConfig(host);
- const app = getAppFromConfig(config, options.clientApp || '0');
- if (app === null) {
- throw new SchematicsException(formatMissingAppMsg('Client', options.clientApp));
- }
- const modulePath = getAppModulePath(host, app);
- const moduleSource = getSourceFile(host, modulePath);
-
- const metadataNode = getDecoratorMetadata(moduleSource, 'NgModule', '@angular/core')[0];
- const bootstrapProperty = getMetadataProperty(metadataNode, 'bootstrap');
-
- const arrLiteral = ( bootstrapProperty)
- .initializer as ts.ArrayLiteralExpression;
-
- const componentSymbol = arrLiteral.elements[0].getText();
-
- const relativePath = getSourceNodes(moduleSource)
- .filter(node => node.kind === ts.SyntaxKind.ImportDeclaration)
- .filter(imp => {
- return findNode(imp, ts.SyntaxKind.Identifier, componentSymbol);
- })
- .map((imp: ts.ImportDeclaration) => {
- const pathStringLiteral = imp.moduleSpecifier;
-
- return pathStringLiteral.text;
- })[0];
-
- const dirEntry = host.getDir(modulePath);
- const dir = dirEntry.parent ? dirEntry.parent.path : '/';
- const compPath = normalize(`/${dir}/${relativePath}.ts`);
-
- const compSource = getSourceFile(host, compPath);
- const compMetadata = getDecoratorMetadata(compSource, 'Component', '@angular/core')[0];
- const templateProp = getMetadataProperty(compMetadata, 'template');
- const templateUrlProp = getMetadataProperty(compMetadata, 'templateUrl');
-
- if (templateProp) {
- if (!//.test(templateProp.initializer.getText())) {
- const recorder = host.beginUpdate(compPath);
- recorder.insertRight(templateProp.initializer.getEnd() - 1, routerOutletMarkup);
- host.commitUpdate(recorder);
- }
- } else {
- const templateUrl = (templateUrlProp.initializer as ts.StringLiteral).text;
- const dirEntry = host.getDir(compPath);
- const dir = dirEntry.parent ? dirEntry.parent.path : '/';
- const templatePath = normalize(`/${dir}/${templateUrl}`);
- const buffer = host.read(templatePath);
- if (buffer) {
- const content = buffer.toString();
- if (!//.test(content)) {
- const recorder = host.beginUpdate(templatePath);
- recorder.insertRight(buffer.length, routerOutletMarkup);
- host.commitUpdate(recorder);
- }
- }
- }
-
- return host;
- };
-}
-
function addServerRoutes(options: AppShellOptions): Rule {
return (host: Tree) => {
const config = getConfig(host);
@@ -293,10 +313,10 @@ function addShellComponent(options: AppShellOptions): Rule {
export default function (options: AppShellOptions): Rule {
return chain([
+ validateProject(options),
addUniversalApp(options),
addAppShellConfig(options),
addRouterModule(options),
- addRouterOutlet(options),
addServerRoutes(options),
addShellComponent(options),
]);
diff --git a/packages/schematics/angular/app-shell/index_spec.ts b/packages/schematics/angular/app-shell/index_spec.ts
index 6aab9054c5..e9e59351ec 100644
--- a/packages/schematics/angular/app-shell/index_spec.ts
+++ b/packages/schematics/angular/app-shell/index_spec.ts
@@ -23,26 +23,34 @@ describe('App Shell Schematic', () => {
};
let appTree: Tree;
+ const appOptions: ApplicationOptions = {
+ directory: '',
+ name: 'app',
+ path: 'src',
+ prefix: '',
+ sourceDir: 'src',
+ inlineStyle: false,
+ inlineTemplate: false,
+ viewEncapsulation: 'None',
+ changeDetection: 'Default',
+ version: '1.2.3',
+ routing: true,
+ style: 'css',
+ skipTests: false,
+ minimal: false,
+ };
+
beforeEach(() => {
- const appOptions: ApplicationOptions = {
- directory: '',
- name: 'app',
- path: 'src',
- prefix: '',
- sourceDir: 'src',
- inlineStyle: false,
- inlineTemplate: false,
- viewEncapsulation: 'None',
- changeDetection: 'Default',
- version: '1.2.3',
- routing: false,
- style: 'css',
- skipTests: false,
- minimal: false,
- };
appTree = schematicRunner.runSchematic('application', appOptions);
});
+ it('should ensure the client app has a router-outlet', () => {
+ appTree = schematicRunner.runSchematic('application', {...appOptions, routing: false});
+ expect(() => {
+ schematicRunner.runSchematic('appShell', defaultOptions, appTree);
+ }).toThrowError();
+ });
+
it('should add a universal app', () => {
const tree = schematicRunner.runSchematic('appShell', defaultOptions, appTree);
const filePath = '/src/app/app.server.module.ts';
@@ -115,12 +123,6 @@ describe('App Shell Schematic', () => {
tree.delete('/src/app/app.component.html');
}
- it('should add the router outlet (external template)', () => {
- const tree = schematicRunner.runSchematic('appShell', defaultOptions, appTree);
- const content = tree.read('/src/app/app.component.html') || new Buffer('');
- expect(content.toString()).toMatch(/<\/router\-outlet>/g);
- });
-
it('should not re-add the router outlet (external template)', () => {
const htmlPath = '/src/app/app.component.html';
appTree.overwrite(htmlPath, '');
@@ -132,13 +134,6 @@ describe('App Shell Schematic', () => {
expect(numMatches).toEqual(1);
});
- it('should add the router outlet (inline template)', () => {
- makeInlineTemplate(appTree);
- const tree = schematicRunner.runSchematic('appShell', defaultOptions, appTree);
- const content = tree.read('/src/app/app.component.ts') || new Buffer('');
- expect(content.toString()).toMatch(/<\/router\-outlet>/g);
- });
-
it('should not re-add the router outlet (inline template)', () => {
makeInlineTemplate(appTree, '');
const tree = schematicRunner.runSchematic('appShell', defaultOptions, appTree);
From 9a63eb3ec4c16b54c278e73ab3ee673b643ca5bc Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Mon, 4 Dec 2017 15:02:34 -0800
Subject: [PATCH 037/807] release: patch
---
.monorepo.json | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/.monorepo.json b/.monorepo.json
index 8ece71d665..473b037740 100644
--- a/.monorepo.json
+++ b/.monorepo.json
@@ -69,20 +69,20 @@
"url": "https://github.com/angular/devkit/blob/master/packages/angular_devkit/schematics/README.md"
}
],
- "version": "0.0.38",
- "hash": "6093295e780664be85d7db21f79d240c"
+ "version": "0.0.39",
+ "hash": "ba64f250a7c6a14c83f455471d99906b"
},
"@schematics/angular": {
"name": "Angular Schematics",
"section": "Schematics",
- "version": "0.1.8",
- "hash": "d3cbbd52d81c87a986fe67dc70a94535"
+ "version": "0.1.9",
+ "hash": "c658f683345f0179e704364447617ec5"
},
"@schematics/schematics": {
"name": "Schematics Schematics",
- "version": "0.0.8",
+ "version": "0.0.9",
"section": "Schematics",
- "hash": "669881de32b42cff03ad6cd2fe62cdd1"
+ "hash": "39f5fbf5bc3c8cb74922e2632d6876bb"
}
}
}
From cebd0436c1cc0774b7b31b2b314ad6783fb1d288 Mon Sep 17 00:00:00 2001
From: Filipe Silva
Date: Fri, 1 Dec 2017 16:20:34 +0000
Subject: [PATCH 038/807] fix(@angular-devkit/build-optimizer): fix relative
pure imports
---
.../build_optimizer/src/purify/purify.ts | 7 +++++-
.../build_optimizer/src/purify/purify_spec.ts | 22 ++++++++++++++++++-
.../src/transforms/prefix-functions.ts | 7 ++++--
.../src/transforms/prefix-functions_spec.ts | 4 +++-
4 files changed, 35 insertions(+), 5 deletions(-)
diff --git a/packages/angular_devkit/build_optimizer/src/purify/purify.ts b/packages/angular_devkit/build_optimizer/src/purify/purify.ts
index 17cf99b501..9f0e251847 100644
--- a/packages/angular_devkit/build_optimizer/src/purify/purify.ts
+++ b/packages/angular_devkit/build_optimizer/src/purify/purify.ts
@@ -19,7 +19,12 @@ export interface Insert {
export function purifyReplacements(content: string) {
- const pureImportMatches = getMatches(content, importCommentRegex, 1).join('|');
+ const pureImportMatches = getMatches(content, importCommentRegex, 1)
+ // Remove dots at the start of matches.
+ // Older versions of Purify added dots for relative imports.
+ .map(match => match.replace(/^\.+/, ''))
+ .join('|');
+
if (!pureImportMatches) {
return [];
}
diff --git a/packages/angular_devkit/build_optimizer/src/purify/purify_spec.ts b/packages/angular_devkit/build_optimizer/src/purify/purify_spec.ts
index 0e0f8a2568..c3157d4efb 100644
--- a/packages/angular_devkit/build_optimizer/src/purify/purify_spec.ts
+++ b/packages/angular_devkit/build_optimizer/src/purify/purify_spec.ts
@@ -31,12 +31,32 @@ describe('purify', () => {
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_rxjs_Subject___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_rxjs_Subject__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_zone_js___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_zone_js__);
/** PURE_IMPORTS_START rxjs_Subject,zone_js PURE_IMPORTS_END */
- `;
+ `;
const output = tags.stripIndent`
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_rxjs_Subject__ = /*@__PURE__*/__webpack_require__("rlar");
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_rxjs_Subject___default = /*@__PURE__*/__webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_rxjs_Subject__);
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_zone_js___default = /*@__PURE__*/__webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_zone_js__);
/** PURE_IMPORTS_START rxjs_Subject,zone_js PURE_IMPORTS_END */
+ `;
+
+ expect(tags.oneLine`${purify(input)}`).toEqual(tags.oneLine`${output}`);
+ });
+
+ // Older versions of Purify added dots for relative imports. We should be backwards compatible.
+ it('finds old matches that started with dots', () => {
+ const input = tags.stripIndent`
+ /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__util_root__ = __webpack_require__(13);
+ /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_toSubscriber__ = __webpack_require__(67);
+ /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__symbol_observable__ = __webpack_require__(45);
+ /* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__util_pipe__ = __webpack_require__(71);
+ /** PURE_IMPORTS_START ._util_root,._util_toSubscriber,.._symbol_observable,._util_pipe PURE_IMPORTS_END */
+ `;
+ const output = tags.stripIndent`
+ /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__util_root__ = /*@__PURE__*/__webpack_require__(13);
+ /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__util_toSubscriber__ = /*@__PURE__*/__webpack_require__(67);
+ /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__symbol_observable__ = /*@__PURE__*/__webpack_require__(45);
+ /* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__util_pipe__ = /*@__PURE__*/__webpack_require__(71);
+ /** PURE_IMPORTS_START ._util_root,._util_toSubscriber,.._symbol_observable,._util_pipe PURE_IMPORTS_END */
`;
expect(tags.oneLine`${purify(input)}`).toEqual(tags.oneLine`${output}`);
diff --git a/packages/angular_devkit/build_optimizer/src/transforms/prefix-functions.ts b/packages/angular_devkit/build_optimizer/src/transforms/prefix-functions.ts
index 1e94b34eae..d17331d375 100644
--- a/packages/angular_devkit/build_optimizer/src/transforms/prefix-functions.ts
+++ b/packages/angular_devkit/build_optimizer/src/transforms/prefix-functions.ts
@@ -101,9 +101,12 @@ export function findPureImports(parentNode: ts.Node): string[] {
if (node.kind === ts.SyntaxKind.ImportDeclaration
&& (node as ts.ImportDeclaration).importClause) {
- // Save the path of the import transformed into snake case
+ // Save the path of the import transformed into snake case and remove relative paths.
const moduleSpecifier = (node as ts.ImportDeclaration).moduleSpecifier as ts.StringLiteral;
- pureImports.push(moduleSpecifier.text.replace(/[\/@\-]/g, '_'));
+ const pureImport = moduleSpecifier.text
+ .replace(/[\/@\-]/g, '_')
+ .replace(/^\.+/, '');
+ pureImports.push(pureImport);
}
ts.forEachChild(node, cb);
diff --git a/packages/angular_devkit/build_optimizer/src/transforms/prefix-functions_spec.ts b/packages/angular_devkit/build_optimizer/src/transforms/prefix-functions_spec.ts
index 37a973b180..e09d38f906 100644
--- a/packages/angular_devkit/build_optimizer/src/transforms/prefix-functions_spec.ts
+++ b/packages/angular_devkit/build_optimizer/src/transforms/prefix-functions_spec.ts
@@ -21,10 +21,12 @@ describe('prefix-functions', () => {
it('adds import list', () => {
const input = tags.stripIndent`
import { Injectable } from '@angular/core';
+ import { Something } from './relative/pure_import';
var foo = Injectable;
+ var bar = Something;
`;
const output = tags.stripIndent`
- /** PURE_IMPORTS_START _angular_core PURE_IMPORTS_END */
+ /** PURE_IMPORTS_START _angular_core,_relative_pure_import PURE_IMPORTS_END */
${input}
`;
From 901bd51d22ffb61feccbe6812a8954c588c7645c Mon Sep 17 00:00:00 2001
From: Filipe Silva
Date: Tue, 5 Dec 2017 17:41:38 +0000
Subject: [PATCH 039/807] fix(@angular-devkit/build-optimizer): fix sourcemap
chaining
---
.../src/build-optimizer/build-optimizer.ts | 9 +++++++--
.../src/build-optimizer/webpack-loader.ts | 19 +++++++++++--------
2 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/packages/angular_devkit/build_optimizer/src/build-optimizer/build-optimizer.ts b/packages/angular_devkit/build_optimizer/src/build-optimizer/build-optimizer.ts
index 0d149a5b1b..b4fb41f460 100644
--- a/packages/angular_devkit/build_optimizer/src/build-optimizer/build-optimizer.ts
+++ b/packages/angular_devkit/build_optimizer/src/build-optimizer/build-optimizer.ts
@@ -62,6 +62,7 @@ function isKnownSideEffectFree(filePath: string) {
export interface BuildOptimizerOptions {
content?: string;
+ originalFilePath?: string;
inputFilePath?: string;
outputFilePath?: string;
emitSourceMap?: boolean;
@@ -72,7 +73,11 @@ export interface BuildOptimizerOptions {
export function buildOptimizer(options: BuildOptimizerOptions): TransformJavascriptOutput {
const { inputFilePath } = options;
- let { content } = options;
+ let { originalFilePath, content } = options;
+
+ if (!originalFilePath && inputFilePath) {
+ originalFilePath = inputFilePath;
+ }
if (!inputFilePath && content === undefined) {
throw new Error('Either filePath or content must be specified in options.');
@@ -97,7 +102,7 @@ export function buildOptimizer(options: BuildOptimizerOptions): TransformJavascr
getTransforms.push(getPrefixClassesTransformer);
}
- if (options.isSideEffectFree || inputFilePath && isKnownSideEffectFree(inputFilePath)) {
+ if (options.isSideEffectFree || originalFilePath && isKnownSideEffectFree(originalFilePath)) {
getTransforms.push(
// getPrefixFunctionsTransformer is rather dangerous, apply only to known pure es5 modules.
// It will mark both `require()` calls and `console.log(stuff)` as pure.
diff --git a/packages/angular_devkit/build_optimizer/src/build-optimizer/webpack-loader.ts b/packages/angular_devkit/build_optimizer/src/build-optimizer/webpack-loader.ts
index 1fa83b419b..caee6e46be 100644
--- a/packages/angular_devkit/build_optimizer/src/build-optimizer/webpack-loader.ts
+++ b/packages/angular_devkit/build_optimizer/src/build-optimizer/webpack-loader.ts
@@ -21,12 +21,15 @@ export default function buildOptimizerLoader
this.cacheable();
const options: BuildOptimizerLoaderOptions = loaderUtils.getOptions(this) || {};
+ // Make up names of the intermediate files so we can chain the sourcemaps.
+ const inputFilePath = this.resourcePath + '.pre-build-optimizer.js';
+ const outputFilePath = this.resourcePath + '.post-build-optimizer.js';
+
const boOutput = buildOptimizer({
content,
- inputFilePath: this.resourcePath,
- // Add a name to the build optimizer output.
- // Without a name the sourcemaps cannot be properly chained.
- outputFilePath: this.resourcePath + '.build-optimizer.js',
+ originalFilePath: this.resourcePath,
+ inputFilePath,
+ outputFilePath,
emitSourceMap: options.sourceMap,
});
@@ -53,10 +56,10 @@ export default function buildOptimizerLoader
// source map chaining example.
// Use http://sokra.github.io/source-map-visualization/ to validate sourcemaps make sense.
- // Fill in the intermediate sourcemap sources as the previous sourcemap sources.
- if (previousSourceMap.sources) {
- intermediateSourceMap.sources = previousSourceMap.sources;
- }
+ // Force the previous sourcemap to use the filename we made up for it.
+ // In order for source maps to be chained, the consumed source map `file` needs to be in the
+ // consumers source map `sources` array.
+ previousSourceMap.file = inputFilePath;
// Chain the sourcemaps.
const consumer = new SourceMapConsumer(intermediateSourceMap);
From 93c19d897a3cc54092e138048010ecc4b18e114f Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Wed, 29 Nov 2017 17:34:25 -0800
Subject: [PATCH 040/807] refactor(@angular-devkit/schematics): use typings on
the runSchematic function
---
.../schematics/testing/schematic-test-runner.ts | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/packages/angular_devkit/schematics/testing/schematic-test-runner.ts b/packages/angular_devkit/schematics/testing/schematic-test-runner.ts
index ec2df1a81e..ff7b3bc7dc 100644
--- a/packages/angular_devkit/schematics/testing/schematic-test-runner.ts
+++ b/packages/angular_devkit/schematics/testing/schematic-test-runner.ts
@@ -20,9 +20,6 @@ import {
import { Observable } from 'rxjs/Observable';
-export interface SchematicSchemaT {}
-
-
export class UnitTestTree extends DelegateTree {
get files() {
const result: string[] = [];
@@ -44,10 +41,7 @@ export class SchematicTestRunner {
this._logger = new logging.Logger('test');
this._registry = new schema.JsonSchemaRegistry();
- this._engineHost.registerOptionsTransform((
- schematicDescription: {},
- opts: SchematicSchemaT,
- ) => {
+ this._engineHost.registerOptionsTransform((schematicDescription: {}, opts: object) => {
const schematic: FileSystemSchematicDesc = schematicDescription as FileSystemSchematicDesc;
if (schematic.schema && schematic.schemaJson) {
@@ -68,7 +62,7 @@ export class SchematicTestRunner {
get logger(): logging.Logger { return this._logger; }
- runSchematicAsync(
+ runSchematicAsync(
schematicName: string,
opts?: SchematicSchemaT,
tree?: Tree,
@@ -80,7 +74,11 @@ export class SchematicTestRunner {
.map(tree => new UnitTestTree(tree));
}
- runSchematic(schematicName: string, opts?: SchematicSchemaT, tree?: Tree): UnitTestTree {
+ runSchematic(
+ schematicName: string,
+ opts?: SchematicSchemaT,
+ tree?: Tree,
+ ): UnitTestTree {
const schematic = this._collection.createSchematic(schematicName);
let result: UnitTestTree | null = null;
From fd59e18f7680ac941807af2199f1be70c477ce26 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Mon, 4 Dec 2017 16:21:56 -0800
Subject: [PATCH 041/807] refactor: remove duplicated if condition
---
packages/angular_devkit/schematics/src/rules/call.ts | 2 --
1 file changed, 2 deletions(-)
diff --git a/packages/angular_devkit/schematics/src/rules/call.ts b/packages/angular_devkit/schematics/src/rules/call.ts
index 3c6fa37882..af463bd8da 100644
--- a/packages/angular_devkit/schematics/src/rules/call.ts
+++ b/packages/angular_devkit/schematics/src/rules/call.ts
@@ -81,8 +81,6 @@ export function callRule(rule: Rule,
return Observable.of(result as Tree);
} else if (Symbol.observable in result) {
return result as Observable;
- } else if (result === undefined) {
- return Observable.of(inputTree);
} else {
throw new InvalidRuleResultException(result);
}
From c1a30e9fe76a7c08d194827f3254c227f4722acc Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Tue, 5 Dec 2017 11:38:08 -0800
Subject: [PATCH 042/807] refactor(@angular-devkit/schematics): use callRule
for calling a schematic
---
.../schematics/src/engine/schematic.ts | 15 +++------------
1 file changed, 3 insertions(+), 12 deletions(-)
diff --git a/packages/angular_devkit/schematics/src/engine/schematic.ts b/packages/angular_devkit/schematics/src/engine/schematic.ts
index 37ff06cb01..6328e90eee 100644
--- a/packages/angular_devkit/schematics/src/engine/schematic.ts
+++ b/packages/angular_devkit/schematics/src/engine/schematic.ts
@@ -9,6 +9,7 @@ import { BaseException } from '@angular-devkit/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/concatMap';
+import { callRule } from '../rules/call';
import { Tree } from '../tree/interface';
import {
Collection,
@@ -48,18 +49,8 @@ export class SchematicImpl>,
): Observable {
const context = this._engine.createContext(this, parentContext);
+ const transformedOptions = this._engine.transformOptions(this, options);
- return host.concatMap(tree => {
- const transformedOptions = this._engine.transformOptions(this, options);
-
- const result = this._factory(transformedOptions)(tree, context);
- if (result instanceof Observable) {
- return result;
- } else if (result === undefined) {
- return Observable.of(tree);
- } else {
- return Observable.of(result);
- }
- });
+ return callRule(this._factory(transformedOptions), host, context);
}
}
From d4c32f5dce8fc8ed24eeb80372f7627a79785cfd Mon Sep 17 00:00:00 2001
From: Mike Brocchi
Date: Tue, 5 Dec 2017 14:59:28 -0500
Subject: [PATCH 043/807] fix(@schematics/angular): Clean up schematic options
---
.../schematics/angular/app-shell/schema.json | 1 +
.../angular/application/schema.d.ts | 19 +++++++++--
.../angular/application/schema.json | 18 +++++++---
packages/schematics/angular/class/schema.d.ts | 14 +++++++-
packages/schematics/angular/class/schema.json | 19 +++++++----
.../__name@dasherize__.component.html | 4 +--
.../angular/component/index_spec.ts | 1 -
.../schematics/angular/component/schema.d.ts | 25 ++++++++++++--
.../schematics/angular/component/schema.json | 33 ++++++++++---------
.../schematics/angular/directive/schema.d.ts | 18 ++++++++++
.../schematics/angular/directive/schema.json | 23 +++++++++----
packages/schematics/angular/enum/schema.d.ts | 14 +++++++-
packages/schematics/angular/enum/schema.json | 19 +++++++----
packages/schematics/angular/guard/schema.d.ts | 20 ++++++++++-
packages/schematics/angular/guard/schema.json | 21 ++++++++----
.../schematics/angular/interface/schema.d.ts | 14 +++++++-
.../schematics/angular/interface/schema.json | 19 +++++++----
.../schematics/angular/module/schema.d.ts | 29 +++++++++++++++-
.../schematics/angular/module/schema.json | 27 +++++++++++----
packages/schematics/angular/pipe/schema.d.ts | 14 +++++++-
packages/schematics/angular/pipe/schema.json | 19 +++++++----
.../schematics/angular/service/schema.d.ts | 16 +++++++--
.../schematics/angular/service/schema.json | 21 ++++++++----
.../schematics/angular/universal/schema.json | 3 +-
24 files changed, 323 insertions(+), 88 deletions(-)
diff --git a/packages/schematics/angular/app-shell/schema.json b/packages/schematics/angular/app-shell/schema.json
index ae7a214373..d066efdc10 100644
--- a/packages/schematics/angular/app-shell/schema.json
+++ b/packages/schematics/angular/app-shell/schema.json
@@ -80,6 +80,7 @@
},
"sourceDir": {
"type": "string",
+ "description": "The path of the source directory.",
"default": "src",
"alias": "sd"
}
diff --git a/packages/schematics/angular/application/schema.d.ts b/packages/schematics/angular/application/schema.d.ts
index 32025a5f7d..bd5249790c 100644
--- a/packages/schematics/angular/application/schema.d.ts
+++ b/packages/schematics/angular/application/schema.d.ts
@@ -11,8 +11,17 @@ export interface Schema {
* The directory name to create the app in.
*/
directory: string;
+ /**
+ * The path of the application.
+ */
path?: string;
+ /**
+ * The path of the source directory.
+ */
sourceDir?: string;
+ /**
+ * The name of the application.
+ */
name: string;
/**
* Specifies if the style will be in the ts file.
@@ -30,7 +39,13 @@ export interface Schema {
* Specifies the change detection strategy.
*/
changeDetection?: ('Default' | 'OnPush');
+ /**
+ * The version of the Angular CLI to use.
+ */
version?: string;
+ /**
+ * Generates a routing module.
+ */
routing?: boolean;
/**
* The prefix to apply to generated selectors.
@@ -49,11 +64,11 @@ export interface Schema {
*/
skipGit?: boolean;
/**
- * Should create a minimal app.
+ * Create a minimal app (no test structure, inline styles/templates).
*/
minimal?: boolean;
/**
- * Should install the @angular/service-worker.
+ * Installs the @angular/service-worker.
*/
serviceWorker?: boolean;
}
diff --git a/packages/schematics/angular/application/schema.json b/packages/schematics/angular/application/schema.json
index 86742ff1ae..15ede3bf65 100644
--- a/packages/schematics/angular/application/schema.json
+++ b/packages/schematics/angular/application/schema.json
@@ -11,14 +11,19 @@
},
"path": {
"type": "string",
- "default": "src"
+ "description": "The path of the application.",
+ "default": "src",
+ "visible": false
},
"sourceDir": {
"type": "string",
+ "description": "The path of the source directory.",
"default": "src",
- "alias": "sd"
+ "alias": "sd",
+ "visible": false
},
"name": {
+ "description": "The name of the application.",
"type": "string"
},
"inlineStyle": {
@@ -45,10 +50,13 @@
"default": "Default"
},
"version": {
- "type": "string"
+ "type": "string",
+ "description": "The version of the Angular CLI to use.",
+ "visible": false
},
"routing": {
"type": "boolean",
+ "description": "Generates a routing module.",
"default": false
},
"prefix": {
@@ -75,12 +83,12 @@
"alias": "sg"
},
"minimal": {
- "description": "Should create a minimal app.",
+ "description": "Create a minimal app (no test structure, inline styles/templates).",
"type": "boolean",
"default": false
},
"serviceWorker": {
- "description": "Should install the @angular/service-worker.",
+ "description": "Installs the @angular/service-worker.",
"type": "boolean",
"default": false
}
diff --git a/packages/schematics/angular/class/schema.d.ts b/packages/schematics/angular/class/schema.d.ts
index 6668692550..9aa8015dfd 100644
--- a/packages/schematics/angular/class/schema.d.ts
+++ b/packages/schematics/angular/class/schema.d.ts
@@ -7,10 +7,22 @@
*/
export interface Schema {
+ /**
+ * The name of the class.
+ */
name: string;
- appRoot?: string;
+ /**
+ * The path to create the class.
+ */
path?: string;
+ /**
+ * The path of the source directory.
+ */
sourceDir?: string;
+ /**
+ * The root of the application.
+ */
+ appRoot?: string;
/**
* Specifies if a spec file is generated.
*/
diff --git a/packages/schematics/angular/class/schema.json b/packages/schematics/angular/class/schema.json
index c1ba53d608..a746f7569a 100644
--- a/packages/schematics/angular/class/schema.json
+++ b/packages/schematics/angular/class/schema.json
@@ -5,18 +5,25 @@
"type": "object",
"properties": {
"name": {
- "type": "string"
- },
- "appRoot": {
- "type": "string"
+ "type": "string",
+ "description": "The name of the class."
},
"path": {
"type": "string",
- "default": "app"
+ "description": "The path to create the class.",
+ "default": "app",
+ "visible": false
},
"sourceDir": {
"type": "string",
- "default": "src"
+ "description": "The path of the source directory.",
+ "default": "src",
+ "visible": false
+ },
+ "appRoot": {
+ "type": "string",
+ "description": "The root of the application.",
+ "visible": false
},
"spec": {
"type": "boolean",
diff --git a/packages/schematics/angular/component/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html b/packages/schematics/angular/component/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html
index 6c17d15fd5..0e75382ec6 100644
--- a/packages/schematics/angular/component/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html
+++ b/packages/schematics/angular/component/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.html
@@ -1,3 +1,3 @@
-<% if (htmlTemplate) { %><%= htmlTemplate %><% } else { %>
+
<%= dasherize(name) %> works!
-
<% } %>
+
diff --git a/packages/schematics/angular/component/index_spec.ts b/packages/schematics/angular/component/index_spec.ts
index b9b138086f..6badbcbbbb 100644
--- a/packages/schematics/angular/component/index_spec.ts
+++ b/packages/schematics/angular/component/index_spec.ts
@@ -24,7 +24,6 @@ describe('Component Schematic', () => {
inlineStyle: false,
inlineTemplate: false,
changeDetection: 'Default',
- routing: false,
styleext: 'css',
spec: true,
module: undefined,
diff --git a/packages/schematics/angular/component/schema.d.ts b/packages/schematics/angular/component/schema.d.ts
index 864d6882b5..3a410e13ee 100644
--- a/packages/schematics/angular/component/schema.d.ts
+++ b/packages/schematics/angular/component/schema.d.ts
@@ -7,9 +7,21 @@
*/
export interface Schema {
+ /**
+ * The path to create the component.
+ */
path?: string;
- appRoot?: string;
+ /**
+ * The path of the source directory.
+ */
sourceDir?: string;
+ /**
+ * The root of the application.
+ */
+ appRoot?: string;
+ /**
+ * The name of the component.
+ */
name: string;
/**
* Specifies if the style will be in the ts file.
@@ -27,7 +39,6 @@ export interface Schema {
* Specifies the change detection strategy.
*/
changeDetection?: ('Default' | 'OnPush');
- routing?: boolean;
/**
* The prefix to apply to generated selectors.
*/
@@ -36,13 +47,21 @@ export interface Schema {
* The file extension to be used for style files.
*/
styleext?: string;
+ /**
+ * Specifies if a spec file is generated.
+ */
spec?: boolean;
/**
* Flag to indicate if a dir is created.
*/
flat?: boolean;
- htmlTemplate?: string;
+ /**
+ * Flag to skip the module import.
+ */
skipImport?: boolean;
+ /**
+ * The selector to use for the component.
+ */
selector?: string;
/**
* Allows specification of the declaring module.
diff --git a/packages/schematics/angular/component/schema.json b/packages/schematics/angular/component/schema.json
index 83aff6e773..990a30665a 100644
--- a/packages/schematics/angular/component/schema.json
+++ b/packages/schematics/angular/component/schema.json
@@ -1,23 +1,30 @@
{
"$schema": "http://json-schema.org/schema",
"id": "SchematicsAngularComponent",
- "title": "Angular Application Options Schema",
+ "title": "Angular Component Options Schema",
"type": "object",
"properties": {
"path": {
"type": "string",
- "default": "app"
- },
- "appRoot": {
- "type": "string"
+ "description": "The path to create the component.",
+ "default": "app",
+ "visible": false
},
"sourceDir": {
"type": "string",
+ "description": "The path of the source directory.",
"default": "src",
- "alias": "sd"
+ "alias": "sd",
+ "visible": false
+ },
+ "appRoot": {
+ "type": "string",
+ "description": "The root of the application.",
+ "visible": false
},
"name": {
- "type": "string"
+ "type": "string",
+ "description": "The name of the component."
},
"inlineStyle": {
"description": "Specifies if the style will be in the ts file.",
@@ -44,10 +51,6 @@
"default": "Default",
"alias": "cd"
},
- "routing": {
- "type": "boolean",
- "default": false
- },
"prefix": {
"type": "string",
"description": "The prefix to apply to generated selectors.",
@@ -61,6 +64,7 @@
},
"spec": {
"type": "boolean",
+ "description": "Specifies if a spec file is generated.",
"default": true
},
"flat": {
@@ -68,15 +72,14 @@
"description": "Flag to indicate if a dir is created.",
"default": false
},
- "htmlTemplate": {
- "type": "string"
- },
"skipImport": {
"type": "boolean",
+ "description": "Flag to skip the module import.",
"default": false
},
"selector": {
- "type": "string"
+ "type": "string",
+ "description": "The selector to use for the component."
},
"module": {
"type": "string",
diff --git a/packages/schematics/angular/directive/schema.d.ts b/packages/schematics/angular/directive/schema.d.ts
index eb5436aade..b7a4e94e75 100644
--- a/packages/schematics/angular/directive/schema.d.ts
+++ b/packages/schematics/angular/directive/schema.d.ts
@@ -7,19 +7,37 @@
*/
export interface Schema {
+ /**
+ * The name of the directive.
+ */
name: string;
+ /**
+ * The path to create the directive.
+ */
path?: string;
+ /**
+ * The root of the application.
+ */
appRoot?: string;
/**
* The prefix to apply to generated selectors.
*/
prefix?: string;
+ /**
+ * The path of the source directory.
+ */
sourceDir?: string;
/**
* Specifies if a spec file is generated.
*/
spec?: boolean;
+ /**
+ * Flag to skip the module import.
+ */
skipImport?: boolean;
+ /**
+ * The selector to use for the directive.
+ */
selector?: string;
/**
* Flag to indicate if a dir is created.
diff --git a/packages/schematics/angular/directive/schema.json b/packages/schematics/angular/directive/schema.json
index ccf145b978..eb4e3e4c5d 100644
--- a/packages/schematics/angular/directive/schema.json
+++ b/packages/schematics/angular/directive/schema.json
@@ -1,18 +1,23 @@
{
"$schema": "http://json-schema.org/schema",
- "id": "SchematicsAngularClass",
- "title": "Angular Class Options Schema",
+ "id": "SchematicsAngularDirective",
+ "title": "Angular Directive Options Schema",
"type": "object",
"properties": {
"name": {
- "type": "string"
+ "type": "string",
+ "description": "The name of the directive."
},
"path": {
"type": "string",
- "default": "app"
+ "description": "The path to create the directive.",
+ "default": "app",
+ "visible": false
},
"appRoot": {
- "type": "string"
+ "type": "string",
+ "description": "The root of the application.",
+ "visible": false
},
"prefix": {
"type": "string",
@@ -22,7 +27,9 @@
},
"sourceDir": {
"type": "string",
- "default": "src"
+ "description": "The path of the source directory.",
+ "default": "src",
+ "visible": false
},
"spec": {
"type": "boolean",
@@ -31,10 +38,12 @@
},
"skipImport": {
"type": "boolean",
+ "description": "Flag to skip the module import.",
"default": false
},
"selector": {
- "type": "string"
+ "type": "string",
+ "description": "The selector to use for the directive."
},
"flat": {
"type": "boolean",
diff --git a/packages/schematics/angular/enum/schema.d.ts b/packages/schematics/angular/enum/schema.d.ts
index 9d7ef0fc2c..b1176ecf52 100644
--- a/packages/schematics/angular/enum/schema.d.ts
+++ b/packages/schematics/angular/enum/schema.d.ts
@@ -7,8 +7,20 @@
*/
export interface Schema {
+ /**
+ * The name of the enum.
+ */
name: string;
+ /**
+ * The path to create the enum.
+ */
path?: string;
- appRoot?: string;
+ /**
+ * The path of the source directory.
+ */
sourceDir?: string;
+ /**
+ * The root of the application.
+ */
+ appRoot?: string;
}
diff --git a/packages/schematics/angular/enum/schema.json b/packages/schematics/angular/enum/schema.json
index a4d4a9a2e3..dc5dc5ccf3 100644
--- a/packages/schematics/angular/enum/schema.json
+++ b/packages/schematics/angular/enum/schema.json
@@ -5,18 +5,25 @@
"type": "object",
"properties": {
"name": {
- "type": "string"
+ "type": "string",
+ "description": "The name of the enum."
},
"path": {
"type": "string",
- "default": "app"
- },
- "appRoot": {
- "type": "string"
+ "description": "The path to create the enum.",
+ "default": "app",
+ "visible": false
},
"sourceDir": {
"type": "string",
- "default": "src"
+ "description": "The path of the source directory.",
+ "default": "src",
+ "visible": false
+ },
+ "appRoot": {
+ "type": "string",
+ "description": "The root of the application.",
+ "visible": false
}
},
"required": [
diff --git a/packages/schematics/angular/guard/schema.d.ts b/packages/schematics/angular/guard/schema.d.ts
index e1730bb937..93ac2aacb3 100644
--- a/packages/schematics/angular/guard/schema.d.ts
+++ b/packages/schematics/angular/guard/schema.d.ts
@@ -7,14 +7,32 @@
*/
export interface Schema {
+ /**
+ * The name of the guard.
+ */
name: string;
+ /**
+ * Specifies if a spec file is generated.
+ */
spec?: boolean;
+ /**
+ * Flag to indicate if a dir is created.
+ */
flat?: boolean;
/**
* Allows specification of the declaring module.
*/
module?: string;
+ /**
+ * The path to create the guard.
+ */
path?: string;
- appRoot?: string;
+ /**
+ * The path of the source directory.
+ */
sourceDir?: string;
+ /**
+ * The root of the application.
+ */
+ appRoot?: string;
}
diff --git a/packages/schematics/angular/guard/schema.json b/packages/schematics/angular/guard/schema.json
index 18c65012f8..614e286da3 100644
--- a/packages/schematics/angular/guard/schema.json
+++ b/packages/schematics/angular/guard/schema.json
@@ -5,14 +5,17 @@
"type": "object",
"properties": {
"name": {
- "type": "string"
+ "type": "string",
+ "description": "The name of the guard."
},
"spec": {
"type": "boolean",
+ "description": "Specifies if a spec file is generated.",
"default": true
},
"flat": {
"type": "boolean",
+ "description": "Flag to indicate if a dir is created.",
"default": true
},
"module": {
@@ -23,14 +26,20 @@
},
"path": {
"type": "string",
- "default": "app"
- },
- "appRoot": {
- "type": "string"
+ "description": "The path to create the guard.",
+ "default": "app",
+ "visible": false
},
"sourceDir": {
"type": "string",
- "default": "src"
+ "description": "The path of the source directory.",
+ "default": "src",
+ "visible": false
+ },
+ "appRoot": {
+ "type": "string",
+ "description": "The root of the application.",
+ "visible": false
}
},
"required": [
diff --git a/packages/schematics/angular/interface/schema.d.ts b/packages/schematics/angular/interface/schema.d.ts
index 1091c0d3c5..92f220ab94 100644
--- a/packages/schematics/angular/interface/schema.d.ts
+++ b/packages/schematics/angular/interface/schema.d.ts
@@ -7,10 +7,22 @@
*/
export interface Schema {
+ /**
+ * The name of the interface.
+ */
name: string;
+ /**
+ * The path to create the interface.
+ */
path?: string;
- appRoot?: string;
+ /**
+ * The path of the source directory.
+ */
sourceDir?: string;
+ /**
+ * The root of the application.
+ */
+ appRoot?: string;
/**
* Specifies the prefix to use.
*/
diff --git a/packages/schematics/angular/interface/schema.json b/packages/schematics/angular/interface/schema.json
index 6d82532e23..62765b2820 100644
--- a/packages/schematics/angular/interface/schema.json
+++ b/packages/schematics/angular/interface/schema.json
@@ -5,18 +5,25 @@
"type": "object",
"properties": {
"name": {
- "type": "string"
+ "type": "string",
+ "description": "The name of the interface."
},
"path": {
"type": "string",
- "default": "app"
- },
- "appRoot": {
- "type": "string"
+ "description": "The path to create the interface.",
+ "default": "app",
+ "visible": false
},
"sourceDir": {
"type": "string",
- "default": "src"
+ "description": "The path of the source directory.",
+ "default": "src",
+ "visible": false
+ },
+ "appRoot": {
+ "type": "string",
+ "description": "The root of the application.",
+ "visible": false
},
"prefix": {
"type": "string",
diff --git a/packages/schematics/angular/module/schema.d.ts b/packages/schematics/angular/module/schema.d.ts
index d5e6d89ba5..12e908551e 100644
--- a/packages/schematics/angular/module/schema.d.ts
+++ b/packages/schematics/angular/module/schema.d.ts
@@ -7,14 +7,41 @@
*/
export interface Schema {
+ /**
+ * The name of the module.
+ */
name: string;
+ /**
+ * The path to create the module.
+ */
path?: string;
- appRoot?: string;
+ /**
+ * The path of the source directory.
+ */
sourceDir?: string;
+ /**
+ * The root of the application.
+ */
+ appRoot?: string;
+ /**
+ * Generates a routing module.
+ */
routing?: boolean;
+ /**
+ * The scope for the generated routing.
+ */
routingScope?: ('Child' | 'Root');
+ /**
+ * Specifies if a spec file is generated.
+ */
spec?: boolean;
+ /**
+ * Flag to indicate if a dir is created.
+ */
flat?: boolean;
+ /**
+ * Flag to control whether the CommonModule is imported.
+ */
commonModule?: boolean;
/**
* Allows specification of the declaring module.
diff --git a/packages/schematics/angular/module/schema.json b/packages/schematics/angular/module/schema.json
index 303c9088c6..5dc35b6224 100644
--- a/packages/schematics/angular/module/schema.json
+++ b/packages/schematics/angular/module/schema.json
@@ -5,39 +5,52 @@
"type": "object",
"properties": {
"name": {
- "type": "string"
+ "type": "string",
+ "description": "The name of the module."
},
"path": {
"type": "string",
- "default": "app"
- },
- "appRoot": {
- "type": "string"
+ "description": "The path to create the module.",
+ "default": "app",
+ "visible": false
},
"sourceDir": {
"type": "string",
- "default": "src"
+ "description": "The path of the source directory.",
+ "default": "src",
+ "visible": false
+ },
+ "appRoot": {
+ "type": "string",
+ "description": "The root of the application.",
+ "visible": false
},
"routing": {
"type": "boolean",
+ "description": "Generates a routing module.",
"default": false
},
"routingScope": {
"enum": ["Child", "Root"],
"type": "string",
+ "description": "The scope for the generated routing.",
"default": "Child"
},
"spec": {
"type": "boolean",
+ "description": "Specifies if a spec file is generated.",
"default": true
},
"flat": {
"type": "boolean",
+ "description": "Flag to indicate if a dir is created.",
"default": false
},
"commonModule": {
"type": "boolean",
- "default": true
+ "description": "Flag to control whether the CommonModule is imported.",
+ "default": true,
+ "visible": false
},
"module": {
"type": "string",
diff --git a/packages/schematics/angular/pipe/schema.d.ts b/packages/schematics/angular/pipe/schema.d.ts
index f8e849e7ef..562afd6ecb 100644
--- a/packages/schematics/angular/pipe/schema.d.ts
+++ b/packages/schematics/angular/pipe/schema.d.ts
@@ -7,10 +7,22 @@
*/
export interface Schema {
+ /**
+ * The name of the pipe.
+ */
name: string;
+ /**
+ * The path to create the pipe.
+ */
path?: string;
- appRoot?: string;
+ /**
+ * The path of the source directory.
+ */
sourceDir?: string;
+ /**
+ * The root of the application.
+ */
+ appRoot?: string;
/**
* Flag to indicate if a dir is created.
*/
diff --git a/packages/schematics/angular/pipe/schema.json b/packages/schematics/angular/pipe/schema.json
index 2c5ae12562..505eef4a25 100644
--- a/packages/schematics/angular/pipe/schema.json
+++ b/packages/schematics/angular/pipe/schema.json
@@ -5,18 +5,25 @@
"type": "object",
"properties": {
"name": {
- "type": "string"
+ "type": "string",
+ "description": "The name of the pipe."
},
"path": {
"type": "string",
- "default": "app"
- },
- "appRoot": {
- "type": "string"
+ "description": "The path to create the pipe.",
+ "default": "app",
+ "visible": false
},
"sourceDir": {
"type": "string",
- "default": "src"
+ "description": "The path of the source directory.",
+ "default": "src",
+ "visible": false
+ },
+ "appRoot": {
+ "type": "string",
+ "description": "The root of the application.",
+ "visible": false
},
"flat": {
"type": "boolean",
diff --git a/packages/schematics/angular/service/schema.d.ts b/packages/schematics/angular/service/schema.d.ts
index 2cab9fc88f..068b07b7f2 100644
--- a/packages/schematics/angular/service/schema.d.ts
+++ b/packages/schematics/angular/service/schema.d.ts
@@ -7,10 +7,22 @@
*/
export interface Schema {
+ /**
+ * The name of the service.
+ */
name: string;
+ /**
+ * The path to create the service.
+ */
path?: string;
- appRoot?: string;
+ /**
+ * The path of the source directory.
+ */
sourceDir?: string;
+ /**
+ * The root of the application.
+ */
+ appRoot?: string;
/**
* Flag to indicate if a dir is created.
*/
@@ -20,7 +32,7 @@ export interface Schema {
*/
spec?: boolean;
/**
- * Allows specification of the declaring module.
+ * Allows specification of the providing module.
*/
module?: string;
}
diff --git a/packages/schematics/angular/service/schema.json b/packages/schematics/angular/service/schema.json
index 6585669a18..082ef3c672 100644
--- a/packages/schematics/angular/service/schema.json
+++ b/packages/schematics/angular/service/schema.json
@@ -5,18 +5,25 @@
"type": "object",
"properties": {
"name": {
- "type": "string"
+ "type": "string",
+ "description": "The name of the service."
},
"path": {
"type": "string",
- "default": "app"
- },
- "appRoot": {
- "type": "string"
+ "description": "The path to create the service.",
+ "default": "app",
+ "visible": false
},
"sourceDir": {
"type": "string",
- "default": "src"
+ "description": "The path of the source directory.",
+ "default": "src",
+ "visible": false
+ },
+ "appRoot": {
+ "type": "string",
+ "description": "The root of the application.",
+ "visible": false
},
"flat": {
"type": "boolean",
@@ -31,7 +38,7 @@
"module": {
"type": "string",
"default": "",
- "description": "Allows specification of the declaring module.",
+ "description": "Allows specification of the providing module.",
"alias": "m",
"subtype": "filepath"
}
diff --git a/packages/schematics/angular/universal/schema.json b/packages/schematics/angular/universal/schema.json
index 87c26fd161..d6ce90f041 100644
--- a/packages/schematics/angular/universal/schema.json
+++ b/packages/schematics/angular/universal/schema.json
@@ -6,7 +6,7 @@
"properties": {
"name": {
"type": "string",
- "description": "Name of the universal app"
+ "description": "Name of the universal app."
},
"clientApp": {
"type": "string",
@@ -69,6 +69,7 @@
},
"sourceDir": {
"type": "string",
+ "description": "The path of the source directory.",
"default": "src",
"alias": "sd"
}
From c3bbf1b64c9c2b9afa122bdec17803b907e15a0f Mon Sep 17 00:00:00 2001
From: Mike Brocchi
Date: Tue, 5 Dec 2017 16:28:31 -0500
Subject: [PATCH 044/807] fix(@schematics/angular): Remove change detection
option
Setting of change detection on the root component of an application is invalid.
---
packages/schematics/angular/app-shell/index_spec.ts | 1 -
packages/schematics/angular/application/index_spec.ts | 1 -
packages/schematics/angular/application/schema.d.ts | 4 ----
packages/schematics/angular/application/schema.json | 6 ------
packages/schematics/angular/universal/index_spec.ts | 1 -
5 files changed, 13 deletions(-)
diff --git a/packages/schematics/angular/app-shell/index_spec.ts b/packages/schematics/angular/app-shell/index_spec.ts
index e9e59351ec..f1381e9a87 100644
--- a/packages/schematics/angular/app-shell/index_spec.ts
+++ b/packages/schematics/angular/app-shell/index_spec.ts
@@ -32,7 +32,6 @@ describe('App Shell Schematic', () => {
inlineStyle: false,
inlineTemplate: false,
viewEncapsulation: 'None',
- changeDetection: 'Default',
version: '1.2.3',
routing: true,
style: 'css',
diff --git a/packages/schematics/angular/application/index_spec.ts b/packages/schematics/angular/application/index_spec.ts
index d95e042284..f61c8f38a2 100644
--- a/packages/schematics/angular/application/index_spec.ts
+++ b/packages/schematics/angular/application/index_spec.ts
@@ -25,7 +25,6 @@ describe('Application Schematic', () => {
inlineStyle: false,
inlineTemplate: false,
viewEncapsulation: 'Emulated',
- changeDetection: 'Default',
version: '1.2.3',
routing: false,
style: 'css',
diff --git a/packages/schematics/angular/application/schema.d.ts b/packages/schematics/angular/application/schema.d.ts
index bd5249790c..273eb3db0e 100644
--- a/packages/schematics/angular/application/schema.d.ts
+++ b/packages/schematics/angular/application/schema.d.ts
@@ -35,10 +35,6 @@ export interface Schema {
* Specifies the view encapsulation strategy.
*/
viewEncapsulation?: ('Emulated' | 'Native' | 'None');
- /**
- * Specifies the change detection strategy.
- */
- changeDetection?: ('Default' | 'OnPush');
/**
* The version of the Angular CLI to use.
*/
diff --git a/packages/schematics/angular/application/schema.json b/packages/schematics/angular/application/schema.json
index 15ede3bf65..2a756112ea 100644
--- a/packages/schematics/angular/application/schema.json
+++ b/packages/schematics/angular/application/schema.json
@@ -43,12 +43,6 @@
"enum": ["Emulated", "Native", "None"],
"type": "string"
},
- "changeDetection": {
- "description": "Specifies the change detection strategy.",
- "enum": ["Default", "OnPush"],
- "type": "string",
- "default": "Default"
- },
"version": {
"type": "string",
"description": "The version of the Angular CLI to use.",
diff --git a/packages/schematics/angular/universal/index_spec.ts b/packages/schematics/angular/universal/index_spec.ts
index fedf211a30..1added509a 100644
--- a/packages/schematics/angular/universal/index_spec.ts
+++ b/packages/schematics/angular/universal/index_spec.ts
@@ -33,7 +33,6 @@ describe('Universal Schematic', () => {
inlineStyle: false,
inlineTemplate: false,
viewEncapsulation: 'None',
- changeDetection: 'Default',
version: '1.2.3',
routing: false,
style: 'css',
From 55ab1606dcbce281b360fa6faffbd1ba78b4f1e2 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Tue, 5 Dec 2017 16:12:09 -0800
Subject: [PATCH 045/807] test(@angular-devkit/schematics): adding some rename
regression tests
---
.../schematics/src/tree/virtual_spec.ts | 46 +++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/packages/angular_devkit/schematics/src/tree/virtual_spec.ts b/packages/angular_devkit/schematics/src/tree/virtual_spec.ts
index 11099a39d4..d6112a81a2 100644
--- a/packages/angular_devkit/schematics/src/tree/virtual_spec.ts
+++ b/packages/angular_devkit/schematics/src/tree/virtual_spec.ts
@@ -178,5 +178,51 @@ describe('VirtualTree', () => {
const fileEntry = tree.get('/hello');
expect((fileEntry as FileEntry).content.toString()).toEqual(newContent);
});
+
+ it('can rename files in base', () => {
+ const host = new InMemoryFileSystemTreeHost({
+ '/hello': 'world',
+ });
+ const tree = new FileSystemTree(host);
+
+ tree.rename('/hello', '/world');
+
+ const fileEntry = tree.get('/hello');
+ const fileEntry2 = tree.get('/world');
+ expect((fileEntry as FileEntry).content.toString())
+ .toEqual((fileEntry2 as FileEntry).content.toString());
+ });
+
+ it('can rename files created in staging', () => {
+ const host = new InMemoryFileSystemTreeHost({
+ });
+ const tree = new FileSystemTree(host);
+
+ tree.create('/hello', 'world');
+ tree.rename('/hello', '/hello2');
+
+ expect(tree.exists('/hello')).toBe(false);
+ const fileEntry = tree.get('/hello2');
+ expect((fileEntry as FileEntry).content.toString())
+ .toEqual('world');
+ });
+
+ it('can rename branched and merged trees', () => {
+ const host = new InMemoryFileSystemTreeHost({
+ '/hello': 'world',
+ });
+ const tree = new FileSystemTree(host);
+ const tree2 = tree.branch();
+
+ expect(tree2.exists('/hello')).toBe(true);
+ tree2.rename('/hello', '/hello2');
+ expect(tree2.exists('/hello2')).toBe(true);
+
+ tree.merge(tree2);
+ expect(tree.exists('/hello2')).toBe(true);
+ const fileEntry = tree.get('/hello2');
+ expect((fileEntry as FileEntry).content.toString())
+ .toEqual('world');
+ });
});
});
From ddbf9fdf2ce766a16f147c339846489f012800c4 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Tue, 5 Dec 2017 16:47:00 -0800
Subject: [PATCH 046/807] fix(@angular-devkit/schematics): do not try to read
the file on rename
Previously the logic for renaming was faulty in that it tried to create the new file
and delete the old one. If the file was on disk though it could not be read and threw
FileDoesNotExist. That logic is all wrong and the Virtual FS should simply try to
move the file using its host (which it now does properly).
---
.../schematics/src/sink/virtual-filesystem.ts | 20 +------------------
1 file changed, 1 insertion(+), 19 deletions(-)
diff --git a/packages/angular_devkit/schematics/src/sink/virtual-filesystem.ts b/packages/angular_devkit/schematics/src/sink/virtual-filesystem.ts
index 9124876958..a2ba8e2fff 100644
--- a/packages/angular_devkit/schematics/src/sink/virtual-filesystem.ts
+++ b/packages/angular_devkit/schematics/src/sink/virtual-filesystem.ts
@@ -13,7 +13,6 @@ import 'rxjs/add/observable/of';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/reduce';
-import { FileDoesNotExistException } from '../exception/exception';
import { CreateFileAction } from '../tree/action';
import { UpdateBuffer } from '../utility/update-buffer';
import { SimpleSinkBase } from './sink';
@@ -39,20 +38,6 @@ export abstract class VirtualFileSystemSink extends SimpleSinkBase {
return this._force ? Observable.empty() : super._validateCreateAction(action);
}
- protected _readFile(p: string): Observable {
- const maybeCreate = this._filesToCreate.get(p);
- if (maybeCreate) {
- return Observable.of(maybeCreate);
- }
-
- const maybeUpdate = this._filesToUpdate.get(p);
- if (maybeUpdate) {
- return Observable.of(maybeUpdate);
- }
-
- throw new FileDoesNotExistException(p);
- }
-
protected _validateFileExists(p: string): Observable {
if (this._filesToCreate.has(p) || this._filesToUpdate.has(p)) {
return Observable.of(true);
@@ -76,10 +61,7 @@ export abstract class VirtualFileSystemSink extends SimpleSinkBase {
protected _renameFile(from: string, to: string): Observable {
this._filesToRename.add([from, to]);
- return this._readFile(from)
- .do(buffer => this._filesToCreate.set(to, buffer))
- .do(() => this._filesToDelete.add(from))
- .map(() => {});
+ return Observable.empty();
}
protected _deleteFile(path: string): Observable {
if (this._filesToCreate.has(path)) {
From 23bcc9886b6b443e5c7f450cb08cda25579b316c Mon Sep 17 00:00:00 2001
From: Mike Brocchi
Date: Mon, 4 Dec 2017 14:22:35 -0500
Subject: [PATCH 047/807] fix(@schematics/angular): Apply the source dir option
correctly for new projects.
Fixes angular/angular-cli#8417
---
.../schematics/angular/app-shell/index_spec.ts | 1 -
.../application/files/__path__/tsconfig.app.json | 13 -------------
.../assets/__dot__gitkeep | 0
.../environments/environment.prod.ts | 0
.../environments/environment.ts | 0
.../files/{__path__ => __sourcedir__}/favicon.ico | Bin
.../files/{__path__ => __sourcedir__}/index.html | 0
.../files/{__path__ => __sourcedir__}/main.ts | 0
.../{__path__ => __sourcedir__}/ngsw-config.json | 0
.../files/{__path__ => __sourcedir__}/polyfills.ts | 0
.../{__path__ => __sourcedir__}/styles.__style__ | 0
.../files/{__path__ => __sourcedir__}/test.ts | 0
.../files/__sourcedir__/tsconfig.app.json | 13 +++++++++++++
.../{__path__ => __sourcedir__}/tsconfig.spec.json | 4 ++--
.../files/{__path__ => __sourcedir__}/typings.d.ts | 0
packages/schematics/angular/application/index.ts | 5 ++++-
.../schematics/angular/application/index_spec.ts | 2 +-
.../schematics/angular/application/schema.json | 2 +-
.../schematics/angular/universal/index_spec.ts | 1 -
19 files changed, 21 insertions(+), 20 deletions(-)
delete mode 100644 packages/schematics/angular/application/files/__path__/tsconfig.app.json
rename packages/schematics/angular/application/files/{__path__ => __sourcedir__}/assets/__dot__gitkeep (100%)
rename packages/schematics/angular/application/files/{__path__ => __sourcedir__}/environments/environment.prod.ts (100%)
rename packages/schematics/angular/application/files/{__path__ => __sourcedir__}/environments/environment.ts (100%)
rename packages/schematics/angular/application/files/{__path__ => __sourcedir__}/favicon.ico (100%)
rename packages/schematics/angular/application/files/{__path__ => __sourcedir__}/index.html (100%)
rename packages/schematics/angular/application/files/{__path__ => __sourcedir__}/main.ts (100%)
rename packages/schematics/angular/application/files/{__path__ => __sourcedir__}/ngsw-config.json (100%)
rename packages/schematics/angular/application/files/{__path__ => __sourcedir__}/polyfills.ts (100%)
rename packages/schematics/angular/application/files/{__path__ => __sourcedir__}/styles.__style__ (100%)
rename packages/schematics/angular/application/files/{__path__ => __sourcedir__}/test.ts (100%)
create mode 100644 packages/schematics/angular/application/files/__sourcedir__/tsconfig.app.json
rename packages/schematics/angular/application/files/{__path__ => __sourcedir__}/tsconfig.spec.json (58%)
rename packages/schematics/angular/application/files/{__path__ => __sourcedir__}/typings.d.ts (100%)
diff --git a/packages/schematics/angular/app-shell/index_spec.ts b/packages/schematics/angular/app-shell/index_spec.ts
index f1381e9a87..800787a563 100644
--- a/packages/schematics/angular/app-shell/index_spec.ts
+++ b/packages/schematics/angular/app-shell/index_spec.ts
@@ -26,7 +26,6 @@ describe('App Shell Schematic', () => {
const appOptions: ApplicationOptions = {
directory: '',
name: 'app',
- path: 'src',
prefix: '',
sourceDir: 'src',
inlineStyle: false,
diff --git a/packages/schematics/angular/application/files/__path__/tsconfig.app.json b/packages/schematics/angular/application/files/__path__/tsconfig.app.json
deleted file mode 100644
index f5325db1cb..0000000000
--- a/packages/schematics/angular/application/files/__path__/tsconfig.app.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "extends": "<%= path.split('/').map(x => '..').join('/') %>/tsconfig.json",
- "compilerOptions": {
- "outDir": "<%= path.split('/').map(x => '..').join('/') %>/out-tsc/app",
- "baseUrl": "./",
- "module": "es2015",
- "types": []
- },
- "exclude": [
- "test.ts",
- "**/*.spec.ts"
- ]
-}
diff --git a/packages/schematics/angular/application/files/__path__/assets/__dot__gitkeep b/packages/schematics/angular/application/files/__sourcedir__/assets/__dot__gitkeep
similarity index 100%
rename from packages/schematics/angular/application/files/__path__/assets/__dot__gitkeep
rename to packages/schematics/angular/application/files/__sourcedir__/assets/__dot__gitkeep
diff --git a/packages/schematics/angular/application/files/__path__/environments/environment.prod.ts b/packages/schematics/angular/application/files/__sourcedir__/environments/environment.prod.ts
similarity index 100%
rename from packages/schematics/angular/application/files/__path__/environments/environment.prod.ts
rename to packages/schematics/angular/application/files/__sourcedir__/environments/environment.prod.ts
diff --git a/packages/schematics/angular/application/files/__path__/environments/environment.ts b/packages/schematics/angular/application/files/__sourcedir__/environments/environment.ts
similarity index 100%
rename from packages/schematics/angular/application/files/__path__/environments/environment.ts
rename to packages/schematics/angular/application/files/__sourcedir__/environments/environment.ts
diff --git a/packages/schematics/angular/application/files/__path__/favicon.ico b/packages/schematics/angular/application/files/__sourcedir__/favicon.ico
similarity index 100%
rename from packages/schematics/angular/application/files/__path__/favicon.ico
rename to packages/schematics/angular/application/files/__sourcedir__/favicon.ico
diff --git a/packages/schematics/angular/application/files/__path__/index.html b/packages/schematics/angular/application/files/__sourcedir__/index.html
similarity index 100%
rename from packages/schematics/angular/application/files/__path__/index.html
rename to packages/schematics/angular/application/files/__sourcedir__/index.html
diff --git a/packages/schematics/angular/application/files/__path__/main.ts b/packages/schematics/angular/application/files/__sourcedir__/main.ts
similarity index 100%
rename from packages/schematics/angular/application/files/__path__/main.ts
rename to packages/schematics/angular/application/files/__sourcedir__/main.ts
diff --git a/packages/schematics/angular/application/files/__path__/ngsw-config.json b/packages/schematics/angular/application/files/__sourcedir__/ngsw-config.json
similarity index 100%
rename from packages/schematics/angular/application/files/__path__/ngsw-config.json
rename to packages/schematics/angular/application/files/__sourcedir__/ngsw-config.json
diff --git a/packages/schematics/angular/application/files/__path__/polyfills.ts b/packages/schematics/angular/application/files/__sourcedir__/polyfills.ts
similarity index 100%
rename from packages/schematics/angular/application/files/__path__/polyfills.ts
rename to packages/schematics/angular/application/files/__sourcedir__/polyfills.ts
diff --git a/packages/schematics/angular/application/files/__path__/styles.__style__ b/packages/schematics/angular/application/files/__sourcedir__/styles.__style__
similarity index 100%
rename from packages/schematics/angular/application/files/__path__/styles.__style__
rename to packages/schematics/angular/application/files/__sourcedir__/styles.__style__
diff --git a/packages/schematics/angular/application/files/__path__/test.ts b/packages/schematics/angular/application/files/__sourcedir__/test.ts
similarity index 100%
rename from packages/schematics/angular/application/files/__path__/test.ts
rename to packages/schematics/angular/application/files/__sourcedir__/test.ts
diff --git a/packages/schematics/angular/application/files/__sourcedir__/tsconfig.app.json b/packages/schematics/angular/application/files/__sourcedir__/tsconfig.app.json
new file mode 100644
index 0000000000..939fe613af
--- /dev/null
+++ b/packages/schematics/angular/application/files/__sourcedir__/tsconfig.app.json
@@ -0,0 +1,13 @@
+{
+ "extends": "<%= sourcedir.split('/').map(x => '..').join('/') %>/tsconfig.json",
+ "compilerOptions": {
+ "outDir": "<%= sourcedir.split('/').map(x => '..').join('/') %>/out-tsc/app",
+ "baseUrl": "./",
+ "module": "es2015",
+ "types": []
+ },
+ "exclude": [
+ "test.ts",
+ "**/*.spec.ts"
+ ]
+}
diff --git a/packages/schematics/angular/application/files/__path__/tsconfig.spec.json b/packages/schematics/angular/application/files/__sourcedir__/tsconfig.spec.json
similarity index 58%
rename from packages/schematics/angular/application/files/__path__/tsconfig.spec.json
rename to packages/schematics/angular/application/files/__sourcedir__/tsconfig.spec.json
index 6f3ecd9009..97ebdc48c2 100644
--- a/packages/schematics/angular/application/files/__path__/tsconfig.spec.json
+++ b/packages/schematics/angular/application/files/__sourcedir__/tsconfig.spec.json
@@ -1,7 +1,7 @@
{
- "extends": "<%= path.split('/').map(x => '..').join('/') %>/tsconfig.json",
+ "extends": "<%= sourcedir.split('/').map(x => '..').join('/') %>/tsconfig.json",
"compilerOptions": {
- "outDir": "<%= path.split('/').map(x => '..').join('/') %>/out-tsc/spec",
+ "outDir": "<%= sourcedir.split('/').map(x => '..').join('/') %>/out-tsc/spec",
"baseUrl": "./",
"module": "commonjs",
"target": "es5",
diff --git a/packages/schematics/angular/application/files/__path__/typings.d.ts b/packages/schematics/angular/application/files/__sourcedir__/typings.d.ts
similarity index 100%
rename from packages/schematics/angular/application/files/__path__/typings.d.ts
rename to packages/schematics/angular/application/files/__sourcedir__/typings.d.ts
diff --git a/packages/schematics/angular/application/index.ts b/packages/schematics/angular/application/index.ts
index 8b811a048a..db762a8ecf 100644
--- a/packages/schematics/angular/application/index.ts
+++ b/packages/schematics/angular/application/index.ts
@@ -98,8 +98,9 @@ export default function (options: ApplicationOptions): Rule {
options.serviceWorker ? noop() : filter(path => !path.endsWith('/ngsw-config.json')),
template({
utils: stringUtils,
- 'dot': '.',
...options as object,
+ 'dot': '.',
+ sourcedir: sourceDir,
}),
move(options.directory),
])),
@@ -109,6 +110,7 @@ export default function (options: ApplicationOptions): Rule {
flat: true,
routing: options.routing,
routingScope: 'Root',
+ path: options.path,
sourceDir: options.directory + '/' + sourceDir,
spec: false,
}),
@@ -117,6 +119,7 @@ export default function (options: ApplicationOptions): Rule {
selector: appRootSelector,
sourceDir: options.directory + '/' + sourceDir,
flat: true,
+ path: options.path,
...componentOptions,
}),
addBootstrapToNgModule(options.directory, sourceDir),
diff --git a/packages/schematics/angular/application/index_spec.ts b/packages/schematics/angular/application/index_spec.ts
index f61c8f38a2..af02ff53a4 100644
--- a/packages/schematics/angular/application/index_spec.ts
+++ b/packages/schematics/angular/application/index_spec.ts
@@ -19,7 +19,6 @@ describe('Application Schematic', () => {
const defaultOptions: ApplicationOptions = {
directory: 'foo',
name: 'foo',
- path: 'src',
prefix: '',
sourceDir: 'src',
inlineStyle: false,
@@ -78,6 +77,7 @@ describe('Application Schematic', () => {
// tslint:disable-next-line:non-null-operator
const files = tree !.files;
expect(files.indexOf('/foo/some/custom/path/app/app.module.ts')).toBeGreaterThanOrEqual(0);
+ expect(files.indexOf('/foo/some/custom/path/tsconfig.app.json')).toBeGreaterThanOrEqual(0);
}
});
diff --git a/packages/schematics/angular/application/schema.json b/packages/schematics/angular/application/schema.json
index 2a756112ea..4e6e6c890c 100644
--- a/packages/schematics/angular/application/schema.json
+++ b/packages/schematics/angular/application/schema.json
@@ -12,7 +12,7 @@
"path": {
"type": "string",
"description": "The path of the application.",
- "default": "src",
+ "default": "app",
"visible": false
},
"sourceDir": {
diff --git a/packages/schematics/angular/universal/index_spec.ts b/packages/schematics/angular/universal/index_spec.ts
index 1added509a..07b7a705d4 100644
--- a/packages/schematics/angular/universal/index_spec.ts
+++ b/packages/schematics/angular/universal/index_spec.ts
@@ -27,7 +27,6 @@ describe('Universal Schematic', () => {
const appOptions: ApplicationOptions = {
directory: '',
name: 'app',
- path: 'src',
prefix: '',
sourceDir: 'src',
inlineStyle: false,
From c16b8414700dfc7122e589fabf3b0220eb35b8a8 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Tue, 5 Dec 2017 15:23:53 -0800
Subject: [PATCH 048/807] build: remove peerDependencies from package
dependencies
---
lib/packages.ts | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/lib/packages.ts b/lib/packages.ts
index 139db0e840..c4ac80fce6 100644
--- a/lib/packages.ts
+++ b/lib/packages.ts
@@ -207,8 +207,7 @@ for (const pkgName of Object.keys(packages)) {
const pkgJson = require(path.join(pkg.root, 'package.json'));
pkg.dependencies = Object.keys(packages).filter(name => {
return name in (pkgJson.dependencies || {})
- || name in (pkgJson.devDependencies || {})
- || name in (pkgJson.peerDependencies || {});
+ || name in (pkgJson.devDependencies || {});
});
}
From 195fbee671d9be1c49942feecb08a248c66827eb Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Tue, 5 Dec 2017 14:46:51 -0800
Subject: [PATCH 049/807] fix(@schematics/schematics): fix missing dependencies
---
packages/angular_devkit/schematics/package.json | 1 +
packages/schematics/schematics/package.json | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/packages/angular_devkit/schematics/package.json b/packages/angular_devkit/schematics/package.json
index 7a8acbd059..1b13d2c30d 100644
--- a/packages/angular_devkit/schematics/package.json
+++ b/packages/angular_devkit/schematics/package.json
@@ -21,6 +21,7 @@
"dependencies": {
"@angular-devkit/core": "0.0.0",
"@ngtools/json-schema": "^1.1.0",
+ "@schematics/schematics": "0.0.0",
"minimist": "^1.2.0",
"rxjs": "^5.5.2"
}
diff --git a/packages/schematics/schematics/package.json b/packages/schematics/schematics/package.json
index 20a020342a..f94a729df2 100644
--- a/packages/schematics/schematics/package.json
+++ b/packages/schematics/schematics/package.json
@@ -13,6 +13,8 @@
},
"schematics": "./collection.json",
"peerDependencies": {
- "@angular-devkit/schematics": "0.0.0"
+ "@angular-devkit/core": "0.0.0",
+ "@angular-devkit/schematics": "0.0.0",
+ "rxjs": "^5.5.2"
}
}
From a15c1ca903fa32413c324cd2e1a7fddcd70df8f6 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Wed, 6 Dec 2017 11:52:50 -0800
Subject: [PATCH 050/807] fix(@angular-devkit/schematics): fix random ordering
of actions
Actions were ordered wrongly before during commit to the filesystem. Now theyre
properly waited after before being committed, which fixes some inconsistencies.
---
.../schematics/src/sink/filesystem_spec.ts | 97 +++++++++++++++++--
.../schematics/src/sink/sink.ts | 4 +-
2 files changed, 92 insertions(+), 9 deletions(-)
diff --git a/packages/angular_devkit/schematics/src/sink/filesystem_spec.ts b/packages/angular_devkit/schematics/src/sink/filesystem_spec.ts
index 3d49f99875..134c0d4e07 100644
--- a/packages/angular_devkit/schematics/src/sink/filesystem_spec.ts
+++ b/packages/angular_devkit/schematics/src/sink/filesystem_spec.ts
@@ -6,8 +6,10 @@
* found in the LICENSE file at https://angular.io/license
*/
import { normalize } from '@angular-devkit/core';
+import { FileSystemTree, FileSystemTreeHost } from '@angular-devkit/schematics';
import * as fs from 'fs';
import * as glob from 'glob';
+import * as path from 'path';
import { join } from 'path';
import { FileSystemCreateTree } from '../tree/filesystem';
import { InMemoryFileSystemTreeHost } from '../tree/memory-host';
@@ -17,12 +19,51 @@ import { FileSystemSink } from './filesystem';
const temp = require('temp');
+// Tools cannot be a dependency of schematics, so we just put the same interface here.
+export class FileSystemHost implements FileSystemTreeHost {
+ constructor(private _root: string) {}
+
+ listDirectory(path: string) {
+ return fs.readdirSync(join(this._root, path));
+ }
+ isDirectory(path: string) {
+ return fs.statSync(join(this._root, path)).isDirectory();
+ }
+ readFile(path: string) {
+ return fs.readFileSync(join(this._root, path));
+ }
+ exists(path: string) {
+ return fs.existsSync(this.join(this._root, path));
+ }
+
+ join(path1: string, path2: string) {
+ return join(path1, path2);
+ }
+}
+
+
describe('FileSystemSink', () => {
let outputRoot: string;
beforeEach(() => {
outputRoot = temp.mkdirSync('schematics-spec-');
});
+ afterEach(() => {
+ // Delete the whole temporary directory.
+ function rmdir(systemPath: string) {
+ for (const name of fs.readdirSync(systemPath)) {
+ const systemName = path.join(systemPath, name);
+ if (fs.statSync(systemName).isDirectory()) {
+ rmdir(systemName);
+ fs.rmdirSync(systemName);
+ } else {
+ fs.unlinkSync(systemName);
+ }
+ }
+ }
+
+ rmdir(outputRoot);
+ });
it('works', done => {
const host = new InMemoryFileSystemTreeHost({
@@ -42,12 +83,54 @@ describe('FileSystemSink', () => {
const sink = new FileSystemSink(outputRoot);
sink.commit(optimize(tree))
- .toPromise()
- .then(() => {
- const tmpFiles = glob.sync(join(outputRoot, '**/*'), { nodir: true });
- expect(tmpFiles.map(x => x.substr(outputRoot.length))).toEqual(files);
- expect(fs.readFileSync(join(outputRoot, 'test'), 'utf-8')).toBe('testing testing 1 2');
- })
- .then(done, done.fail);
+ .toPromise()
+ .then(() => {
+ const tmpFiles = glob.sync(join(outputRoot, '**/*'), { nodir: true });
+ expect(tmpFiles.map(x => x.substr(outputRoot.length))).toEqual(files);
+ expect(fs.readFileSync(join(outputRoot, 'test'), 'utf-8')).toBe('testing testing 1 2');
+ })
+ .then(done, done.fail);
+ });
+
+ describe('complex tests', () => {
+ beforeEach(done => {
+ // Commit a version of the tree.
+ const host = new InMemoryFileSystemTreeHost({
+ '/file0': '/file0',
+ '/sub/directory/file2': '/sub/directory/file2',
+ '/sub/file1': '/sub/file1',
+ });
+ const tree = new FileSystemCreateTree(host);
+
+ const sink = new FileSystemSink(outputRoot);
+ sink.commit(optimize(tree))
+ .toPromise()
+ .then(done, done.fail);
+ });
+
+ it('can rename files', done => {
+ const tree = new FileSystemTree(new FileSystemHost(outputRoot));
+ tree.rename('/file0', '/file1');
+
+ const sink = new FileSystemSink(outputRoot);
+ sink.commit(optimize(tree))
+ .toPromise()
+ .then(() => {
+ expect(fs.existsSync(join(outputRoot, 'file0'))).toBe(false);
+ expect(fs.existsSync(join(outputRoot, 'file1'))).toBe(true);
+ })
+ .then(done, done.fail);
+ });
+
+ it('can delete and create the same file', done => {
+ const tree = new FileSystemTree(new FileSystemHost(outputRoot));
+ tree.delete('/file0');
+ tree.create('/file0', 'hello');
+
+ const sink = new FileSystemSink(outputRoot);
+ sink.commit(optimize(tree))
+ .toPromise()
+ .then(done, done.fail);
+ });
});
});
diff --git a/packages/angular_devkit/schematics/src/sink/sink.ts b/packages/angular_devkit/schematics/src/sink/sink.ts
index 23d196951c..af44221676 100644
--- a/packages/angular_devkit/schematics/src/sink/sink.ts
+++ b/packages/angular_devkit/schematics/src/sink/sink.ts
@@ -130,10 +130,10 @@ export abstract class SimpleSinkBase implements Sink {
return maybeAction;
}
})
- .mergeMap((action: Action) => {
+ .concatMap((action: Action) => {
return this.commitSingleAction(action).ignoreElements().concat([action]);
})
- .mergeMap((action: Action) => this.postCommitAction(action) || Observable.empty())
+ .concatMap((action: Action) => this.postCommitAction(action) || Observable.empty())
.concat(Observable.defer(() => this._done()))
.concat(Observable.defer(() => this.postCommit() || Observable.empty()));
}
From 5a220058605a40314dde1eb31aaa94816f7c9f42 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Wed, 6 Dec 2017 13:14:46 -0800
Subject: [PATCH 051/807] release: patch
---
.monorepo.json | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/.monorepo.json b/.monorepo.json
index 473b037740..0d1a6ee044 100644
--- a/.monorepo.json
+++ b/.monorepo.json
@@ -53,8 +53,8 @@
"url": "https://github.com/angular/devkit/blob/master/packages/angular_devkit/build_optimizer/README.md"
}
],
- "version": "0.0.34",
- "hash": "bf3b25ed5f8c6b5f4c3de1fc20c3b317"
+ "version": "0.0.35",
+ "hash": "88c0abf84c28c0423049af9e433d1fad"
},
"@angular-devkit/core": {
"name": "Core",
@@ -69,20 +69,20 @@
"url": "https://github.com/angular/devkit/blob/master/packages/angular_devkit/schematics/README.md"
}
],
- "version": "0.0.39",
- "hash": "ba64f250a7c6a14c83f455471d99906b"
+ "version": "0.0.40",
+ "hash": "0693678d7a0aea83c55dc808e1f1f13e"
},
"@schematics/angular": {
"name": "Angular Schematics",
"section": "Schematics",
- "version": "0.1.9",
- "hash": "c658f683345f0179e704364447617ec5"
+ "version": "0.1.10",
+ "hash": "6cd8b4e0065d6d5745104f5f8bcc4597"
},
"@schematics/schematics": {
"name": "Schematics Schematics",
- "version": "0.0.9",
+ "version": "0.0.10",
"section": "Schematics",
- "hash": "39f5fbf5bc3c8cb74922e2632d6876bb"
+ "hash": "787acac400e274f3f40ecab6909d0c8d"
}
}
}
From ac51fb39b8fd8217733c119d3587e9ed7fbf3eba Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Wed, 6 Dec 2017 15:47:30 -0800
Subject: [PATCH 052/807] feat(@angular-devkit/schematics): add strategy to
branchAndMerge
---
packages/angular_devkit/schematics/src/rules/base.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/angular_devkit/schematics/src/rules/base.ts b/packages/angular_devkit/schematics/src/rules/base.ts
index bdc3d3c442..b4dee20290 100644
--- a/packages/angular_devkit/schematics/src/rules/base.ts
+++ b/packages/angular_devkit/schematics/src/rules/base.ts
@@ -87,12 +87,12 @@ export function asSource(rule: Rule): Source {
}
-export function branchAndMerge(rule: Rule): Rule {
+export function branchAndMerge(rule: Rule, strategy = MergeStrategy.Default): Rule {
return (tree: Tree, context: SchematicContext) => {
const branchedTree = branch(tree);
return callRule(rule, Observable.of(branchedTree), context)
- .map(t => staticMerge(tree, t));
+ .map(t => staticMerge(tree, t, strategy));
};
}
From 3294334afa3556a817b045f6faefa03c848da0da Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Wed, 6 Dec 2017 15:48:11 -0800
Subject: [PATCH 053/807] fix(@angular-devkit/schematics): recursively optimize
until its stable
Seems like optimization is not working properly. TODO added to revisit but this is
an emergency fix for now.
---
packages/angular_devkit/schematics/src/tree/action.ts | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/packages/angular_devkit/schematics/src/tree/action.ts b/packages/angular_devkit/schematics/src/tree/action.ts
index 3de30cc5b4..1a0ed47421 100644
--- a/packages/angular_devkit/schematics/src/tree/action.ts
+++ b/packages/angular_devkit/schematics/src/tree/action.ts
@@ -53,6 +53,7 @@ export class ActionList implements Iterable {
optimize() {
+ let changed = false;
const actions = this._actions;
const deleted = new Set();
this._actions = [];
@@ -69,6 +70,7 @@ export class ActionList implements Iterable {
for (let j = i + 1; j < actions.length; j++) {
const action = actions[j];
if (path == action.path) {
+ changed = true;
switch (action.kind) {
case 'c': content = action.content; actions.splice(j--, 1); break;
case 'o': content = action.content; actions.splice(j--, 1); break;
@@ -96,6 +98,11 @@ export class ActionList implements Iterable {
}
}
}
+
+ // TODO: fix the optimization and remove this recursivity.
+ if (changed) {
+ this.optimize();
+ }
}
push(action: Action) { this._actions.push(action); }
From 0b9c700ccf3b9b3f2e7cdc2a662825598a8e850c Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Wed, 6 Dec 2017 15:57:39 -0800
Subject: [PATCH 054/807] release: patch
---
.monorepo.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.monorepo.json b/.monorepo.json
index 0d1a6ee044..2edcec0fb5 100644
--- a/.monorepo.json
+++ b/.monorepo.json
@@ -69,8 +69,8 @@
"url": "https://github.com/angular/devkit/blob/master/packages/angular_devkit/schematics/README.md"
}
],
- "version": "0.0.40",
- "hash": "0693678d7a0aea83c55dc808e1f1f13e"
+ "version": "0.0.41",
+ "hash": "96e71fbcb1b2dd32f452ace07b1681d3"
},
"@schematics/angular": {
"name": "Angular Schematics",
From a5f97c76a090b3916e1960c2d379f9314200060d Mon Sep 17 00:00:00 2001
From: Cyrille Tuzi
Date: Thu, 19 Oct 2017 12:17:43 +0200
Subject: [PATCH 055/807] fix(@schematics/angular): build in --prod mode by
default
According to the idea the CLI should be ready to use, if I want to work in dev, I run `npm start`, and if I want to go in production, I run `npm run build`. But currently the build is in dev mode by default, requiring the user to know he/she has to go to modify the npm script accordingly.
---
packages/schematics/angular/application/files/package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/schematics/angular/application/files/package.json b/packages/schematics/angular/application/files/package.json
index 6f4211b0e5..eaca7ef206 100644
--- a/packages/schematics/angular/application/files/package.json
+++ b/packages/schematics/angular/application/files/package.json
@@ -5,7 +5,7 @@
"scripts": {
"ng": "ng",
"start": "ng serve",
- "build": "ng build",
+ "build": "ng build --prod",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
From bce3eccffc0820619095c1dd67f658f2b6696d23 Mon Sep 17 00:00:00 2001
From: Charles Lyding <19598772+clydin@users.noreply.github.com>
Date: Sun, 26 Nov 2017 11:41:53 -0500
Subject: [PATCH 056/807] build: support building with TS 2.6
---
WORKSPACE | 11 +-
package-lock.json | 124 +++---------------
package.json | 5 +-
.../src/helpers/transform-javascript.ts | 2 +-
.../src/transforms/class-fold.ts | 7 +-
.../src/transforms/scrub-file.ts | 7 +-
packages/angular_devkit/schematics/BUILD | 2 +
.../schematics/src/rules/template.ts | 2 +-
.../schematics/src/sink/dryrun.ts | 5 +-
.../tools/file-system-engine-host-base.ts | 2 +-
.../schematics/angular/application/index.ts | 2 +-
packages/schematics/angular/class/index.ts | 2 +-
.../schematics/angular/component/index.ts | 2 +-
.../schematics/angular/directive/index.ts | 2 +-
packages/schematics/angular/enum/index.ts | 2 +-
packages/schematics/angular/guard/index.ts | 2 +-
.../schematics/angular/interface/index.ts | 2 +-
packages/schematics/angular/module/index.ts | 2 +-
packages/schematics/angular/pipe/index.ts | 2 +-
packages/schematics/angular/service/index.ts | 2 +-
20 files changed, 45 insertions(+), 142 deletions(-)
diff --git a/WORKSPACE b/WORKSPACE
index 2ed858c60a..37b9166f05 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1,13 +1,18 @@
git_repository(
name = "build_bazel_rules_nodejs",
remote = "https://github.com/bazelbuild/rules_nodejs.git",
- tag = "0.1.0",
+ tag = "0.3.1",
)
load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories")
node_repositories(package_json = ["//:package.json"])
-local_repository(
+git_repository(
name = "build_bazel_rules_typescript",
- path = "node_modules/@bazel/typescript",
+ remote = "https://github.com/bazelbuild/rules_typescript.git",
+ tag = "0.6.0",
)
+
+load("@build_bazel_rules_typescript//:defs.bzl", "ts_repositories")
+
+ts_repositories()
diff --git a/package-lock.json b/package-lock.json
index 2206879003..1f42bfb7f4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4,32 +4,6 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
- "@bazel/typescript": {
- "version": "0.0.10",
- "resolved": "https://registry.npmjs.org/@bazel/typescript/-/typescript-0.0.10.tgz",
- "integrity": "sha1-SbU1d7/VrWLGu6Ox68LggQtKYVI=",
- "dev": true,
- "requires": {
- "@types/node": "7.0.18",
- "protobufjs": "5.0.0",
- "tsickle": "0.23.6",
- "typescript": "2.3.4"
- },
- "dependencies": {
- "@types/node": {
- "version": "7.0.18",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.18.tgz",
- "integrity": "sha1-zWfyfT3Az7dG8L3V4IbExdVb4XM=",
- "dev": true
- },
- "typescript": {
- "version": "2.3.4",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.3.4.tgz",
- "integrity": "sha1-PTgyGCgjHkNPKHUUlZw3qCtin0I=",
- "dev": true
- }
- }
- },
"@ngtools/json-schema": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@ngtools/json-schema/-/json-schema-1.1.0.tgz",
@@ -220,16 +194,6 @@
"resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
"integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0="
},
- "ascli": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/ascli/-/ascli-1.0.1.tgz",
- "integrity": "sha1-vPpZdKYvGOgcq660lzKrSoj5Brw=",
- "dev": true,
- "requires": {
- "colour": "0.7.1",
- "optjs": "3.2.2"
- }
- },
"asn1": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
@@ -343,15 +307,6 @@
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
"integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8="
},
- "bytebuffer": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz",
- "integrity": "sha1-WC7qSxqHO20CCkjVjfhfC7ps/d0=",
- "dev": true,
- "requires": {
- "long": "3.2.0"
- }
- },
"camelcase": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
@@ -375,6 +330,7 @@
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
"integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
+ "optional": true,
"requires": {
"align-text": "0.1.4",
"lazy-cache": "1.0.4"
@@ -414,6 +370,7 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
"integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
+ "optional": true,
"requires": {
"center-align": "0.1.3",
"right-align": "0.1.3",
@@ -423,7 +380,8 @@
"wordwrap": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
- "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
+ "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=",
+ "optional": true
}
}
},
@@ -455,12 +413,6 @@
"resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
"integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM="
},
- "colour": {
- "version": "0.7.1",
- "resolved": "https://registry.npmjs.org/colour/-/colour-0.7.1.tgz",
- "integrity": "sha1-nLFpkX7F0SwHNtPoaFdG3xyt93g=",
- "dev": true
- },
"combined-stream": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz",
@@ -1437,7 +1389,8 @@
"lazy-cache": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
- "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4="
+ "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=",
+ "optional": true
},
"levn": {
"version": "0.3.0",
@@ -1497,12 +1450,6 @@
"lodash._reinterpolate": "3.0.0"
}
},
- "long": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/long/-/long-3.2.0.tgz",
- "integrity": "sha1-2CG3E4yhy1gcFymQ7xTbIAtcR0s=",
- "dev": true
- },
"longest": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
@@ -5207,12 +5154,6 @@
}
}
},
- "optjs": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz",
- "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=",
- "dev": true
- },
"os-homedir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
@@ -5314,33 +5255,6 @@
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
},
- "protobufjs": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-5.0.0.tgz",
- "integrity": "sha1-QiMGMjPqlqwGPKK1VANSBNtST6E=",
- "dev": true,
- "requires": {
- "ascli": "1.0.1",
- "bytebuffer": "5.0.1",
- "glob": "5.0.15",
- "yargs": "3.10.0"
- },
- "dependencies": {
- "glob": {
- "version": "5.0.15",
- "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
- "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
- "dev": true,
- "requires": {
- "inflight": "1.0.6",
- "inherits": "2.0.3",
- "minimatch": "3.0.4",
- "once": "1.4.0",
- "path-is-absolute": "1.0.1"
- }
- }
- }
- },
"protochain": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/protochain/-/protochain-1.0.5.tgz",
@@ -5478,6 +5392,7 @@
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
"integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
+ "optional": true,
"requires": {
"align-text": "0.1.4"
}
@@ -5881,18 +5796,6 @@
}
}
},
- "tsickle": {
- "version": "0.23.6",
- "resolved": "https://registry.npmjs.org/tsickle/-/tsickle-0.23.6.tgz",
- "integrity": "sha1-/O5Xpct/kqjDqeV47gooZCfc+s0=",
- "dev": true,
- "requires": {
- "minimist": "1.2.0",
- "mkdirp": "0.5.1",
- "source-map": "0.5.7",
- "source-map-support": "0.4.18"
- }
- },
"tslib": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.8.0.tgz",
@@ -5957,9 +5860,9 @@
}
},
"typescript": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.4.2.tgz",
- "integrity": "sha1-+DlfhdRZJ2BnyYiqQYN6j4KHCEQ="
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.6.1.tgz",
+ "integrity": "sha1-7znN6ierrAtQAkLWcmq5DgyEZjE="
},
"uglify-js": {
"version": "2.8.29",
@@ -6069,7 +5972,8 @@
"window-size": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
- "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0="
+ "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=",
+ "optional": true
},
"wordwrap": {
"version": "0.0.3",
@@ -6095,6 +5999,7 @@
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
"integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
+ "optional": true,
"requires": {
"camelcase": "1.2.1",
"cliui": "2.1.0",
@@ -6105,7 +6010,8 @@
"camelcase": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
- "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="
+ "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
+ "optional": true
}
}
},
diff --git a/package.json b/package.json
index 2888f4eeae..0c27d3b460 100644
--- a/package.json
+++ b/package.json
@@ -72,11 +72,8 @@
"temp": "^0.8.3",
"ts-node": "^2.0.0",
"tslint": "^5.5.0",
- "typescript": "~2.4.0",
+ "typescript": "~2.6.1",
"v8-profiler": "^5.7.0",
"webpack-sources": "^1.0.1"
- },
- "devDependencies": {
- "@bazel/typescript": "0.0.10"
}
}
diff --git a/packages/angular_devkit/build_optimizer/src/helpers/transform-javascript.ts b/packages/angular_devkit/build_optimizer/src/helpers/transform-javascript.ts
index 08e16b8709..e7adc84a5b 100644
--- a/packages/angular_devkit/build_optimizer/src/helpers/transform-javascript.ts
+++ b/packages/angular_devkit/build_optimizer/src/helpers/transform-javascript.ts
@@ -47,7 +47,7 @@ export function transformJavascript(
}
// Print error diagnostics.
- const checkDiagnostics = (diagnostics: ts.Diagnostic[]) => {
+ const checkDiagnostics = (diagnostics: ReadonlyArray) => {
if (diagnostics && diagnostics.length > 0) {
let errors = '';
errors = errors + '\n' + ts.formatDiagnostics(diagnostics, {
diff --git a/packages/angular_devkit/build_optimizer/src/transforms/class-fold.ts b/packages/angular_devkit/build_optimizer/src/transforms/class-fold.ts
index 55002df6e9..3dd0a82471 100644
--- a/packages/angular_devkit/build_optimizer/src/transforms/class-fold.ts
+++ b/packages/angular_devkit/build_optimizer/src/transforms/class-fold.ts
@@ -29,13 +29,10 @@ export function getFoldFileTransformer(program: ts.Program): ts.TransformerFacto
const classes = findClassDeclarations(sf);
const statements = findClassStaticPropertyAssignments(sf, checker, classes);
- const visitor: ts.Visitor = (node: ts.Node): ts.Node => {
+ const visitor: ts.Visitor = (node: ts.Node): ts.VisitResult => {
// Check if node is a statement to be dropped.
if (statements.find((st) => st.expressionStatement === node)) {
- // According to @mhegazy returning undefined is supported.
- // https://github.com/Microsoft/TypeScript/pull/17044
- // tslint:disable-next-line:no-any
- return undefined as any;
+ return undefined;
}
// Check if node is a class to add statements to.
diff --git a/packages/angular_devkit/build_optimizer/src/transforms/scrub-file.ts b/packages/angular_devkit/build_optimizer/src/transforms/scrub-file.ts
index 2af38ec80f..620b4815ff 100644
--- a/packages/angular_devkit/build_optimizer/src/transforms/scrub-file.ts
+++ b/packages/angular_devkit/build_optimizer/src/transforms/scrub-file.ts
@@ -85,13 +85,10 @@ export function getScrubFileTransformer(program: ts.Program): ts.TransformerFact
}
}
- const visitor: ts.Visitor = (node: ts.Node): ts.Node => {
+ const visitor: ts.Visitor = (node: ts.Node): ts.VisitResult => {
// Check if node is a statement to be dropped.
if (nodes.find((n) => n === node)) {
- // According to @mhegazy returning undefined is supported.
- // https://github.com/Microsoft/TypeScript/pull/17044
- // tslint:disable-next-line:no-any
- return undefined as any;
+ return undefined;
}
// Otherwise return node as is.
diff --git a/packages/angular_devkit/schematics/BUILD b/packages/angular_devkit/schematics/BUILD
index bda638e786..515c2dc6c7 100644
--- a/packages/angular_devkit/schematics/BUILD
+++ b/packages/angular_devkit/schematics/BUILD
@@ -63,6 +63,7 @@ ts_library(
),
deps = [
":schematics",
+ "//packages/angular_devkit/core",
# @deps: rxjs
# @typings: jasmine
],
@@ -75,6 +76,7 @@ ts_library(
include = ["tools/**/*_spec.ts"],
),
deps = [
+ ":schematics",
":tools",
# @deps: rxjs
# @typings: jasmine
diff --git a/packages/angular_devkit/schematics/src/rules/template.ts b/packages/angular_devkit/schematics/src/rules/template.ts
index d630a3b125..cd950cf513 100644
--- a/packages/angular_devkit/schematics/src/rules/template.ts
+++ b/packages/angular_devkit/schematics/src/rules/template.ts
@@ -31,7 +31,7 @@ export const kPathTemplateComponentRE = /__(.+?)__/g;
export const kPathTemplatePipeRE = /@([^@]+)/;
-export type TemplateValue = boolean | string | number;
+export type TemplateValue = boolean | string | number | undefined;
export type TemplatePipeFunction = (x: string) => TemplateValue;
export type TemplateOptions = {
[key: string]: TemplateValue | TemplateOptions | TemplatePipeFunction,
diff --git a/packages/angular_devkit/schematics/src/sink/dryrun.ts b/packages/angular_devkit/schematics/src/sink/dryrun.ts
index fb6add4998..b29c4dae6b 100644
--- a/packages/angular_devkit/schematics/src/sink/dryrun.ts
+++ b/packages/angular_devkit/schematics/src/sink/dryrun.ts
@@ -84,8 +84,7 @@ export class DryRunSink extends FileSystemSink {
}
}
- const content = null;
- this._subject.next({ kind: 'delete', path, content });
+ this._subject.next({ kind: 'delete', path });
});
this._filesToCreate.forEach((content, path) => {
// Check if this is a renaming.
@@ -106,7 +105,7 @@ export class DryRunSink extends FileSystemSink {
this._subject.next({ kind: 'update', path, content: content.generate() });
});
this._filesToRename.forEach(([path, to]) => {
- this._subject.next({ kind: 'rename', path, to, content: null });
+ this._subject.next({ kind: 'rename', path, to });
});
this._subject.complete();
diff --git a/packages/angular_devkit/schematics/tools/file-system-engine-host-base.ts b/packages/angular_devkit/schematics/tools/file-system-engine-host-base.ts
index 6ec6a9d16c..1a21a4b1e7 100644
--- a/packages/angular_devkit/schematics/tools/file-system-engine-host-base.ts
+++ b/packages/angular_devkit/schematics/tools/file-system-engine-host-base.ts
@@ -118,7 +118,7 @@ export abstract class FileSystemEngineHostBase implements
createCollectionDescription(name: string): FileSystemCollectionDesc {
const path = this._resolveCollectionPath(name);
const jsonValue = readJsonFile(path);
- if (!jsonValue || typeof jsonValue != 'object') {
+ if (!jsonValue || typeof jsonValue != 'object' || Array.isArray(jsonValue)) {
throw new InvalidCollectionJsonException(name, path);
}
diff --git a/packages/schematics/angular/application/index.ts b/packages/schematics/angular/application/index.ts
index db762a8ecf..d5108e49a1 100644
--- a/packages/schematics/angular/application/index.ts
+++ b/packages/schematics/angular/application/index.ts
@@ -98,7 +98,7 @@ export default function (options: ApplicationOptions): Rule {
options.serviceWorker ? noop() : filter(path => !path.endsWith('/ngsw-config.json')),
template({
utils: stringUtils,
- ...options as object,
+ ...options,
'dot': '.',
sourcedir: sourceDir,
}),
diff --git a/packages/schematics/angular/class/index.ts b/packages/schematics/angular/class/index.ts
index f07335365c..aa2c8296d0 100644
--- a/packages/schematics/angular/class/index.ts
+++ b/packages/schematics/angular/class/index.ts
@@ -35,7 +35,7 @@ export default function (options: ClassOptions): Rule {
options.spec ? noop() : filter(path => !path.endsWith('.spec.ts')),
template({
...stringUtils,
- ...options as object,
+ ...options,
}),
move(sourceDir),
]);
diff --git a/packages/schematics/angular/component/index.ts b/packages/schematics/angular/component/index.ts
index a67bf613cc..02e1bf7c86 100644
--- a/packages/schematics/angular/component/index.ts
+++ b/packages/schematics/angular/component/index.ts
@@ -119,7 +119,7 @@ export default function(options: ComponentOptions): Rule {
template({
...stringUtils,
'if-flat': (s: string) => options.flat ? '' : s,
- ...options as object,
+ ...options,
}),
move(sourceDir),
]);
diff --git a/packages/schematics/angular/directive/index.ts b/packages/schematics/angular/directive/index.ts
index a043661c29..8ade528a88 100644
--- a/packages/schematics/angular/directive/index.ts
+++ b/packages/schematics/angular/directive/index.ts
@@ -113,7 +113,7 @@ export default function (options: DirectiveOptions): Rule {
template({
...stringUtils,
'if-flat': (s: string) => options.flat ? '' : s,
- ...options as object,
+ ...options,
}),
move(sourceDir),
]);
diff --git a/packages/schematics/angular/enum/index.ts b/packages/schematics/angular/enum/index.ts
index 5f46c1dd41..e5cfb2b87b 100644
--- a/packages/schematics/angular/enum/index.ts
+++ b/packages/schematics/angular/enum/index.ts
@@ -31,7 +31,7 @@ export default function (options: EnumOptions): Rule {
const templateSource = apply(url('./files'), [
template({
...stringUtils,
- ...options as object,
+ ...options,
}),
move(sourceDir),
]);
diff --git a/packages/schematics/angular/guard/index.ts b/packages/schematics/angular/guard/index.ts
index cd1c3634ae..a1c76119ab 100644
--- a/packages/schematics/angular/guard/index.ts
+++ b/packages/schematics/angular/guard/index.ts
@@ -81,7 +81,7 @@ export default function (options: GuardOptions): Rule {
options.spec ? noop() : filter(path => !path.endsWith('.spec.ts')),
template({
...stringUtils,
- ...options as object,
+ ...options,
}),
move(sourceDir),
]);
diff --git a/packages/schematics/angular/interface/index.ts b/packages/schematics/angular/interface/index.ts
index c1e466d205..100d281ff4 100644
--- a/packages/schematics/angular/interface/index.ts
+++ b/packages/schematics/angular/interface/index.ts
@@ -33,7 +33,7 @@ export default function (options: InterfaceOptions): Rule {
const templateSource = apply(url('./files'), [
template({
...stringUtils,
- ...options as object,
+ ...options,
}),
move(sourceDir),
]);
diff --git a/packages/schematics/angular/module/index.ts b/packages/schematics/angular/module/index.ts
index 3dcc550df8..2a2a956887 100644
--- a/packages/schematics/angular/module/index.ts
+++ b/packages/schematics/angular/module/index.ts
@@ -87,7 +87,7 @@ export default function (options: ModuleOptions): Rule {
template({
...stringUtils,
'if-flat': (s: string) => options.flat ? '' : s,
- ...options as object,
+ ...options,
}),
move(sourceDir),
]);
diff --git a/packages/schematics/angular/pipe/index.ts b/packages/schematics/angular/pipe/index.ts
index 37af3b5b28..3b442f2534 100644
--- a/packages/schematics/angular/pipe/index.ts
+++ b/packages/schematics/angular/pipe/index.ts
@@ -100,7 +100,7 @@ export default function (options: PipeOptions): Rule {
template({
...stringUtils,
'if-flat': (s: string) => options.flat ? '' : s,
- ...options as object,
+ ...options,
}),
move(sourceDir),
]);
diff --git a/packages/schematics/angular/service/index.ts b/packages/schematics/angular/service/index.ts
index b8800f9905..cc98ea0409 100644
--- a/packages/schematics/angular/service/index.ts
+++ b/packages/schematics/angular/service/index.ts
@@ -86,7 +86,7 @@ export default function (options: ServiceOptions): Rule {
template({
...stringUtils,
'if-flat': (s: string) => options.flat ? '' : s,
- ...options as object,
+ ...options,
}),
move(sourceDir),
]);
From 07e12b953706ac54c9f213971374bf83d7ef6d44 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Mon, 11 Dec 2017 11:59:46 -0800
Subject: [PATCH 057/807] build: add appveyor CI
And fix broken tests.
---
.appveyor.yml | 21 +++++++++++++++++++
.../files/src/my-full-schematic/index_spec.ts | 4 ++--
scripts/test.ts | 9 ++++----
3 files changed, 28 insertions(+), 6 deletions(-)
create mode 100644 .appveyor.yml
diff --git a/.appveyor.yml b/.appveyor.yml
new file mode 100644
index 0000000000..6824e4b356
--- /dev/null
+++ b/.appveyor.yml
@@ -0,0 +1,21 @@
+environment:
+ matrix:
+ - nodejs_version: "6"
+
+matrix:
+ fast_finish: true
+
+install:
+ - ps: Install-Product node $env:nodejs_version
+ - npm install -g npm@~5.6.0
+ - npm install
+
+test_script:
+ - node --version
+ - npm --version
+ - npm run test
+
+build: off
+
+cache:
+ - node_modules -> package-lock.json
diff --git a/packages/schematics/schematics/schematic/files/src/my-full-schematic/index_spec.ts b/packages/schematics/schematics/schematic/files/src/my-full-schematic/index_spec.ts
index 89c4d085e8..eb84c70921 100644
--- a/packages/schematics/schematics/schematic/files/src/my-full-schematic/index_spec.ts
+++ b/packages/schematics/schematics/schematic/files/src/my-full-schematic/index_spec.ts
@@ -16,9 +16,9 @@ describe('my-full-schematic', () => {
it('works', () => {
const runner = new SchematicTestRunner('schematics', collectionPath);
- const tree = runner.runSchematic('my-full-schematic', { required: 'str' }, Tree.empty());
+ const tree = runner.runSchematic('my-full-schematic', { name: 'str' }, Tree.empty());
// Listing files
- expect(tree.files.sort()).toEqual(['/allo', '/hola']);
+ expect(tree.files.sort()).toEqual(['/allo', '/hola', '/test1', '/test2']);
});
});
diff --git a/scripts/test.ts b/scripts/test.ts
index e60c61f664..64ca18c77f 100644
--- a/scripts/test.ts
+++ b/scripts/test.ts
@@ -226,10 +226,11 @@ export default function (args: ParsedArgs, logger: logging.Logger) {
const pattern = '^('
+ (tsConfig.config.exclude as string[])
.map(ex => '('
- + ex
- .replace(/[\-\[\]{}()+?./\\^$|]/g, '\\$&')
- .replace(/(\\\\|\\\/)\*\*/g, '((\/|\\\\).+?)?')
- .replace(/\*/g, '[^/\\\\]*')
+ + ex.split(/[\/\\]/g).map(f => f
+ .replace(/[\-\[\]{}()+?.^$|]/g, '\\$&')
+ .replace(/^\*\*/g, '(.+?)?')
+ .replace(/\*/g, '[^/\\\\]*'))
+ .join('[\/\\\\]')
+ ')')
.join('|')
+ ')($|/|\\\\)';
From 3d420e6c8fcfa35b41bd8e7dc4b8ba5158102b45 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Wed, 6 Dec 2017 19:24:57 -0800
Subject: [PATCH 058/807] feat(@angular-devkit/schematics): add visit to
DirEntry
---
.../schematics/src/tree/interface.ts | 9 +++--
.../schematics/src/tree/null.ts | 2 +
.../schematics/src/tree/virtual.ts | 19 +++++++++
.../schematics/src/tree/virtual_spec.ts | 40 +++++++++++++++++++
4 files changed, 66 insertions(+), 4 deletions(-)
diff --git a/packages/angular_devkit/schematics/src/tree/interface.ts b/packages/angular_devkit/schematics/src/tree/interface.ts
index 326a9c88cb..ee20d0a546 100644
--- a/packages/angular_devkit/schematics/src/tree/interface.ts
+++ b/packages/angular_devkit/schematics/src/tree/interface.ts
@@ -31,6 +31,9 @@ export enum MergeStrategy {
}
+export const FileVisitorCancelToken = Symbol();
+export type FileVisitor = FilePredicate;
+
export interface FileEntry {
readonly path: Path;
readonly content: Buffer;
@@ -45,16 +48,14 @@ export interface DirEntry {
dir(name: PathFragment): DirEntry;
file(name: PathFragment): FileEntry | null;
+
+ visit(visitor: FileVisitor): void;
}
export interface FilePredicate {
(path: Path, entry?: Readonly | null): T;
}
-export const FileVisitorCancelToken = Symbol();
-export type FileVisitor = FilePredicate;
-
-
declare const window: { Symbol: { schematicTree: symbol }, window: {} };
declare const self: { Symbol: { schematicTree: symbol }, self: {} };
declare const global: { Symbol: { schematicTree: symbol }, global: {} };
diff --git a/packages/angular_devkit/schematics/src/tree/null.ts b/packages/angular_devkit/schematics/src/tree/null.ts
index 087d5a2162..cd0a9ba535 100644
--- a/packages/angular_devkit/schematics/src/tree/null.ts
+++ b/packages/angular_devkit/schematics/src/tree/null.ts
@@ -38,6 +38,8 @@ export class NullTreeDirEntry implements DirEntry {
return new NullTreeDirEntry(join(this.path, name));
}
file(_name: PathFragment) { return null; }
+
+ visit() {}
}
diff --git a/packages/angular_devkit/schematics/src/tree/virtual.ts b/packages/angular_devkit/schematics/src/tree/virtual.ts
index 45b79f98fa..219b2c5150 100644
--- a/packages/angular_devkit/schematics/src/tree/virtual.ts
+++ b/packages/angular_devkit/schematics/src/tree/virtual.ts
@@ -71,6 +71,25 @@ export class VirtualDirEntry implements DirEntry {
file(name: PathFragment) {
return this._tree.get(join(this._path, name));
}
+
+ visit(visitor: FileVisitor) {
+ function _recurse(entry: VirtualDirEntry) {
+ entry.subfiles.forEach(path => {
+ visitor(join(entry._path, path), entry.file(path));
+ });
+ entry.subdirs.forEach(path => {
+ _recurse(entry.dir(path) as VirtualDirEntry);
+ });
+ }
+
+ try {
+ _recurse(this);
+ } catch (e) {
+ if (e !== FileVisitorCancelToken) {
+ throw e;
+ }
+ }
+ }
}
diff --git a/packages/angular_devkit/schematics/src/tree/virtual_spec.ts b/packages/angular_devkit/schematics/src/tree/virtual_spec.ts
index d6112a81a2..fd550c2a0d 100644
--- a/packages/angular_devkit/schematics/src/tree/virtual_spec.ts
+++ b/packages/angular_devkit/schematics/src/tree/virtual_spec.ts
@@ -23,6 +23,46 @@ function files(tree: Tree) {
}
+describe('VirtualDirEntry', () => {
+ it('can visit', () => {
+ const files = {
+ '/sub1/file1': '/sub1/file1',
+ '/sub1/file2': '/sub1/file2',
+ '/sub1/file3': '/sub1/file3',
+ '/sub1/sub2/file4': '/sub1/sub2/file4',
+ '/sub1/sub2/file5': '/sub1/sub2/file5',
+ '/sub3/file6': '',
+ };
+ const host = new InMemoryFileSystemTreeHost(files);
+ const tree = new FileSystemTree(host);
+
+ let allPaths: string[] = [];
+ tree.getDir(normalize('/sub1'))
+ .visit((p, entry) => {
+ expect(entry).not.toBeNull();
+ expect(entry !.content.toString()).toEqual(p);
+ allPaths.push(p);
+ });
+
+ expect(allPaths).toEqual([
+ '/sub1/file1',
+ '/sub1/file2',
+ '/sub1/file3',
+ '/sub1/sub2/file4',
+ '/sub1/sub2/file5',
+ ]);
+
+ allPaths = [];
+ tree.getDir(normalize('/'))
+ .visit((p, _entry) => {
+ allPaths.push(p);
+ });
+
+ expect(allPaths).toEqual(Object.keys(files));
+ });
+});
+
+
describe('VirtualTree', () => {
describe('exists()', () => {
it('works', () => {
From ab8062c4f95fbb3ff27f06e64d7487502cbae31c Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Mon, 27 Nov 2017 14:33:23 -0800
Subject: [PATCH 059/807] fix(@angular-devkit/schematics): check that
rules/sources return proper value
Add a check if a rule returns an Observable, which will fail if the Observable does not
contain a Tree.
---
.../schematics/src/rules/call.ts | 33 +++-
.../schematics/src/rules/call_spec.ts | 150 ++++++++++++++++++
2 files changed, 178 insertions(+), 5 deletions(-)
create mode 100644 packages/angular_devkit/schematics/src/rules/call_spec.ts
diff --git a/packages/angular_devkit/schematics/src/rules/call.ts b/packages/angular_devkit/schematics/src/rules/call.ts
index af463bd8da..cf3a0009cb 100644
--- a/packages/angular_devkit/schematics/src/rules/call.ts
+++ b/packages/angular_devkit/schematics/src/rules/call.ts
@@ -7,6 +7,9 @@
*/
import { BaseException } from '@angular-devkit/core';
import { Observable } from 'rxjs/Observable';
+import { _throw } from 'rxjs/observable/throw';
+import { last } from 'rxjs/operators/last';
+import { tap } from 'rxjs/operators/tap';
import { Rule, SchematicContext, Source } from '../engine/interface';
import { Tree, TreeSymbol } from '../tree/interface';
@@ -58,13 +61,21 @@ export function callSource(source: Source, context: SchematicContext): Observabl
const result = source(context) as object;
if (result === undefined) {
- throw new InvalidSourceResultException(result);
+ return _throw(new InvalidSourceResultException(result));
} else if (TreeSymbol in result) {
return Observable.of(result as Tree);
} else if (Symbol.observable in result) {
- return result as Observable;
+ // Only return the last Tree, and make sure it's a Tree.
+ return (result as Observable).pipe(
+ last(),
+ tap(inner => {
+ if (!(TreeSymbol in inner)) {
+ throw new InvalidSourceResultException(inner);
+ }
+ }),
+ );
} else {
- throw new InvalidSourceResultException(result);
+ return _throw(new InvalidSourceResultException(result));
}
}
@@ -80,9 +91,21 @@ export function callRule(rule: Rule,
} else if (TreeSymbol in result) {
return Observable.of(result as Tree);
} else if (Symbol.observable in result) {
- return result as Observable;
+ const obs = result as Observable;
+
+ // Only return the last Tree, and make sure it's a Tree.
+ return obs.pipe(
+ last(),
+ tap(inner => {
+ if (!(TreeSymbol in inner)) {
+ throw new InvalidRuleResultException(inner);
+ }
+ }),
+ );
+ } else if (result === undefined) {
+ return Observable.of(inputTree);
} else {
- throw new InvalidRuleResultException(result);
+ return _throw(new InvalidRuleResultException(result));
}
});
}
diff --git a/packages/angular_devkit/schematics/src/rules/call_spec.ts b/packages/angular_devkit/schematics/src/rules/call_spec.ts
new file mode 100644
index 0000000000..08bb492afc
--- /dev/null
+++ b/packages/angular_devkit/schematics/src/rules/call_spec.ts
@@ -0,0 +1,150 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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
+ */
+// tslint:disable:non-null-operator
+// tslint:disable:no-any
+import { MergeStrategy } from '@angular-devkit/schematics';
+import { Observable } from 'rxjs/Observable';
+import 'rxjs/add/operator/toPromise';
+import { Rule, SchematicContext, Source } from '../engine/interface';
+import { Tree } from '../tree/interface';
+import { empty } from '../tree/static';
+import {
+ InvalidRuleResultException,
+ InvalidSourceResultException,
+ callRule,
+ callSource,
+} from './call';
+
+
+const context: SchematicContext = {
+ engine: null,
+ debug: false,
+ strategy: MergeStrategy.Default,
+} as {} as SchematicContext;
+
+
+describe('callSource', () => {
+ it('errors if undefined source', done => {
+ const source0: any = () => undefined;
+
+ callSource(source0, context)
+ .toPromise()
+ .then(() => done.fail(), err => {
+ expect(err.constructor).toBe(InvalidSourceResultException);
+ })
+ .then(done, done.fail);
+ });
+
+ it('errors if invalid source object', done => {
+ const source0: Source = () => ({} as Tree);
+
+ callSource(source0, context)
+ .toPromise()
+ .then(() => done.fail(), err => {
+ expect(err.constructor).toBe(InvalidSourceResultException);
+ })
+ .then(done, done.fail);
+ });
+
+ it('errors if Observable of invalid source object', done => {
+ const source0: Source = () => Observable.of({} as Tree);
+
+ callSource(source0, context)
+ .toPromise()
+ .then(() => done.fail(), err => {
+ expect(err.constructor).toBe(InvalidSourceResultException);
+ })
+ .then(done, done.fail);
+ });
+
+ it('works with a Tree', done => {
+ const tree0 = empty();
+ const source0: Source = () => tree0;
+
+ callSource(source0, context)
+ .toPromise()
+ .then(tree => {
+ expect(tree).toBe(tree0);
+ })
+ .then(done, done.fail);
+ });
+
+ it('works with an Observable', done => {
+ const tree0 = empty();
+ const source0: Source = () => Observable.of(tree0);
+
+ callSource(source0, context)
+ .toPromise()
+ .then(tree => {
+ expect(tree).toBe(tree0);
+ })
+ .then(done, done.fail);
+ });
+});
+
+describe('callRule', () => {
+ it('errors if invalid source object', done => {
+ const tree0 = Observable.of(empty());
+ const rule0: Rule = () => ({} as Tree);
+
+ callRule(rule0, tree0, context)
+ .toPromise()
+ .then(() => done.fail(), err => {
+ expect(err.constructor).toBe(InvalidRuleResultException);
+ })
+ .then(done, done.fail);
+ });
+
+ it('errors if Observable of invalid source object', done => {
+ const tree0 = Observable.of(empty());
+ const rule0: Rule = () => Observable.of({} as Tree);
+
+ callRule(rule0, tree0, context)
+ .toPromise()
+ .then(() => done.fail(), err => {
+ expect(err.constructor).toBe(InvalidRuleResultException);
+ })
+ .then(done, done.fail);
+ });
+
+ it('works with undefined result', done => {
+ const tree0 = empty();
+ const rule0: Rule = () => undefined;
+
+ callRule(rule0, Observable.of(tree0), context)
+ .toPromise()
+ .then(tree => {
+ expect(tree).toBe(tree0);
+ })
+ .then(done, done.fail);
+ });
+
+ it('works with a Tree', done => {
+ const tree0 = empty();
+ const rule0: Rule = () => tree0;
+
+ callRule(rule0, Observable.of(tree0), context)
+ .toPromise()
+ .then(tree => {
+ expect(tree).toBe(tree0);
+ })
+ .then(done, done.fail);
+ });
+
+ it('works with an Observable', done => {
+ const tree0 = empty();
+ const rule0: Rule = () => Observable.of(tree0);
+
+ callRule(rule0, Observable.of(tree0), context)
+ .toPromise()
+ .then(tree => {
+ expect(tree).toBe(tree0);
+ })
+ .then(done, done.fail);
+ });
+});
From 851b74054a14dc8a9af0a35d48e62ed11c312a55 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Tue, 5 Dec 2017 22:13:32 -0800
Subject: [PATCH 060/807] feat(@angular-devkit/core): add a virtual FS
interface
Along with a simple memory implementation, and a scoped + sync host
adapters.
---
.../core/src/exception/exception.ts | 10 +
.../core/src/virtual-fs/host/buffer.ts | 25 +++
.../core/src/virtual-fs/host/index.ts | 13 ++
.../core/src/virtual-fs/host/interface.ts | 68 ++++++
.../core/src/virtual-fs/host/memory.ts | 205 ++++++++++++++++++
.../core/src/virtual-fs/host/memory_spec.ts | 112 ++++++++++
.../core/src/virtual-fs/host/scoped.ts | 60 +++++
.../core/src/virtual-fs/host/sync.ts | 104 +++++++++
.../core/src/virtual-fs/index.ts | 3 +
9 files changed, 600 insertions(+)
create mode 100644 packages/angular_devkit/core/src/virtual-fs/host/buffer.ts
create mode 100644 packages/angular_devkit/core/src/virtual-fs/host/index.ts
create mode 100644 packages/angular_devkit/core/src/virtual-fs/host/interface.ts
create mode 100644 packages/angular_devkit/core/src/virtual-fs/host/memory.ts
create mode 100644 packages/angular_devkit/core/src/virtual-fs/host/memory_spec.ts
create mode 100644 packages/angular_devkit/core/src/virtual-fs/host/scoped.ts
create mode 100644 packages/angular_devkit/core/src/virtual-fs/host/sync.ts
diff --git a/packages/angular_devkit/core/src/exception/exception.ts b/packages/angular_devkit/core/src/exception/exception.ts
index cc82a6b71a..3ccea7a8a8 100644
--- a/packages/angular_devkit/core/src/exception/exception.ts
+++ b/packages/angular_devkit/core/src/exception/exception.ts
@@ -20,6 +20,12 @@ export class FileDoesNotExistException extends BaseException {
export class FileAlreadyExistException extends BaseException {
constructor(path: string) { super(`Path "${path}" already exist.`); }
}
+export class PathIsDirectoryException extends BaseException {
+ constructor(path: string) { super(`Path "${path}" is a directory.`); }
+}
+export class PathIsFileException extends BaseException {
+ constructor(path: string) { super(`Path "${path}" is a file.`); }
+}
export class ContentHasMutatedException extends BaseException {
constructor(path: string) {
super(`Content at path "${path}" has changed between the start and the end of an update.`);
@@ -37,3 +43,7 @@ export class MergeConflictException extends BaseException {
export class UnimplementedException extends BaseException {
constructor() { super('This function is unimplemented.'); }
}
+
+export class UnsupportedPlatformException extends BaseException {
+ constructor() { super('This platform is not supported by this code path.'); }
+}
diff --git a/packages/angular_devkit/core/src/virtual-fs/host/buffer.ts b/packages/angular_devkit/core/src/virtual-fs/host/buffer.ts
new file mode 100644
index 0000000000..3ab53b633d
--- /dev/null
+++ b/packages/angular_devkit/core/src/virtual-fs/host/buffer.ts
@@ -0,0 +1,25 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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 { UnsupportedPlatformException } from '../../exception/exception';
+import { FileBuffer } from './interface';
+
+export function stringToFileBuffer(str: string): FileBuffer {
+ // If we're in Node...
+ if (typeof Buffer !== 'undefined' && typeof Buffer.from === 'function') {
+ const buf = Buffer.from(str);
+ const ab = new ArrayBuffer(buf.length);
+ const view = new Uint8Array(ab);
+ for (let i = 0; i < buf.length; ++i) {
+ view[i] = buf[i];
+ }
+
+ return ab;
+ }
+
+ throw new UnsupportedPlatformException();
+}
diff --git a/packages/angular_devkit/core/src/virtual-fs/host/index.ts b/packages/angular_devkit/core/src/virtual-fs/host/index.ts
new file mode 100644
index 0000000000..91a9aae22a
--- /dev/null
+++ b/packages/angular_devkit/core/src/virtual-fs/host/index.ts
@@ -0,0 +1,13 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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
+ */
+
+export * from './buffer';
+export * from './interface';
+export * from './memory';
+export * from './scoped';
+export * from './sync';
diff --git a/packages/angular_devkit/core/src/virtual-fs/host/interface.ts b/packages/angular_devkit/core/src/virtual-fs/host/interface.ts
new file mode 100644
index 0000000000..9d9d5372b9
--- /dev/null
+++ b/packages/angular_devkit/core/src/virtual-fs/host/interface.ts
@@ -0,0 +1,68 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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 { Observable } from 'rxjs/Observable';
+import { Path, PathFragment } from '../path';
+
+
+export declare type FileBuffer = ArrayBuffer;
+
+export interface HostWatchOptions {
+ readonly persistent?: boolean;
+ readonly recursive?: boolean;
+}
+
+
+export const enum HostWatchEventType {
+ Changed = 0,
+ Created = 1,
+ Deleted = 2,
+ Renamed = 3, // Applied to the original file path.
+}
+
+export type Stats = T & {
+ isFile(): boolean;
+ isDirectory(): boolean;
+
+ readonly size: number;
+
+ readonly atime: Date;
+ readonly mtime: Date;
+ readonly ctime: Date;
+ readonly birthtime: Date;
+};
+
+export interface HostWatchEvent {
+ readonly time: Date;
+ readonly type: HostWatchEventType;
+ readonly path: Path;
+}
+
+export interface HostCapabilities {
+ synchronous: boolean;
+}
+
+export interface Host {
+ readonly capabilities: HostCapabilities;
+
+ write(path: Path, content: FileBuffer): Observable;
+ read(path: Path): Observable;
+ delete(path: Path): Observable;
+ rename(from: Path, to: Path): Observable;
+
+ list(path: Path): Observable;
+
+ exists(path: Path): Observable;
+ isDirectory(path: Path): Observable;
+ isFile(path: Path): Observable;
+
+ // Some hosts may not support stats.
+ stats(path: Path): Observable> | null;
+
+ // Some hosts may not support watching.
+ watch(path: Path, options?: HostWatchOptions): Observable | null;
+}
diff --git a/packages/angular_devkit/core/src/virtual-fs/host/memory.ts b/packages/angular_devkit/core/src/virtual-fs/host/memory.ts
new file mode 100644
index 0000000000..9cf502a883
--- /dev/null
+++ b/packages/angular_devkit/core/src/virtual-fs/host/memory.ts
@@ -0,0 +1,205 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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 { Observable } from 'rxjs/Observable';
+import { Subject } from 'rxjs/Subject';
+import { ArrayObservable } from 'rxjs/observable/ArrayObservable';
+import { _throw } from 'rxjs/observable/throw';
+import {
+ FileAlreadyExistException,
+ FileDoesNotExistException,
+ PathIsDirectoryException,
+ PathIsFileException,
+} from '../../exception/exception';
+import {
+ NormalizedSep,
+ Path,
+ PathFragment,
+ dirname,
+ join,
+ split,
+} from '../path';
+import {
+ FileBuffer,
+ Host,
+ HostCapabilities,
+ HostWatchEvent,
+ HostWatchEventType,
+ HostWatchOptions,
+ Stats,
+} from './interface';
+
+
+export class SimpleMemoryHost implements Host<{}> {
+ private _cache = new Map();
+ private _watchers = new Map][]>();
+
+ protected _isDir(path: Path) {
+ for (const p of this._cache.keys()) {
+ if (p.startsWith(path + NormalizedSep)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected _updateWatchers(path: Path, type: HostWatchEventType) {
+ const time = new Date();
+ let currentPath = path;
+ let parent: Path | null = null;
+
+ if (this._watchers.size == 0) {
+ // Nothing to do if there's no watchers.
+ return;
+ }
+
+ const maybeWatcher = this._watchers.get(currentPath);
+ if (maybeWatcher) {
+ maybeWatcher.forEach(watcher => {
+ const [options, subject] = watcher;
+ subject.next({ path, time, type });
+
+ if (!options.persistent && type == HostWatchEventType.Deleted) {
+ subject.complete();
+ this._watchers.delete(currentPath);
+ }
+ });
+ }
+
+ do {
+ currentPath = parent !== null ? parent : currentPath;
+ parent = dirname(currentPath);
+
+ const maybeWatcher = this._watchers.get(currentPath);
+ if (maybeWatcher) {
+ maybeWatcher.forEach(watcher => {
+ const [options, subject] = watcher;
+ if (!options.recursive) {
+ return;
+ }
+ subject.next({ path, time, type });
+
+ if (!options.persistent && type == HostWatchEventType.Deleted) {
+ subject.complete();
+ this._watchers.delete(currentPath);
+ }
+ });
+ }
+ } while (parent != currentPath);
+ }
+
+ get capabilities(): HostCapabilities {
+ return { synchronous: true };
+ }
+
+ write(path: Path, content: FileBuffer): Observable {
+ if (this._isDir(path)) {
+ return _throw(new PathIsDirectoryException(path));
+ }
+
+ const existed = this._cache.has(path);
+ this._cache.set(path, content);
+ this._updateWatchers(path, existed ? HostWatchEventType.Changed : HostWatchEventType.Created);
+
+ return Observable.empty();
+ }
+ read(path: Path): Observable {
+ if (this._isDir(path)) {
+ return _throw(new PathIsDirectoryException(path));
+ }
+ const maybeBuffer = this._cache.get(path);
+ if (!maybeBuffer) {
+ return _throw(new FileDoesNotExistException(path));
+ } else {
+ return ArrayObservable.of(maybeBuffer);
+ }
+ }
+ delete(path: Path): Observable {
+ if (this._isDir(path)) {
+ for (const [cachePath, _] of this._cache.entries()) {
+ if (path.startsWith(cachePath + NormalizedSep)) {
+ this._cache.delete(cachePath);
+ }
+ }
+ } else {
+ this._cache.delete(path);
+ }
+ this._updateWatchers(path, HostWatchEventType.Deleted);
+
+ return Observable.empty();
+ }
+ rename(from: Path, to: Path): Observable {
+ if (!this._cache.has(from)) {
+ return _throw(new FileDoesNotExistException(from));
+ } else if (this._cache.has(to)) {
+ return _throw(new FileAlreadyExistException(from));
+ }
+ if (this._isDir(from)) {
+ for (const path of this._cache.keys()) {
+ if (path.startsWith(from + NormalizedSep)) {
+ const content = this._cache.get(path);
+ if (content) {
+ this._cache.set(join(to, NormalizedSep, path.slice(from.length)), content);
+ }
+ }
+ }
+ } else {
+ const content = this._cache.get(from);
+ if (content) {
+ this._cache.delete(from);
+ this._cache.set(to, content);
+ }
+ }
+
+ this._updateWatchers(from, HostWatchEventType.Renamed);
+
+ return Observable.empty();
+ }
+
+ list(path: Path): Observable {
+ if (this._cache.has(path)) {
+ return _throw(new PathIsFileException(path));
+ }
+ const fragments = split(path);
+ const result = new Set();
+ for (const p of this._cache.keys()) {
+ if (p.startsWith(path + NormalizedSep)) {
+ result.add(split(p)[fragments.length]);
+ }
+ }
+
+ return ArrayObservable.of([...result]);
+ }
+
+ exists(path: Path): Observable {
+ return ArrayObservable.of(this._cache.has(path) || this._isDir(path));
+ }
+ isDirectory(path: Path): Observable {
+ return ArrayObservable.of(this._isDir(path));
+ }
+ isFile(path: Path): Observable {
+ return ArrayObservable.of(this._cache.has(path));
+ }
+
+ stats(_path: Path): Observable> | null {
+ return null;
+ }
+
+ watch(path: Path, options?: HostWatchOptions): Observable | null {
+ const subject = new Subject();
+ let maybeWatcherArray = this._watchers.get(path);
+ if (!maybeWatcherArray) {
+ maybeWatcherArray = [];
+ this._watchers.set(path, maybeWatcherArray);
+ }
+
+ maybeWatcherArray.push([options || {}, subject]);
+
+ return subject.asObservable();
+ }
+}
diff --git a/packages/angular_devkit/core/src/virtual-fs/host/memory_spec.ts b/packages/angular_devkit/core/src/virtual-fs/host/memory_spec.ts
new file mode 100644
index 0000000000..566a231200
--- /dev/null
+++ b/packages/angular_devkit/core/src/virtual-fs/host/memory_spec.ts
@@ -0,0 +1,112 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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
+ */
+// tslint:disable:non-null-operator
+import { fragment, normalize } from '@angular-devkit/core';
+import { stringToFileBuffer } from './buffer';
+import { SimpleMemoryHost } from './memory';
+import { SyncDelegateHost } from './sync';
+
+describe('SimpleMemoryHost', () => {
+
+ it('can watch', () => {
+ const host = new SyncDelegateHost(new SimpleMemoryHost());
+
+ host.write(normalize('/sub/file1'), stringToFileBuffer(''));
+
+ let recursiveCalled = 0;
+ let noRecursiveCalled = 0;
+ let noRecursiveFileCalled = 0;
+ let diffFile = 0;
+
+ host.watch(normalize('/sub'), { recursive: true }) !.subscribe(() => recursiveCalled++);
+ host.watch(normalize('/sub')) !.subscribe(() => noRecursiveCalled++);
+ host.watch(normalize('/sub/file2')) !.subscribe(() => noRecursiveFileCalled++);
+ host.watch(normalize('/sub/file3')) !.subscribe(() => diffFile++);
+
+ host.write(normalize('/sub/file2'), stringToFileBuffer(''));
+
+ expect(recursiveCalled).toBe(1);
+ expect(noRecursiveCalled).toBe(0);
+ expect(noRecursiveFileCalled).toBe(1);
+ expect(diffFile).toBe(0);
+
+ host.write(normalize('/sub/file3'), stringToFileBuffer(''));
+
+ expect(recursiveCalled).toBe(2);
+ expect(noRecursiveCalled).toBe(0);
+ expect(noRecursiveFileCalled).toBe(1);
+ expect(diffFile).toBe(1);
+ });
+
+ it('can read', () => {
+ const host = new SyncDelegateHost(new SimpleMemoryHost());
+
+ const buffer = stringToFileBuffer('hello');
+
+ host.write(normalize('/hello'), buffer);
+ expect(host.read(normalize('/hello'))).toBe(buffer);
+ });
+
+ it('can delete', () => {
+ const host = new SyncDelegateHost(new SimpleMemoryHost());
+
+ const buffer = stringToFileBuffer('hello');
+
+ expect(host.exists(normalize('/sub/file1'))).toBe(false);
+ host.write(normalize('/sub/file1'), buffer);
+ expect(host.exists(normalize('/sub/file1'))).toBe(true);
+ host.delete(normalize('/sub/file1'));
+ expect(host.exists(normalize('/sub/file1'))).toBe(false);
+ });
+
+ it('can rename', () => {
+ const host = new SyncDelegateHost(new SimpleMemoryHost());
+
+ const buffer = stringToFileBuffer('hello');
+
+ expect(host.exists(normalize('/sub/file1'))).toBe(false);
+ host.write(normalize('/sub/file1'), buffer);
+ expect(host.exists(normalize('/sub/file1'))).toBe(true);
+ host.rename(normalize('/sub/file1'), normalize('/sub/file2'));
+ expect(host.exists(normalize('/sub/file1'))).toBe(false);
+ expect(host.exists(normalize('/sub/file2'))).toBe(true);
+ expect(host.read(normalize('/sub/file2'))).toBe(buffer);
+ });
+
+ it('can list', () => {
+ const host = new SyncDelegateHost(new SimpleMemoryHost());
+
+ const buffer = stringToFileBuffer('hello');
+
+ host.write(normalize('/sub/file1'), buffer);
+ host.write(normalize('/sub/file2'), buffer);
+ host.write(normalize('/sub/sub1/file3'), buffer);
+ host.write(normalize('/file4'), buffer);
+
+ expect(host.list(normalize('/sub')))
+ .toEqual([fragment('file1'), fragment('file2'), fragment('sub1')]);
+ });
+
+ it('supports isFile / isDirectory', () => {
+ const host = new SyncDelegateHost(new SimpleMemoryHost());
+
+ const buffer = stringToFileBuffer('hello');
+
+ host.write(normalize('/sub/file1'), buffer);
+ host.write(normalize('/sub/file2'), buffer);
+ host.write(normalize('/sub/sub1/file3'), buffer);
+ host.write(normalize('/file4'), buffer);
+
+ expect(host.isFile(normalize('/sub'))).toBe(false);
+ expect(host.isFile(normalize('/sub1'))).toBe(false);
+ expect(host.isDirectory(normalize('/sub'))).toBe(true);
+ expect(host.isDirectory(normalize('/sub/sub1'))).toBe(true);
+ expect(host.isDirectory(normalize('/sub/file1'))).toBe(false);
+ expect(host.isDirectory(normalize('/sub/sub1/file3'))).toBe(false);
+ });
+});
diff --git a/packages/angular_devkit/core/src/virtual-fs/host/scoped.ts b/packages/angular_devkit/core/src/virtual-fs/host/scoped.ts
new file mode 100644
index 0000000000..94c84503c6
--- /dev/null
+++ b/packages/angular_devkit/core/src/virtual-fs/host/scoped.ts
@@ -0,0 +1,60 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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 { Observable } from 'rxjs/Observable';
+import { NormalizedRoot, Path, PathFragment, join } from '../path';
+import {
+ FileBuffer,
+ Host,
+ HostCapabilities,
+ HostWatchEvent,
+ HostWatchOptions,
+ Stats,
+} from './interface';
+
+export class ScopedHost implements Host {
+ constructor(protected _delegate: Host, protected _root: Path = NormalizedRoot) {}
+
+ get capabilities(): HostCapabilities { return this._delegate.capabilities; }
+
+ write(path: Path, content: FileBuffer): Observable {
+ return this._delegate.write(join(this._root, path), content);
+ }
+ read(path: Path): Observable {
+ return this._delegate.read(join(this._root, path));
+ }
+ delete(path: Path): Observable {
+ return this._delegate.delete(join(this._root, path));
+ }
+ rename(from: Path, to: Path): Observable {
+ return this._delegate.rename(join(this._root, from), join(this._root, to));
+ }
+
+ list(path: Path): Observable {
+ return this._delegate.list(join(this._root, path));
+ }
+
+ exists(path: Path): Observable {
+ return this._delegate.exists(join(this._root, path));
+ }
+ isDirectory(path: Path): Observable {
+ return this._delegate.isDirectory(join(this._root, path));
+ }
+ isFile(path: Path): Observable {
+ return this._delegate.isFile(join(this._root, path));
+ }
+
+ // Some hosts may not support stats.
+ stats(path: Path): Observable> | null {
+ return this._delegate.stats(join(this._root, path));
+ }
+
+ // Some hosts may not support watching.
+ watch(path: Path, options?: HostWatchOptions): Observable | null {
+ return this._delegate.watch(join(this._root, path), options);
+ }
+}
diff --git a/packages/angular_devkit/core/src/virtual-fs/host/sync.ts b/packages/angular_devkit/core/src/virtual-fs/host/sync.ts
new file mode 100644
index 0000000000..03cb66e7a9
--- /dev/null
+++ b/packages/angular_devkit/core/src/virtual-fs/host/sync.ts
@@ -0,0 +1,104 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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 { Observable } from 'rxjs/Observable';
+import { BaseException } from '../../exception/exception';
+import { Path, PathFragment } from '../path';
+import {
+ FileBuffer,
+ Host,
+ HostCapabilities,
+ HostWatchEvent,
+ HostWatchOptions,
+ Stats,
+} from './interface';
+
+
+export class SynchronousDelegateExpectedException extends BaseException {
+ constructor() { super(`Expected a synchronous delegate but got an asynchronous one.`); }
+}
+
+/**
+ * Implement a synchronous-only host interface (remove the Observable parts).
+ */
+export class SyncDelegateHost {
+ constructor(protected _delegate: Host) {
+ if (!_delegate.capabilities.synchronous) {
+ throw new SynchronousDelegateExpectedException();
+ }
+ }
+
+ protected _doSyncCall(observable: Observable): ResultT {
+ let completed = false;
+ let result: ResultT | undefined = undefined;
+ let errorResult: Error | undefined = undefined;
+ observable.subscribe({
+ next(x: ResultT) { result = x; },
+ error(err: Error) { errorResult = err; },
+ complete() { completed = true; },
+ });
+
+ if (errorResult !== undefined) {
+ throw errorResult;
+ }
+ if (!completed) {
+ throw new SynchronousDelegateExpectedException();
+ }
+
+ // The non-null operation is to work around `void` type. We don't allow to return undefined
+ // but ResultT could be void, which is undefined in JavaScript, so this doesn't change the
+ // behaviour.
+ // tslint:disable-next-line:non-null-operator
+ return result !;
+ }
+
+ get capabilities(): HostCapabilities {
+ return this._delegate.capabilities;
+ }
+
+ write(path: Path, content: FileBuffer): void {
+ return this._doSyncCall(this._delegate.write(path, content));
+ }
+ read(path: Path): FileBuffer {
+ return this._doSyncCall(this._delegate.read(path));
+ }
+ delete(path: Path): void {
+ return this._doSyncCall(this._delegate.delete(path));
+ }
+ rename(from: Path, to: Path): void {
+ return this._doSyncCall(this._delegate.rename(from, to));
+ }
+
+ list(path: Path): PathFragment[] {
+ return this._doSyncCall(this._delegate.list(path));
+ }
+
+ exists(path: Path): boolean {
+ return this._doSyncCall(this._delegate.exists(path));
+ }
+ isDirectory(path: Path): boolean {
+ return this._doSyncCall(this._delegate.isDirectory(path));
+ }
+ isFile(path: Path): boolean {
+ return this._doSyncCall(this._delegate.isFile(path));
+ }
+
+ // Some hosts may not support stats.
+ stats(path: Path): Stats | null {
+ const result: Observable> | null = this._delegate.stats(path);
+
+ if (result) {
+ return this._doSyncCall(result);
+ } else {
+ return null;
+ }
+ }
+
+ watch(path: Path, options?: HostWatchOptions): Observable | null {
+ return this._delegate.watch(path, options);
+ }
+}
diff --git a/packages/angular_devkit/core/src/virtual-fs/index.ts b/packages/angular_devkit/core/src/virtual-fs/index.ts
index dc88e8ba13..ab9ccf25fc 100644
--- a/packages/angular_devkit/core/src/virtual-fs/index.ts
+++ b/packages/angular_devkit/core/src/virtual-fs/index.ts
@@ -6,3 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/
export * from './path';
+
+import * as virtualFs from './host';
+export { virtualFs };
From 1a870ba16a6bb0bb4e643b97dffd9d6237b44e18 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Thu, 7 Dec 2017 17:19:11 -0800
Subject: [PATCH 061/807] feat(@angular-devkit/core): add a NodeJsAsyncHost and
its Sync version
---
package-lock.json | 1306 +++++++++++++++--
package.json | 1 +
packages/angular_devkit/core/BUILD | 1 +
packages/angular_devkit/core/node/host.ts | 345 +++++
.../angular_devkit/core/node/host_spec.ts | 60 +
packages/angular_devkit/core/node/index.ts | 1 +
packages/angular_devkit/core/package.json | 1 +
.../core/src/virtual-fs/host/buffer.ts | 21 +-
.../core/src/virtual-fs/path.ts | 22 +
9 files changed, 1658 insertions(+), 100 deletions(-)
create mode 100644 packages/angular_devkit/core/node/host.ts
create mode 100644 packages/angular_devkit/core/node/host_spec.ts
diff --git a/package-lock.json b/package-lock.json
index 1f42bfb7f4..cba074b857 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -142,6 +142,15 @@
"color-convert": "1.9.0"
}
},
+ "anymatch": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
+ "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==",
+ "requires": {
+ "micromatch": "2.3.11",
+ "normalize-path": "2.1.1"
+ }
+ },
"aproba": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
@@ -164,6 +173,19 @@
"sprintf-js": "1.0.3"
}
},
+ "arr-diff": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+ "requires": {
+ "arr-flatten": "1.1.0"
+ }
+ },
+ "arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg=="
+ },
"array-filter": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz",
@@ -189,6 +211,11 @@
"resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz",
"integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys="
},
+ "array-unique": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM="
+ },
"arrify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
@@ -209,6 +236,11 @@
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
"integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo="
},
+ "async-each": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
+ "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0="
+ },
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -277,6 +309,11 @@
"resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
"integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q=="
},
+ "binary-extensions": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz",
+ "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU="
+ },
"block-stream": {
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
@@ -302,6 +339,16 @@
"concat-map": "0.0.1"
}
},
+ "braces": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+ "requires": {
+ "expand-range": "1.8.2",
+ "preserve": "0.2.0",
+ "repeat-element": "1.1.2"
+ }
+ },
"builtin-modules": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
@@ -361,6 +408,22 @@
}
}
},
+ "chokidar": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
+ "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
+ "requires": {
+ "anymatch": "1.3.2",
+ "async-each": "1.0.1",
+ "fsevents": "1.1.3",
+ "glob-parent": "2.0.0",
+ "inherits": "2.0.3",
+ "is-binary-path": "1.0.1",
+ "is-glob": "2.0.1",
+ "path-is-absolute": "1.0.1",
+ "readdirp": "2.1.0"
+ }
+ },
"chownr": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz",
@@ -786,109 +849,952 @@
"integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=",
"optional": true,
"requires": {
- "amdefine": "1.0.1"
+ "amdefine": "1.0.1"
+ }
+ }
+ }
+ },
+ "esprima": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+ "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE="
+ },
+ "estraverse": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz",
+ "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q="
+ },
+ "esutils": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
+ },
+ "event-stream": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
+ "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=",
+ "requires": {
+ "duplexer": "0.1.1",
+ "from": "0.1.7",
+ "map-stream": "0.1.0",
+ "pause-stream": "0.0.11",
+ "split": "0.3.3",
+ "stream-combiner": "0.0.4",
+ "through": "2.3.8"
+ },
+ "dependencies": {
+ "split": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz",
+ "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=",
+ "requires": {
+ "through": "2.3.8"
+ }
+ }
+ }
+ },
+ "exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw="
+ },
+ "expand-brackets": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+ "requires": {
+ "is-posix-bracket": "0.1.1"
+ }
+ },
+ "expand-range": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
+ "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
+ "requires": {
+ "fill-range": "2.2.3"
+ }
+ },
+ "extend": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
+ "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ="
+ },
+ "extglob": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+ "requires": {
+ "is-extglob": "1.0.0"
+ }
+ },
+ "extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
+ },
+ "filename-regex": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
+ "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY="
+ },
+ "fill-range": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
+ "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=",
+ "requires": {
+ "is-number": "2.1.0",
+ "isobject": "2.1.0",
+ "randomatic": "1.1.7",
+ "repeat-element": "1.1.2",
+ "repeat-string": "1.6.1"
+ }
+ },
+ "find-up": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+ "requires": {
+ "path-exists": "2.1.0",
+ "pinkie-promise": "2.0.1"
+ }
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA="
+ },
+ "for-own": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
+ "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
+ "requires": {
+ "for-in": "1.0.2"
+ }
+ },
+ "foreach": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
+ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k="
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
+ },
+ "form-data": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
+ "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
+ "requires": {
+ "asynckit": "0.4.0",
+ "combined-stream": "1.0.5",
+ "mime-types": "2.1.17"
+ }
+ },
+ "from": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
+ "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4="
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "fsevents": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz",
+ "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==",
+ "optional": true,
+ "requires": {
+ "nan": "2.7.0",
+ "node-pre-gyp": "0.6.39"
+ },
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.0",
+ "bundled": true,
+ "optional": true
+ },
+ "ajv": {
+ "version": "4.11.8",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "co": "4.6.0",
+ "json-stable-stringify": "1.0.1"
+ }
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "bundled": true
+ },
+ "aproba": {
+ "version": "1.1.1",
+ "bundled": true,
+ "optional": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.4",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "delegates": "1.0.0",
+ "readable-stream": "2.2.9"
+ }
+ },
+ "asn1": {
+ "version": "0.2.3",
+ "bundled": true,
+ "optional": true
+ },
+ "assert-plus": {
+ "version": "0.2.0",
+ "bundled": true,
+ "optional": true
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "bundled": true,
+ "optional": true
+ },
+ "aws-sign2": {
+ "version": "0.6.0",
+ "bundled": true,
+ "optional": true
+ },
+ "aws4": {
+ "version": "1.6.0",
+ "bundled": true,
+ "optional": true
+ },
+ "balanced-match": {
+ "version": "0.4.2",
+ "bundled": true
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "tweetnacl": "0.14.5"
+ }
+ },
+ "block-stream": {
+ "version": "0.0.9",
+ "bundled": true,
+ "requires": {
+ "inherits": "2.0.3"
+ }
+ },
+ "boom": {
+ "version": "2.10.1",
+ "bundled": true,
+ "requires": {
+ "hoek": "2.16.3"
+ }
+ },
+ "brace-expansion": {
+ "version": "1.1.7",
+ "bundled": true,
+ "requires": {
+ "balanced-match": "0.4.2",
+ "concat-map": "0.0.1"
+ }
+ },
+ "buffer-shims": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "bundled": true,
+ "optional": true
+ },
+ "co": {
+ "version": "4.6.0",
+ "bundled": true,
+ "optional": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true
+ },
+ "combined-stream": {
+ "version": "1.0.5",
+ "bundled": true,
+ "requires": {
+ "delayed-stream": "1.0.0"
+ }
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "bundled": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "cryptiles": {
+ "version": "2.0.5",
+ "bundled": true,
+ "requires": {
+ "boom": "2.10.1"
+ }
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "assert-plus": "1.0.0"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ }
+ }
+ },
+ "debug": {
+ "version": "2.6.8",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "deep-extend": {
+ "version": "0.4.2",
+ "bundled": true,
+ "optional": true
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "detect-libc": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "ecc-jsbn": {
+ "version": "0.1.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "jsbn": "0.1.1"
+ }
+ },
+ "extend": {
+ "version": "3.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "extsprintf": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "bundled": true,
+ "optional": true
+ },
+ "form-data": {
+ "version": "2.1.4",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "asynckit": "0.4.0",
+ "combined-stream": "1.0.5",
+ "mime-types": "2.1.15"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "fstream": {
+ "version": "1.0.11",
+ "bundled": true,
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "inherits": "2.0.3",
+ "mkdirp": "0.5.1",
+ "rimraf": "2.6.1"
+ }
+ },
+ "fstream-ignore": {
+ "version": "1.0.5",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "fstream": "1.0.11",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4"
+ }
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "aproba": "1.1.1",
+ "console-control-strings": "1.1.0",
+ "has-unicode": "2.0.1",
+ "object-assign": "4.1.1",
+ "signal-exit": "3.0.2",
+ "string-width": "1.0.2",
+ "strip-ansi": "3.0.1",
+ "wide-align": "1.1.2"
+ }
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "assert-plus": "1.0.0"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ }
+ }
+ },
+ "glob": {
+ "version": "7.1.2",
+ "bundled": true,
+ "requires": {
+ "fs.realpath": "1.0.0",
+ "inflight": "1.0.6",
+ "inherits": "2.0.3",
+ "minimatch": "3.0.4",
+ "once": "1.4.0",
+ "path-is-absolute": "1.0.1"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.1.11",
+ "bundled": true
+ },
+ "har-schema": {
+ "version": "1.0.5",
+ "bundled": true,
+ "optional": true
+ },
+ "har-validator": {
+ "version": "4.2.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "ajv": "4.11.8",
+ "har-schema": "1.0.5"
+ }
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "hawk": {
+ "version": "3.1.3",
+ "bundled": true,
+ "requires": {
+ "boom": "2.10.1",
+ "cryptiles": "2.0.5",
+ "hoek": "2.16.3",
+ "sntp": "1.0.9"
+ }
+ },
+ "hoek": {
+ "version": "2.16.3",
+ "bundled": true
+ },
+ "http-signature": {
+ "version": "1.1.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "assert-plus": "0.2.0",
+ "jsprim": "1.4.0",
+ "sshpk": "1.13.0"
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "requires": {
+ "once": "1.4.0",
+ "wrappy": "1.0.2"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "bundled": true
+ },
+ "ini": {
+ "version": "1.3.4",
+ "bundled": true,
+ "optional": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "bundled": true,
+ "requires": {
+ "number-is-nan": "1.0.1"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "bundled": true,
+ "optional": true
+ },
+ "jodid25519": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "jsbn": "0.1.1"
+ }
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "bundled": true,
+ "optional": true
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "bundled": true,
+ "optional": true
+ },
+ "json-stable-stringify": {
+ "version": "1.0.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "jsonify": "0.0.0"
+ }
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "jsonify": {
+ "version": "0.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "jsprim": {
+ "version": "1.4.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.0.2",
+ "json-schema": "0.2.3",
+ "verror": "1.3.6"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ }
+ }
+ },
+ "mime-db": {
+ "version": "1.27.0",
+ "bundled": true
+ },
+ "mime-types": {
+ "version": "2.1.15",
+ "bundled": true,
+ "requires": {
+ "mime-db": "1.27.0"
+ }
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "requires": {
+ "brace-expansion": "1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "bundled": true
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "bundled": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "node-pre-gyp": {
+ "version": "0.6.39",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "detect-libc": "1.0.2",
+ "hawk": "3.1.3",
+ "mkdirp": "0.5.1",
+ "nopt": "4.0.1",
+ "npmlog": "4.1.0",
+ "rc": "1.2.1",
+ "request": "2.81.0",
+ "rimraf": "2.6.1",
+ "semver": "5.3.0",
+ "tar": "2.2.1",
+ "tar-pack": "3.4.0"
+ }
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "abbrev": "1.1.0",
+ "osenv": "0.1.4"
+ }
+ },
+ "npmlog": {
+ "version": "4.1.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "are-we-there-yet": "1.1.4",
+ "console-control-strings": "1.1.0",
+ "gauge": "2.7.4",
+ "set-blocking": "2.0.0"
+ }
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "oauth-sign": {
+ "version": "0.8.2",
+ "bundled": true,
+ "optional": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "bundled": true,
+ "optional": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "requires": {
+ "wrappy": "1.0.2"
+ }
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "osenv": {
+ "version": "0.1.4",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "os-homedir": "1.0.2",
+ "os-tmpdir": "1.0.2"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true
+ },
+ "performance-now": {
+ "version": "0.2.0",
+ "bundled": true,
+ "optional": true
+ },
+ "process-nextick-args": {
+ "version": "1.0.7",
+ "bundled": true
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "bundled": true,
+ "optional": true
+ },
+ "qs": {
+ "version": "6.4.0",
+ "bundled": true,
+ "optional": true
+ },
+ "rc": {
+ "version": "1.2.1",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "deep-extend": "0.4.2",
+ "ini": "1.3.4",
+ "minimist": "1.2.0",
+ "strip-json-comments": "2.0.1"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "bundled": true,
+ "optional": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.2.9",
+ "bundled": true,
+ "requires": {
+ "buffer-shims": "1.0.0",
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "string_decoder": "1.0.1",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "request": {
+ "version": "2.81.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "aws-sign2": "0.6.0",
+ "aws4": "1.6.0",
+ "caseless": "0.12.0",
+ "combined-stream": "1.0.5",
+ "extend": "3.0.1",
+ "forever-agent": "0.6.1",
+ "form-data": "2.1.4",
+ "har-validator": "4.2.1",
+ "hawk": "3.1.3",
+ "http-signature": "1.1.1",
+ "is-typedarray": "1.0.0",
+ "isstream": "0.1.2",
+ "json-stringify-safe": "5.0.1",
+ "mime-types": "2.1.15",
+ "oauth-sign": "0.8.2",
+ "performance-now": "0.2.0",
+ "qs": "6.4.0",
+ "safe-buffer": "5.0.1",
+ "stringstream": "0.0.5",
+ "tough-cookie": "2.3.2",
+ "tunnel-agent": "0.6.0",
+ "uuid": "3.0.1"
+ }
+ },
+ "rimraf": {
+ "version": "2.6.1",
+ "bundled": true,
+ "requires": {
+ "glob": "7.1.2"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.0.1",
+ "bundled": true
+ },
+ "semver": {
+ "version": "5.3.0",
+ "bundled": true,
+ "optional": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "bundled": true,
+ "optional": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "bundled": true,
+ "optional": true
+ },
+ "sntp": {
+ "version": "1.0.9",
+ "bundled": true,
+ "requires": {
+ "hoek": "2.16.3"
+ }
+ },
+ "sshpk": {
+ "version": "1.13.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "asn1": "0.2.3",
+ "assert-plus": "1.0.0",
+ "bcrypt-pbkdf": "1.0.1",
+ "dashdash": "1.14.1",
+ "ecc-jsbn": "0.1.1",
+ "getpass": "0.1.7",
+ "jodid25519": "1.0.2",
+ "jsbn": "0.1.1",
+ "tweetnacl": "0.14.5"
+ },
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "optional": true
+ }
+ }
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "requires": {
+ "code-point-at": "1.1.0",
+ "is-fullwidth-code-point": "1.0.0",
+ "strip-ansi": "3.0.1"
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.1",
+ "bundled": true,
+ "requires": {
+ "safe-buffer": "5.0.1"
+ }
+ },
+ "stringstream": {
+ "version": "0.0.5",
+ "bundled": true,
+ "optional": true
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "requires": {
+ "ansi-regex": "2.1.1"
+ }
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "tar": {
+ "version": "2.2.1",
+ "bundled": true,
+ "requires": {
+ "block-stream": "0.0.9",
+ "fstream": "1.0.11",
+ "inherits": "2.0.3"
+ }
+ },
+ "tar-pack": {
+ "version": "3.4.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "debug": "2.6.8",
+ "fstream": "1.0.11",
+ "fstream-ignore": "1.0.5",
+ "once": "1.4.0",
+ "readable-stream": "2.2.9",
+ "rimraf": "2.6.1",
+ "tar": "2.2.1",
+ "uid-number": "0.0.6"
}
- }
- }
- },
- "esprima": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
- "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE="
- },
- "estraverse": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz",
- "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q="
- },
- "esutils": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
- "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs="
- },
- "event-stream": {
- "version": "3.3.4",
- "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
- "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=",
- "requires": {
- "duplexer": "0.1.1",
- "from": "0.1.7",
- "map-stream": "0.1.0",
- "pause-stream": "0.0.11",
- "split": "0.3.3",
- "stream-combiner": "0.0.4",
- "through": "2.3.8"
- },
- "dependencies": {
- "split": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz",
- "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=",
+ },
+ "tough-cookie": {
+ "version": "2.3.2",
+ "bundled": true,
+ "optional": true,
"requires": {
- "through": "2.3.8"
+ "punycode": "1.4.1"
+ }
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "safe-buffer": "5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "bundled": true,
+ "optional": true
+ },
+ "uid-number": {
+ "version": "0.0.6",
+ "bundled": true,
+ "optional": true
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true
+ },
+ "uuid": {
+ "version": "3.0.1",
+ "bundled": true,
+ "optional": true
+ },
+ "verror": {
+ "version": "1.3.6",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "extsprintf": "1.0.2"
}
+ },
+ "wide-align": {
+ "version": "1.1.2",
+ "bundled": true,
+ "optional": true,
+ "requires": {
+ "string-width": "1.0.2"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true
}
}
},
- "exit": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
- "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw="
- },
- "extend": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz",
- "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ="
- },
- "extsprintf": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
- "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
- },
- "fast-levenshtein": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
- },
- "find-up": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
- "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
- "requires": {
- "path-exists": "2.1.0",
- "pinkie-promise": "2.0.1"
- }
- },
- "foreach": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
- "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k="
- },
- "forever-agent": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
- "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
- },
- "form-data": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz",
- "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=",
- "requires": {
- "asynckit": "0.4.0",
- "combined-stream": "1.0.5",
- "mime-types": "2.1.17"
- }
- },
- "from": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
- "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4="
- },
- "fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
- },
"fstream": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
@@ -1013,6 +1919,23 @@
"path-is-absolute": "1.0.1"
}
},
+ "glob-base": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
+ "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
+ "requires": {
+ "glob-parent": "2.0.0",
+ "is-glob": "2.0.1"
+ }
+ },
+ "glob-parent": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
+ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
+ "requires": {
+ "is-glob": "2.0.1"
+ }
+ },
"graceful-fs": {
"version": "4.1.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
@@ -1142,6 +2065,14 @@
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
},
+ "is-binary-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+ "requires": {
+ "binary-extensions": "1.11.0"
+ }
+ },
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
@@ -1165,6 +2096,29 @@
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
"integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY="
},
+ "is-dotfile": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
+ "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE="
+ },
+ "is-equal-shallow": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
+ "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
+ "requires": {
+ "is-primitive": "2.0.0"
+ }
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik="
+ },
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA="
+ },
"is-finite": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
@@ -1181,11 +2135,37 @@
"number-is-nan": "1.0.1"
}
},
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "requires": {
+ "is-extglob": "1.0.0"
+ }
+ },
+ "is-number": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
+ "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
+ "requires": {
+ "kind-of": "3.2.2"
+ }
+ },
"is-obj": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
},
+ "is-posix-bracket": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
+ "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q="
+ },
+ "is-primitive": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
+ "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU="
+ },
"is-regex": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
@@ -1232,6 +2212,14 @@
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
},
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "requires": {
+ "isarray": "1.0.0"
+ }
+ },
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
@@ -1536,6 +2524,26 @@
"trim-newlines": "1.0.0"
}
},
+ "micromatch": {
+ "version": "2.3.11",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+ "requires": {
+ "arr-diff": "2.0.0",
+ "array-unique": "0.2.1",
+ "braces": "1.8.5",
+ "expand-brackets": "0.1.5",
+ "extglob": "0.3.2",
+ "filename-regex": "2.0.1",
+ "is-extglob": "1.0.0",
+ "is-glob": "2.0.1",
+ "kind-of": "3.2.2",
+ "normalize-path": "2.1.1",
+ "object.omit": "2.0.1",
+ "parse-glob": "3.0.4",
+ "regex-cache": "0.4.4"
+ }
+ },
"mime-db": {
"version": "1.30.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz",
@@ -1680,6 +2688,14 @@
"validate-npm-package-license": "3.0.1"
}
},
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "requires": {
+ "remove-trailing-separator": "1.1.0"
+ }
+ },
"npm": {
"version": "5.5.1",
"resolved": "https://registry.npmjs.org/npm/-/npm-5.5.1.tgz",
@@ -5110,6 +6126,15 @@
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz",
"integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0="
},
+ "object.omit": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
+ "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
+ "requires": {
+ "for-own": "0.1.5",
+ "is-extendable": "0.1.1"
+ }
+ },
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -5178,6 +6203,17 @@
"resolved": "https://registry.npmjs.org/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz",
"integrity": "sha1-nn2LslKmy2ukJZUGC3v23z28H1A="
},
+ "parse-glob": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
+ "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
+ "requires": {
+ "glob-base": "0.3.0",
+ "is-dotfile": "1.0.3",
+ "is-extglob": "1.0.0",
+ "is-glob": "2.0.1"
+ }
+ },
"parse-json": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
@@ -5250,6 +6286,11 @@
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ="
},
+ "preserve": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
+ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks="
+ },
"process-nextick-args": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
@@ -5288,6 +6329,43 @@
"resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz",
"integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM="
},
+ "randomatic": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
+ "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==",
+ "requires": {
+ "is-number": "3.0.0",
+ "kind-of": "4.0.0"
+ },
+ "dependencies": {
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "requires": {
+ "kind-of": "3.2.2"
+ },
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "requires": {
+ "is-buffer": "1.1.6"
+ }
+ }
+ }
+ },
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "requires": {
+ "is-buffer": "1.1.6"
+ }
+ }
+ }
+ },
"rc": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.2.tgz",
@@ -5332,6 +6410,17 @@
"util-deprecate": "1.0.2"
}
},
+ "readdirp": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
+ "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=",
+ "requires": {
+ "graceful-fs": "4.1.11",
+ "minimatch": "3.0.4",
+ "readable-stream": "2.3.3",
+ "set-immediate-shim": "1.0.1"
+ }
+ },
"redent": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
@@ -5341,6 +6430,24 @@
"strip-indent": "1.0.1"
}
},
+ "regex-cache": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
+ "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
+ "requires": {
+ "is-equal-shallow": "0.1.3"
+ }
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8="
+ },
+ "repeat-element": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz",
+ "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo="
+ },
"repeat-string": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
@@ -5433,6 +6540,11 @@
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
},
+ "set-immediate-shim": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
+ "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E="
+ },
"shebang-command": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
diff --git a/package.json b/package.json
index 0c27d3b460..05c6d8351d 100644
--- a/package.json
+++ b/package.json
@@ -55,6 +55,7 @@
"@types/source-map": "^0.5.0",
"@types/webpack": "^3.0.2",
"@types/webpack-sources": "^0.1.3",
+ "chokidar": "^1.7.0",
"conventional-changelog": "^1.1.0",
"glob": "^7.0.3",
"istanbul": "^0.4.5",
diff --git a/packages/angular_devkit/core/BUILD b/packages/angular_devkit/core/BUILD
index c1dd19cca8..9ade24c9d2 100644
--- a/packages/angular_devkit/core/BUILD
+++ b/packages/angular_devkit/core/BUILD
@@ -29,6 +29,7 @@ ts_library(
),
deps = [
"//packages/angular_devkit/core",
+ # @deps: rxjs
],
tsconfig = "//:tsconfig.json",
module_name = "@angular-devkit/core/node",
diff --git a/packages/angular_devkit/core/node/host.ts b/packages/angular_devkit/core/node/host.ts
new file mode 100644
index 0000000000..01cb0b168f
--- /dev/null
+++ b/packages/angular_devkit/core/node/host.ts
@@ -0,0 +1,345 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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 {
+ Path,
+ PathFragment,
+ asPosixPath,
+ asWindowsPath,
+ dirname,
+ fragment,
+ join,
+ normalize,
+ virtualFs,
+} from '@angular-devkit/core';
+import * as fs from 'fs';
+import { Observable } from 'rxjs/Observable';
+import { ArrayObservable } from 'rxjs/observable/ArrayObservable';
+import { FromObservable } from 'rxjs/observable/FromObservable';
+import { concat } from 'rxjs/operators/concat';
+import { concatMap } from 'rxjs/operators/concatMap';
+import { ignoreElements } from 'rxjs/operators/ignoreElements';
+import { map } from 'rxjs/operators/map';
+import { mergeMap } from 'rxjs/operators/mergeMap';
+import { publish } from 'rxjs/operators/publish';
+import { refCount } from 'rxjs/operators/refCount';
+
+
+interface ChokidarWatcher {
+ new (options: {}): ChokidarWatcher;
+
+ add(path: string): ChokidarWatcher;
+ on(type: 'change', cb: (path: string) => void): ChokidarWatcher;
+ on(type: 'add', cb: (path: string) => void): ChokidarWatcher;
+ on(type: 'unlink', cb: (path: string) => void): ChokidarWatcher;
+
+ close(): void;
+}
+
+const { FSWatcher }: { FSWatcher: ChokidarWatcher } = require('chokidar');
+
+
+type FsFunction0 = (cb: (err?: Error, result?: R) => void) => void;
+type FsFunction1 = (p1: T1, cb: (err?: Error, result?: R) => void) => void;
+type FsFunction2
+ = (p1: T1, p2: T2, cb: (err?: Error, result?: R) => void) => void;
+
+
+function _callFs(fn: FsFunction0): Observable;
+function _callFs(fn: FsFunction1, p1: T1): Observable;
+function _callFs(fn: FsFunction2, p1: T1, p2: T2): Observable;
+
+function _callFs(fn: Function, ...args: {}[]): Observable {
+ return new Observable(obs => {
+ fn(...args, (err?: Error, result?: ResultT) => {
+ if (err) {
+ obs.error(err);
+ } else {
+ obs.next(result);
+ obs.complete();
+ }
+ });
+ });
+}
+
+
+/**
+ * An implementation of the Virtual FS using Node as the background. There are two versions; one
+ * synchronous and one asynchronous.
+ */
+export class NodeJsAsyncHost implements virtualFs.Host {
+ protected _getSystemPath(path: Path): string {
+ if (process.platform.startsWith('win32')) {
+ return asWindowsPath(path);
+ } else {
+ return asPosixPath(path);
+ }
+ }
+
+ get capabilities(): virtualFs.HostCapabilities {
+ return { synchronous: false };
+ }
+
+ write(path: Path, content: virtualFs.FileBuffer): Observable {
+ return new Observable(obs => {
+ // Create folders if necessary.
+ const _createDir = (path: Path) => {
+ if (fs.existsSync(this._getSystemPath(path))) {
+ return;
+ }
+ if (dirname(path) === path) {
+ throw new Error();
+ }
+ _createDir(dirname(path));
+ fs.mkdirSync(this._getSystemPath(path));
+ };
+ _createDir(dirname(path));
+
+ _callFs(
+ fs.writeFile,
+ this._getSystemPath(path),
+ new Uint8Array(content),
+ ).subscribe(obs);
+ });
+ }
+
+ read(path: Path): Observable {
+ return _callFs(fs.readFile, this._getSystemPath(path)).pipe(
+ map(buffer => new Uint8Array(buffer).buffer as virtualFs.FileBuffer),
+ );
+ }
+
+ delete(path: Path): Observable {
+ return this.isDirectory(path).pipe(
+ mergeMap(isDirectory => {
+ if (isDirectory) {
+ const allFiles: Path[] = [];
+ const allDirs: Path[] = [];
+ const _recurseList = (path: Path) => {
+ for (const fragment of fs.readdirSync(this._getSystemPath(path))) {
+ if (fs.statSync(this._getSystemPath(join(path, fragment))).isDirectory()) {
+ _recurseList(join(path, fragment));
+ allDirs.push(join(path, fragment));
+ } else {
+ allFiles.push(join(path, fragment));
+ }
+ }
+ };
+ _recurseList(path);
+
+ return FromObservable.create(allFiles)
+ .pipe(
+ mergeMap(p => _callFs(fs.unlink, this._getSystemPath(p))),
+ ignoreElements(),
+ concat(FromObservable.create(allDirs).pipe(
+ concatMap(p => _callFs(fs.rmdir, this._getSystemPath(p))),
+ )),
+ map(() => {}),
+ );
+ } else {
+ return _callFs(fs.unlink, this._getSystemPath(path));
+ }
+ }),
+ );
+ }
+
+ rename(from: Path, to: Path): Observable {
+ return _callFs(fs.rename, this._getSystemPath(from), this._getSystemPath(to));
+ }
+
+ list(path: Path): Observable {
+ return _callFs(fs.readdir, this._getSystemPath(path)).pipe(
+ map(names => names.map(name => fragment(name))),
+ );
+ }
+
+ exists(path: Path): Observable {
+ // Exists is a special case because it cannot error.
+ return new Observable(obs => {
+ fs.exists(path, exists => {
+ obs.next(exists);
+ obs.complete();
+ });
+ });
+ }
+
+ isDirectory(path: Path): Observable {
+ return _callFs(fs.stat, this._getSystemPath(path)).pipe(
+ map(stat => stat.isDirectory()),
+ );
+ }
+ isFile(path: Path): Observable {
+ return _callFs(fs.stat, this._getSystemPath(path)).pipe(
+ map(stat => stat.isDirectory()),
+ );
+ }
+
+ // Some hosts may not support stats.
+ stats(path: Path): Observable> | null {
+ return _callFs(fs.stat, this._getSystemPath(path));
+ }
+
+ // Some hosts may not support watching.
+ watch(
+ path: Path,
+ _options?: virtualFs.HostWatchOptions,
+ ): Observable | null {
+ return new Observable(obs => {
+ const watcher = new FSWatcher({ persistent: true }).add(this._getSystemPath(path));
+
+ watcher
+ .on('change', path => {
+ obs.next({
+ path: normalize(path),
+ time: new Date(),
+ type: virtualFs.HostWatchEventType.Changed,
+ });
+ })
+ .on('add', path => {
+ obs.next({
+ path: normalize(path),
+ time: new Date(),
+ type: virtualFs.HostWatchEventType.Created,
+ });
+ })
+ .on('unlink', path => {
+ obs.next({
+ path: normalize(path),
+ time: new Date(),
+ type: virtualFs.HostWatchEventType.Deleted,
+ });
+ });
+
+ return () => watcher.close();
+ }).pipe(
+ publish(),
+ refCount(),
+ );
+ }
+}
+
+
+/**
+ * An implementation of the Virtual FS using Node as the backend, synchronously.
+ */
+export class NodeJsSyncHost implements virtualFs.Host {
+ protected _getSystemPath(path: Path): string {
+ if (process.platform.startsWith('win32')) {
+ return asWindowsPath(path);
+ } else {
+ return asPosixPath(path);
+ }
+ }
+
+ get capabilities(): virtualFs.HostCapabilities {
+ return { synchronous: true };
+ }
+
+ write(path: Path, content: virtualFs.FileBuffer): Observable {
+ // Create folders if necessary.
+ const _createDir = (path: Path) => {
+ if (fs.existsSync(this._getSystemPath(path))) {
+ return;
+ }
+ _createDir(dirname(path));
+ fs.mkdirSync(path);
+ };
+ _createDir(dirname(path));
+ fs.writeFileSync(this._getSystemPath(path), new Uint8Array(content));
+
+ return Observable.empty();
+ }
+
+ read(path: Path): Observable {
+ const buffer = fs.readFileSync(this._getSystemPath(path));
+
+ return ArrayObservable.of(new Uint8Array(buffer).buffer as virtualFs.FileBuffer);
+ }
+
+ delete(path: Path): Observable {
+ if (this.isDirectory(path)) {
+ // Since this is synchronous, we can recurse and safely ignore the result.
+ for (const name of fs.readdirSync(this._getSystemPath(path))) {
+ this.delete(join(path, name));
+ }
+ fs.rmdirSync(this._getSystemPath(path));
+ } else {
+ fs.unlinkSync(this._getSystemPath(path));
+ }
+
+ return Observable.empty();
+ }
+
+ rename(from: Path, to: Path): Observable {
+ fs.renameSync(this._getSystemPath(from), this._getSystemPath(to));
+
+ return Observable.empty();
+ }
+
+ list(path: Path): Observable {
+ return ArrayObservable.of(fs.readdirSync(this._getSystemPath(path))).pipe(
+ map(names => names.map(name => fragment(name))),
+ );
+ }
+
+ exists(path: Path): Observable {
+ return ArrayObservable.of(fs.existsSync(this._getSystemPath(path)));
+ }
+
+ isDirectory(path: Path): Observable {
+ // tslint:disable-next-line:non-null-operator
+ return this.stats(path) !.map(stat => stat.isDirectory());
+ }
+ isFile(path: Path): Observable {
+ // tslint:disable-next-line:non-null-operator
+ return this.stats(path) !.map(stat => stat.isFile());
+ }
+
+ // Some hosts may not support stats.
+ stats(path: Path): Observable> | null {
+ return ArrayObservable.of(fs.statSync(this._getSystemPath(path)));
+ }
+
+ // Some hosts may not support watching.
+ watch(
+ path: Path,
+ _options?: virtualFs.HostWatchOptions,
+ ): Observable | null {
+ return new Observable(obs => {
+ const opts = { persistent: false };
+ const watcher = new FSWatcher(opts).add(this._getSystemPath(path));
+
+ watcher
+ .on('change', path => {
+ obs.next({
+ path: normalize(path),
+ time: new Date(),
+ type: virtualFs.HostWatchEventType.Changed,
+ });
+ })
+ .on('add', path => {
+ obs.next({
+ path: normalize(path),
+ time: new Date(),
+ type: virtualFs.HostWatchEventType.Created,
+ });
+ })
+ .on('unlink', path => {
+ obs.next({
+ path: normalize(path),
+ time: new Date(),
+ type: virtualFs.HostWatchEventType.Deleted,
+ });
+ });
+
+ return () => watcher.close();
+ }).pipe(
+ publish(),
+ refCount(),
+ );
+ }
+}
diff --git a/packages/angular_devkit/core/node/host_spec.ts b/packages/angular_devkit/core/node/host_spec.ts
new file mode 100644
index 0000000000..b2fc85443f
--- /dev/null
+++ b/packages/angular_devkit/core/node/host_spec.ts
@@ -0,0 +1,60 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * 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
+ */
+// tslint:disable:no-any
+// tslint:disable:non-null-operator
+import { normalize, virtualFs } from '@angular-devkit/core';
+import { NodeJsAsyncHost } from '@angular-devkit/core/node';
+import * as fs from 'fs';
+import { Observable } from 'rxjs/Observable';
+import { Subscription } from 'rxjs/Subscription';
+
+const temp = require('temp');
+
+
+describe('NodeJsAsyncHost', () => {
+ let root: string;
+ let host: virtualFs.Host;
+
+ beforeEach(() => {
+ root = temp.mkdirSync('core-node-spec-');
+ host = new virtualFs.ScopedHost(new NodeJsAsyncHost(), normalize(root));
+ });
+ afterEach(done => {
+ host.delete(normalize('/'))
+ .subscribe({ complete() { done(); } });
+ });
+
+ it('can watch', done => {
+ let obs: Observable;
+ let subscription: Subscription;
+ const content = virtualFs.stringToFileBuffer('hello world');
+ const content2 = virtualFs.stringToFileBuffer('hello world 2');
+ const allEvents: virtualFs.HostWatchEvent[] = [];
+
+ Promise.resolve()
+ .then(() => fs.mkdirSync(root + '/sub1'))
+ .then(() => fs.writeFileSync(root + '/sub1/file1', 'hello world'))
+ .then(() => {
+ obs = host.watch(normalize('/sub1'), { recursive: true }) !;
+ expect(obs).not.toBeNull();
+ subscription = obs.subscribe(event => { allEvents.push(event); });
+ })
+ .then(() => new Promise(resolve => setTimeout(resolve, 100)))
+ // Discard the events registered so far.
+ .then(() => allEvents.splice(0))
+ .then(() => host.write(normalize('/sub1/sub2/file3'), content).toPromise())
+ .then(() => host.write(normalize('/sub1/file2'), content2).toPromise())
+ .then(() => host.delete(normalize('/sub1/file1')).toPromise())
+ .then(() => new Promise(resolve => setTimeout(resolve, 2000)))
+ .then(() => {
+ expect(allEvents.length).toBe(3);
+ subscription.unsubscribe();
+ })
+ .then(done, done.fail);
+ }, 10000000);
+});
diff --git a/packages/angular_devkit/core/node/index.ts b/packages/angular_devkit/core/node/index.ts
index d38ace92c0..51a3944ba3 100644
--- a/packages/angular_devkit/core/node/index.ts
+++ b/packages/angular_devkit/core/node/index.ts
@@ -8,6 +8,7 @@
import * as fs from './fs';
export * from './cli-logger';
+export * from './host';
export { ModuleNotFoundException, ResolveOptions, resolve } from './resolve';
export { fs };
diff --git a/packages/angular_devkit/core/package.json b/packages/angular_devkit/core/package.json
index d0c1dc09b1..946165a90b 100644
--- a/packages/angular_devkit/core/package.json
+++ b/packages/angular_devkit/core/package.json
@@ -11,6 +11,7 @@
"core"
],
"dependencies": {
+ "chokidar": "^1.7.0",
"source-map": "^0.5.6"
}
}
diff --git a/packages/angular_devkit/core/src/virtual-fs/host/buffer.ts b/packages/angular_devkit/core/src/virtual-fs/host/buffer.ts
index 3ab53b633d..e2bc6296ba 100644
--- a/packages/angular_devkit/core/src/virtual-fs/host/buffer.ts
+++ b/packages/angular_devkit/core/src/virtual-fs/host/buffer.ts
@@ -5,9 +5,14 @@
* 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 { UnsupportedPlatformException } from '../../exception/exception';
import { FileBuffer } from './interface';
+declare const TextEncoder: {
+ new (encoding: string): {
+ encode(str: string): Uint8Array;
+ };
+};
+
export function stringToFileBuffer(str: string): FileBuffer {
// If we're in Node...
if (typeof Buffer !== 'undefined' && typeof Buffer.from === 'function') {
@@ -19,7 +24,17 @@ export function stringToFileBuffer(str: string): FileBuffer {
}
return ab;
- }
+ } else if (typeof TextEncoder !== 'undefined') {
+ // Modern browsers implement TextEncode.
+ return new TextEncoder('utf-8').encode(str).buffer as ArrayBuffer;
+ } else {
+ // Slowest method but sure to be compatible with every platform.
+ const buf = new ArrayBuffer(str.length * 2); // 2 bytes for each char
+ const bufView = new Uint16Array(buf);
+ for (let i = 0, strLen = str.length; i < strLen; i++) {
+ bufView[i] = str.charCodeAt(i);
+ }
- throw new UnsupportedPlatformException();
+ return buf;
+ }
}
diff --git a/packages/angular_devkit/core/src/virtual-fs/path.ts b/packages/angular_devkit/core/src/virtual-fs/path.ts
index 0332fcadc2..6efff030b1 100644
--- a/packages/angular_devkit/core/src/virtual-fs/path.ts
+++ b/packages/angular_devkit/core/src/virtual-fs/path.ts
@@ -241,3 +241,25 @@ export function normalize(path: string): Path {
return p.join(NormalizedSep) as Path;
}
}
+
+
+// Platform-specific paths.
+export type WindowsPath = string & {
+ __PRIVATE_DEVKIT_WINDOWS_PATH: void;
+};
+export type PosixPath = string & {
+ __PRIVATE_DEVKIT_POSIX_PATH: void;
+};
+
+export function asWindowsPath(path: Path): WindowsPath {
+ const drive = path.match(/^\/(\w)\/(.*)$/);
+ if (drive) {
+ return `${drive[1]}:\\${drive[2].replace(/\//g, '\\')}` as WindowsPath;
+ }
+
+ return path.replace(/\//g, '\\') as WindowsPath;
+}
+
+export function asPosixPath(path: Path): PosixPath {
+ return path as string as PosixPath;
+}
From 75dc063af5c5ea254ca7ba8e15537890d402f56a Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Wed, 13 Dec 2017 10:19:51 -0800
Subject: [PATCH 062/807] build: do not bazel build ...
Due to bazelbuild/bazel#4242 it actually recurses in node_modules which is bad.
---
.circleci/config.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 1287d14523..bddffe69c2 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -74,7 +74,7 @@ jobs:
key: angular_devkit-{{ checksum "package-lock.json" }}
- run: bazel run @nodejs//:npm install
- - run: bazel build ...
+ - run: bazel build //packages/...
- save_cache:
key: angular_devkit-{{ checksum "package-lock.json" }}
From ad84741590783e974c1f5bd2eeb80ffdf573318b Mon Sep 17 00:00:00 2001
From: Cyrille Tuzi
Date: Sat, 16 Dec 2017 14:58:17 +0100
Subject: [PATCH 063/807] fix(@schematics/angular): add dist-server in
.gitignore
---
packages/schematics/angular/application/files/__dot__gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/packages/schematics/angular/application/files/__dot__gitignore b/packages/schematics/angular/application/files/__dot__gitignore
index 54bfd2001e..4ae2c37916 100755
--- a/packages/schematics/angular/application/files/__dot__gitignore
+++ b/packages/schematics/angular/application/files/__dot__gitignore
@@ -2,6 +2,7 @@
# compiled output
/dist
+/dist-server
/tmp
/out-tsc
From 3b0d31770dbe1d7de450e592e6fdd1d78fa897a9 Mon Sep 17 00:00:00 2001
From: Charles Lyding <19598772+clydin@users.noreply.github.com>
Date: Mon, 18 Dec 2017 11:21:07 -0500
Subject: [PATCH 064/807] refactor(@angular-devkit/build-optimizer): improve
resiliency of enum wrapper
---
.../build-optimizer/build-optimizer_spec.ts | 5 +-
.../src/transforms/wrap-enums.ts | 199 ++++++++++--------
.../src/transforms/wrap-enums_spec.ts | 9 +-
3 files changed, 121 insertions(+), 92 deletions(-)
diff --git a/packages/angular_devkit/build_optimizer/src/build-optimizer/build-optimizer_spec.ts b/packages/angular_devkit/build_optimizer/src/build-optimizer/build-optimizer_spec.ts
index 1604caab6f..b73072d307 100644
--- a/packages/angular_devkit/build_optimizer/src/build-optimizer/build-optimizer_spec.ts
+++ b/packages/angular_devkit/build_optimizer/src/build-optimizer/build-optimizer_spec.ts
@@ -58,12 +58,11 @@ describe('build-optimizer', () => {
/** PURE_IMPORTS_START _angular_core,tslib PURE_IMPORTS_END */
${imports}
import { __extends } from "tslib";
- var ChangeDetectionStrategy = /*@__PURE__*/ (function () {
- var ChangeDetectionStrategy = {};
+ var ChangeDetectionStrategy = /*@__PURE__*/ (function (ChangeDetectionStrategy) {
ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush";
ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default";
return ChangeDetectionStrategy;
- })();
+ })({});
var Clazz = /*@__PURE__*/ (function () { function Clazz() { } ${staticProperty} return Clazz; }());
var ComponentClazz = /*@__PURE__*/ (function () {
function ComponentClazz() { }
diff --git a/packages/angular_devkit/build_optimizer/src/transforms/wrap-enums.ts b/packages/angular_devkit/build_optimizer/src/transforms/wrap-enums.ts
index 267c246a4a..2506160d6b 100644
--- a/packages/angular_devkit/build_optimizer/src/transforms/wrap-enums.ts
+++ b/packages/angular_devkit/build_optimizer/src/transforms/wrap-enums.ts
@@ -35,7 +35,7 @@ export function getWrapEnumsTransformer(): ts.TransformerFactory
const result = visitBlockStatements(sf.statements, context);
- return ts.updateSourceFileNode(sf, result);
+ return ts.updateSourceFileNode(sf, ts.setTextRange(result, sf.statements));
};
return transformer;
@@ -52,10 +52,11 @@ function visitBlockStatements(
const visitor: ts.Visitor = (node) => {
if (isBlockLike(node)) {
- const result = visitBlockStatements(node.statements, context);
+ let result = visitBlockStatements(node.statements, context);
if (result === node.statements) {
return node;
}
+ result = ts.setTextRange(result, node.statements);
switch (node.kind) {
case ts.SyntaxKind.Block:
return ts.updateBlock(node as ts.Block, result);
@@ -98,18 +99,16 @@ function visitBlockStatements(
const name = variableDeclaration.name.text;
if (!variableDeclaration.initializer) {
- const enumStatements = findTs2_3EnumStatements(name, statements[oIndex + 1]);
- if (enumStatements.length > 0) {
+ const iife = findTs2_3EnumIife(name, statements[oIndex + 1]);
+ if (iife) {
// found an enum
if (!updatedStatements) {
updatedStatements = statements.slice();
}
- // create wrapper and replace variable statement and IIFE
- updatedStatements.splice(uIndex, 2, createWrappedEnum(
- name,
+ // update IIFE and replace variable statement and old IIFE
+ updatedStatements.splice(uIndex, 2, updateEnumIife(
currentStatement,
- enumStatements,
- undefined,
+ iife,
));
// skip IIFE statement
oIndex++;
@@ -117,8 +116,7 @@ function visitBlockStatements(
}
} else if (ts.isObjectLiteralExpression(variableDeclaration.initializer)
&& variableDeclaration.initializer.properties.length === 0) {
- const nextStatements = statements.slice(oIndex + 1);
- const enumStatements = findTs2_2EnumStatements(name, nextStatements);
+ const enumStatements = findTs2_2EnumStatements(name, statements, oIndex + 1);
if (enumStatements.length > 0) {
// found an enum
if (!updatedStatements) {
@@ -138,8 +136,7 @@ function visitBlockStatements(
} else if (ts.isObjectLiteralExpression(variableDeclaration.initializer)
&& variableDeclaration.initializer.properties.length !== 0) {
const literalPropertyCount = variableDeclaration.initializer.properties.length;
- const nextStatements = statements.slice(oIndex + 1);
- const enumStatements = findTsickleEnumStatements(name, nextStatements);
+ const enumStatements = findTsickleEnumStatements(name, statements, oIndex + 1);
if (enumStatements.length === literalPropertyCount) {
// found an enum
if (!updatedStatements) {
@@ -175,9 +172,10 @@ function visitBlockStatements(
}
// TS 2.3 enums have statements that are inside a IIFE.
-function findTs2_3EnumStatements(name: string, statement: ts.Statement): ts.ExpressionStatement[] {
- const enumStatements: ts.ExpressionStatement[] = [];
- const noNodes: ts.ExpressionStatement[] = [];
+function findTs2_3EnumIife(name: string, statement: ts.Statement): ts.CallExpression | null {
+ if (!ts.isExpressionStatement(statement) || !ts.isCallExpression(statement.expression)) {
+ return null;
+ }
const funcExpr = drilldownNodes(statement,
[
@@ -187,14 +185,14 @@ function findTs2_3EnumStatements(name: string, statement: ts.Statement): ts.Expr
{ prop: 'expression', kind: ts.SyntaxKind.FunctionExpression },
]);
- if (funcExpr === null) { return noNodes; }
+ if (funcExpr === null) { return null; }
if (!(
funcExpr.parameters.length === 1
&& funcExpr.parameters[0].name.kind === ts.SyntaxKind.Identifier
&& (funcExpr.parameters[0].name as ts.Identifier).text === name
)) {
- return noNodes;
+ return null;
}
// In TS 2.3 enums, the IIFE contains only expressions with a certain format.
@@ -207,13 +205,11 @@ function findTs2_3EnumStatements(name: string, statement: ts.Statement): ts.Expr
{ prop: 'expression', kind: ts.SyntaxKind.BinaryExpression },
]);
- if (innerBinExpr === null) { return noNodes; }
-
- const exprStmt = innerStmt as ts.ExpressionStatement;
+ if (innerBinExpr === null) { return null; }
if (!(innerBinExpr.operatorToken.kind === ts.SyntaxKind.FirstAssignment
&& innerBinExpr.left.kind === ts.SyntaxKind.ElementAccessExpression)) {
- return noNodes;
+ return null;
}
const innerElemAcc = innerBinExpr.left as ts.ElementAccessExpression;
@@ -224,13 +220,13 @@ function findTs2_3EnumStatements(name: string, statement: ts.Statement): ts.Expr
&& innerElemAcc.argumentExpression
&& innerElemAcc.argumentExpression.kind === ts.SyntaxKind.BinaryExpression
)) {
- return noNodes;
+ return null;
}
const innerArgBinExpr = innerElemAcc.argumentExpression as ts.BinaryExpression;
if (innerArgBinExpr.left.kind !== ts.SyntaxKind.ElementAccessExpression) {
- return noNodes;
+ return null;
}
const innerArgElemAcc = innerArgBinExpr.left as ts.ElementAccessExpression;
@@ -239,28 +235,27 @@ function findTs2_3EnumStatements(name: string, statement: ts.Statement): ts.Expr
innerArgElemAcc.expression.kind === ts.SyntaxKind.Identifier
&& (innerArgElemAcc.expression as ts.Identifier).text === name
)) {
- return noNodes;
+ return null;
}
-
- enumStatements.push(exprStmt);
}
- return enumStatements;
+ return statement.expression;
}
// TS 2.2 enums have statements after the variable declaration, with index statements followed
// by value statements.
function findTs2_2EnumStatements(
name: string,
- statements: ts.Statement[],
+ statements: ts.NodeArray,
+ statementOffset: number,
): ts.ExpressionStatement[] {
const enumStatements: ts.ExpressionStatement[] = [];
let beforeValueStatements = true;
- for (const stmt of statements) {
+ for (let index = statementOffset; index < statements.length; index++) {
// Ensure all statements are of the expected format and using the right identifer.
// When we find a statement that isn't part of the enum, return what we collected so far.
- const binExpr = drilldownNodes(stmt,
+ const binExpr = drilldownNodes(statements[index],
[
{ prop: null, kind: ts.SyntaxKind.ExpressionStatement },
{ prop: 'expression', kind: ts.SyntaxKind.BinaryExpression },
@@ -273,7 +268,7 @@ function findTs2_2EnumStatements(
return beforeValueStatements ? [] : enumStatements;
}
- const exprStmt = stmt as ts.ExpressionStatement;
+ const exprStmt = statements[index] as ts.ExpressionStatement;
const leftExpr = binExpr.left as ts.PropertyAccessExpression | ts.ElementAccessExpression;
if (!(leftExpr.expression.kind === ts.SyntaxKind.Identifier
@@ -298,76 +293,47 @@ function findTs2_2EnumStatements(
// See https://github.com/angular/devkit/issues/229#issuecomment-338512056 fore more information.
function findTsickleEnumStatements(
name: string,
- statements: ts.Statement[],
-): ts.ExpressionStatement[] {
- const enumStatements: ts.ExpressionStatement[] = [];
- // let beforeValueStatements = true;
+ statements: ts.NodeArray,
+ statementOffset: number,
+): ts.Statement[] {
+ const enumStatements: ts.Statement[] = [];
- for (const stmt of statements) {
+ for (let index = statementOffset; index < statements.length; index++) {
// Ensure all statements are of the expected format and using the right identifer.
// When we find a statement that isn't part of the enum, return what we collected so far.
- const binExpr = drilldownNodes(stmt,
+ const access = drilldownNodes(statements[index],
[
{ prop: null, kind: ts.SyntaxKind.ExpressionStatement },
{ prop: 'expression', kind: ts.SyntaxKind.BinaryExpression },
+ { prop: 'left', kind: ts.SyntaxKind.ElementAccessExpression },
]);
- if (binExpr === null || binExpr.left.kind !== ts.SyntaxKind.ElementAccessExpression) {
- return enumStatements;
+ if (!access) {
+ break;
}
- const exprStmt = stmt as ts.ExpressionStatement;
- const leftExpr = binExpr.left as ts.ElementAccessExpression;
+ if (!ts.isIdentifier(access.expression) || access.expression.text !== name) {
+ break;
+ }
- if (!(leftExpr.expression.kind === ts.SyntaxKind.Identifier
- && (leftExpr.expression as ts.Identifier).text === name)) {
- return enumStatements;
+ if (!access.argumentExpression || !ts.isPropertyAccessExpression(access.argumentExpression)) {
+ break;
}
- enumStatements.push(exprStmt);
+
+ const enumExpression = access.argumentExpression.expression;
+ if (!ts.isIdentifier(enumExpression) || enumExpression.text !== name) {
+ break;
+ }
+
+ enumStatements.push(statements[index]);
}
return enumStatements;
}
-function createWrappedEnum(
- name: string,
- hostNode: ts.VariableStatement,
- statements: Array,
- literalInitializer: ts.ObjectLiteralExpression | undefined,
-): ts.Statement {
+function updateHostNode(hostNode: ts.VariableStatement, expression: ts.Expression): ts.Statement {
const pureFunctionComment = '@__PURE__';
- literalInitializer = literalInitializer || ts.createObjectLiteral();
- const innerVarStmt = ts.createVariableStatement(
- undefined,
- ts.createVariableDeclarationList([
- ts.createVariableDeclaration(name, undefined, literalInitializer),
- ]),
- );
-
- const innerReturn = ts.createReturn(ts.createIdentifier(name));
-
- // NOTE: TS 2.4+ has a create IIFE helper method
- const iife = ts.createCall(
- ts.createParen(
- ts.createFunctionExpression(
- undefined,
- undefined,
- undefined,
- undefined,
- [],
- undefined,
- ts.createBlock([
- innerVarStmt,
- ...statements,
- innerReturn,
- ]),
- ),
- ),
- undefined,
- [],
- );
-
// Update existing host node with the pure comment before the variable declaration initializer.
const variableDeclaration = hostNode.declarationList.declarations[0];
const outerVarStmt = ts.updateVariableStatement(
@@ -381,7 +347,10 @@ function createWrappedEnum(
variableDeclaration.name,
variableDeclaration.type,
ts.addSyntheticLeadingComment(
- iife, ts.SyntaxKind.MultiLineCommentTrivia, pureFunctionComment, false,
+ expression,
+ ts.SyntaxKind.MultiLineCommentTrivia,
+ pureFunctionComment,
+ false,
),
),
],
@@ -390,3 +359,65 @@ function createWrappedEnum(
return outerVarStmt;
}
+
+function updateEnumIife(hostNode: ts.VariableStatement, iife: ts.CallExpression): ts.Statement {
+ if (!ts.isParenthesizedExpression(iife.expression)
+ || !ts.isFunctionExpression(iife.expression.expression)) {
+ throw new Error('Invalid IIFE Structure');
+ }
+
+ const expression = iife.expression.expression;
+ const updatedFunction = ts.updateFunctionExpression(
+ expression,
+ expression.modifiers,
+ expression.asteriskToken,
+ expression.name,
+ expression.typeParameters,
+ expression.parameters,
+ expression.type,
+ ts.updateBlock(
+ expression.body,
+ [
+ ...expression.body.statements,
+ ts.createReturn(expression.parameters[0].name as ts.Identifier),
+ ],
+ ),
+ );
+
+ const updatedIife = ts.updateCall(
+ iife,
+ ts.updateParen(
+ iife.expression,
+ updatedFunction,
+ ),
+ iife.typeArguments,
+ [ts.createObjectLiteral()],
+ );
+
+ return updateHostNode(hostNode, updatedIife);
+}
+
+function createWrappedEnum(
+ name: string,
+ hostNode: ts.VariableStatement,
+ statements: Array,
+ literalInitializer: ts.ObjectLiteralExpression | undefined,
+): ts.Statement {
+ literalInitializer = literalInitializer || ts.createObjectLiteral();
+ const innerVarStmt = ts.createVariableStatement(
+ undefined,
+ ts.createVariableDeclarationList([
+ ts.createVariableDeclaration(name, undefined, literalInitializer),
+ ]),
+ );
+
+ const innerReturn = ts.createReturn(ts.createIdentifier(name));
+
+ const iife = ts.createImmediatelyInvokedFunctionExpression([
+ innerVarStmt,
+ ...statements,
+ innerReturn,
+ ]);
+
+ return updateHostNode(hostNode, ts.createParen(iife));
+}
diff --git a/packages/angular_devkit/build_optimizer/src/transforms/wrap-enums_spec.ts b/packages/angular_devkit/build_optimizer/src/transforms/wrap-enums_spec.ts
index e4d7f3780e..34d8e4d5b2 100644
--- a/packages/angular_devkit/build_optimizer/src/transforms/wrap-enums_spec.ts
+++ b/packages/angular_devkit/build_optimizer/src/transforms/wrap-enums_spec.ts
@@ -30,7 +30,7 @@ describe('wrap-enums', () => {
ChangeDetectionStrategy[ChangeDetectionStrategy.OnPush] = "OnPush";
ChangeDetectionStrategy[ChangeDetectionStrategy.Default] = "Default";
return ChangeDetectionStrategy;
- })();
+ }());
`;
expect(testWrapEnums(input)).toBeTruthy();
@@ -46,12 +46,11 @@ describe('wrap-enums', () => {
})(ChangeDetectionStrategy || (ChangeDetectionStrategy = {}));
`;
const output = tags.stripIndent`
- export var ChangeDetectionStrategy = /*@__PURE__*/ (function () {
- var ChangeDetectionStrategy = {};
+ export var ChangeDetectionStrategy = /*@__PURE__*/ (function (ChangeDetectionStrategy) {
ChangeDetectionStrategy[ChangeDetectionStrategy["OnPush"] = 0] = "OnPush";
ChangeDetectionStrategy[ChangeDetectionStrategy["Default"] = 1] = "Default";
return ChangeDetectionStrategy;
- })();
+ })({});
`;
expect(testWrapEnums(input)).toBeTruthy();
@@ -85,7 +84,7 @@ describe('wrap-enums', () => {
FormatWidth[FormatWidth.Long] = "Long";
FormatWidth[FormatWidth.Full] = "Full";
return FormatWidth;
- })();
+ }());
`;
expect(testWrapEnums(input)).toBeTruthy();
From 132c9a56ac5c04de8ba9b797c789e9289e029d33 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Wed, 20 Dec 2017 17:08:19 -0800
Subject: [PATCH 065/807] release: patch
---
.monorepo.json | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/.monorepo.json b/.monorepo.json
index 2edcec0fb5..bebac77bad 100644
--- a/.monorepo.json
+++ b/.monorepo.json
@@ -53,13 +53,13 @@
"url": "https://github.com/angular/devkit/blob/master/packages/angular_devkit/build_optimizer/README.md"
}
],
- "version": "0.0.35",
- "hash": "88c0abf84c28c0423049af9e433d1fad"
+ "version": "0.0.36",
+ "hash": "718b816298c9ab7b7b12bd4c2f56423b"
},
"@angular-devkit/core": {
"name": "Core",
- "version": "0.0.22",
- "hash": "d3c7e8bba4e1e14a68df2076622af5f8"
+ "version": "0.0.23",
+ "hash": "45c3c8b7d60b038bbedd3000ebca1b88"
},
"@angular-devkit/schematics": {
"name": "Schematics",
@@ -69,20 +69,20 @@
"url": "https://github.com/angular/devkit/blob/master/packages/angular_devkit/schematics/README.md"
}
],
- "version": "0.0.41",
- "hash": "96e71fbcb1b2dd32f452ace07b1681d3"
+ "version": "0.0.42",
+ "hash": "33e9d31bdce777d0010265fcf99b8469"
},
"@schematics/angular": {
"name": "Angular Schematics",
"section": "Schematics",
- "version": "0.1.10",
- "hash": "6cd8b4e0065d6d5745104f5f8bcc4597"
+ "version": "0.1.11",
+ "hash": "94b15bcd6aafddd2cfa32c10bf1d46ab"
},
"@schematics/schematics": {
"name": "Schematics Schematics",
- "version": "0.0.10",
+ "version": "0.0.11",
"section": "Schematics",
- "hash": "787acac400e274f3f40ecab6909d0c8d"
+ "hash": "e5e524d6f6c523d4aed505bd7e6344cf"
}
}
}
From 555865f438f0ef016cc325f60641821add7b5dab Mon Sep 17 00:00:00 2001
From: cexbrayat
Date: Fri, 15 Dec 2017 17:45:24 -0300
Subject: [PATCH 066/807] feat(@schematics/angular): use TS 2.5
As Angular 5.1 now supports TS 2.5, this is now the default TS version.
---
packages/schematics/angular/application/files/package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/schematics/angular/application/files/package.json b/packages/schematics/angular/application/files/package.json
index eaca7ef206..a8dd18071e 100644
--- a/packages/schematics/angular/application/files/package.json
+++ b/packages/schematics/angular/application/files/package.json
@@ -45,6 +45,6 @@
"protractor": "~5.1.2",
"ts-node": "~3.2.0",
"tslint": "~5.7.0",<% } %>
- "typescript": "~2.4.2"
+ "typescript": "~2.5.3"
}
}
From 92aa56e5d8c33e22960b90991d8b13ff0fc795b3 Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Fri, 15 Dec 2017 11:00:08 -0800
Subject: [PATCH 067/807] feat(@angular-devkit/schematics): add more info on
--debug and show message
Show a message when nothing needs to be done. Otherwise its hard to tell if nothing was
done or if an unreported error happened.
---
.../angular_devkit/schematics/bin/schematics.ts | 15 ++++++++++++++-
.../schematics/testing/schematic-test-runner.ts | 8 ++++++++
2 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/packages/angular_devkit/schematics/bin/schematics.ts b/packages/angular_devkit/schematics/bin/schematics.ts
index 79a9e64e7a..4e8b04d328 100644
--- a/packages/angular_devkit/schematics/bin/schematics.ts
+++ b/packages/angular_devkit/schematics/bin/schematics.ts
@@ -182,11 +182,16 @@ const fsSink = new FileSystemSink(process.cwd(), force);
// actual filesystem. In this case we simply show the dry-run, but skip the fsSink commit.
let error = false;
+// Indicate to the user when nothing has been done.
+let nothingDone = true;
+
const loggingQueue: string[] = [];
// Logs out dry run events.
dryRunSink.reporter.subscribe((event: DryRunEvent) => {
+ nothingDone = false;
+
switch (event.kind) {
case 'error':
const desc = event.description == 'alreadyExist' ? 'already exists' : 'does not exist.';
@@ -255,6 +260,10 @@ schematic.call(args, host, { debug, logger: logger.asApi() })
loggingQueue.forEach(log => logger.info(log));
}
+ if (nothingDone) {
+ logger.info('Nothing to be done.');
+ }
+
if (dryRun || error) {
return Observable.of(tree);
}
@@ -269,7 +278,11 @@ schematic.call(args, host, { debug, logger: logger.asApi() })
} else if (err instanceof schema.javascript.InvalidPropertyNameException) {
logger.fatal('A non-supported argument was passed: ' + err.path.split('/').pop());
} else {
- logger.fatal(err.message);
+ if (debug) {
+ logger.fatal('An error occured:\n' + err.stack);
+ } else {
+ logger.fatal(err.message);
+ }
}
process.exit(1);
},
diff --git a/packages/angular_devkit/schematics/testing/schematic-test-runner.ts b/packages/angular_devkit/schematics/testing/schematic-test-runner.ts
index ff7b3bc7dc..0daa6ead51 100644
--- a/packages/angular_devkit/schematics/testing/schematic-test-runner.ts
+++ b/packages/angular_devkit/schematics/testing/schematic-test-runner.ts
@@ -9,6 +9,7 @@ import { logging, schema } from '@angular-devkit/core';
import {
Collection,
DelegateTree,
+ Rule, Schematic, SchematicContext,
SchematicEngine,
Tree,
VirtualTree,
@@ -18,6 +19,7 @@ import {
NodeModulesTestEngineHost,
} from '@angular-devkit/schematics/tools';
import { Observable } from 'rxjs/Observable';
+import { callRule } from '../src/rules/call';
export class UnitTestTree extends DelegateTree {
@@ -93,4 +95,10 @@ export class SchematicTestRunner {
return result;
}
+
+ callRule(rule: Rule, tree: Tree, parentContext?: Partial): Observable {
+ const context = this._engine.createContext({} as Schematic<{}, {}>, parentContext);
+
+ return callRule(rule, Observable.of(tree), context);
+ }
}
From d53554ce10425c75de150fbe0c03d76e4cb177ef Mon Sep 17 00:00:00 2001
From: Hans Larsen
Date: Fri, 15 Dec 2017 11:01:12 -0800
Subject: [PATCH 068/807] feat(@angular-devkit/schematics): add listing
schematics to collection interface
---
packages/angular_devkit/schematics/bin/schematics.ts | 2 +-
.../schematics/src/engine/collection.ts | 4 ++++
.../angular_devkit/schematics/src/engine/engine.ts | 4 ++++
.../angular_devkit/schematics/src/engine/interface.ts | 4 +++-
.../angular_devkit/schematics/src/engine/schematic.ts | 2 +-
.../schematics/tools/fallback-engine-host.ts | 11 +++++++++++
.../schematics/tools/file-system-engine-host-base.ts | 7 +++----
7 files changed, 27 insertions(+), 7 deletions(-)
diff --git a/packages/angular_devkit/schematics/bin/schematics.ts b/packages/angular_devkit/schematics/bin/schematics.ts
index 4e8b04d328..ed0ad9047a 100644
--- a/packages/angular_devkit/schematics/bin/schematics.ts
+++ b/packages/angular_devkit/schematics/bin/schematics.ts
@@ -154,7 +154,7 @@ if (collection === null) {
/** If the user wants to list schematics, we simply show all the schematic names. */
if (argv['list-schematics']) {
- logger.info(engineHost.listSchematics(collection).join('\n'));
+ logger.info(engine.listSchematicNames(collection).join('\n'));
process.exit(0);
throw 0; // TypeScript doesn't know that process.exit() never returns.
}
diff --git a/packages/angular_devkit/schematics/src/engine/collection.ts b/packages/angular_devkit/schematics/src/engine/collection.ts
index f306c2ac71..1834644941 100644
--- a/packages/angular_devkit/schematics/src/engine/collection.ts
+++ b/packages/angular_devkit/schematics/src/engine/collection.ts
@@ -21,4 +21,8 @@ export class CollectionImpl {
return this._engine.createSchematic(name, this);
}
+
+ listSchematics(): string[] {
+ return this._engine.listSchematicNames(this);
+ }
}
diff --git a/packages/angular_devkit/schematics/src/engine/engine.ts b/packages/angular_devkit/schematics/src/engine/engine.ts
index 94377a3b2d..9e40b80a5a 100644
--- a/packages/angular_devkit/schematics/src/engine/engine.ts
+++ b/packages/angular_devkit/schematics/src/engine/engine.ts
@@ -119,6 +119,10 @@ export class SchematicEngine) {
+ return this._host.listSchematicNames(collection.description);
+ }
+
transformOptions(
schematic: Schematic, options: OptionT): ResultT {
return this._host.transformOptions(
diff --git a/packages/angular_devkit/schematics/src/engine/interface.ts b/packages/angular_devkit/schematics/src/engine/interface.ts
index 3c59900f03..1b21a5a6f8 100644
--- a/packages/angular_devkit/schematics/src/engine/interface.ts
+++ b/packages/angular_devkit/schematics/src/engine/interface.ts
@@ -39,6 +39,8 @@ export type SchematicDescription {
createCollectionDescription(name: string): CollectionDescription;
+ listSchematicNames(collection: CollectionDescription): string[];
+
createSchematicDescription(
name: string,
collection: CollectionDescription):
@@ -55,7 +57,6 @@ export interface EngineHost;
createSchematic(name: string): Schematic;
+ listSchematics(): string[];
}
diff --git a/packages/angular_devkit/schematics/src/engine/schematic.ts b/packages/angular_devkit/schematics/src/engine/schematic.ts
index 6328e90eee..a0ca25e322 100644
--- a/packages/angular_devkit/schematics/src/engine/schematic.ts
+++ b/packages/angular_devkit/schematics/src/engine/schematic.ts
@@ -35,7 +35,7 @@ export class SchematicImpl,
private _collection: Collection,
private _engine: Engine) {
- if (!_description.name.match(/^[-_.a-zA-Z0-9]+$/)) {
+ if (!_description.name.match(/^[-@/_.a-zA-Z0-9]+$/)) {
throw new InvalidSchematicsNameException(_description.name);
}
}
diff --git a/packages/angular_devkit/schematics/tools/fallback-engine-host.ts b/packages/angular_devkit/schematics/tools/fallback-engine-host.ts
index 95d5a9ff0c..b7eec28015 100644
--- a/packages/angular_devkit/schematics/tools/fallback-engine-host.ts
+++ b/packages/angular_devkit/schematics/tools/fallback-engine-host.ts
@@ -90,4 +90,15 @@ export class FallbackEngineHost implements EngineHost<{}, {}> {
): ResultT {
return this._transforms.reduce((acc: ResultT, t) => t(schematic, acc), options) as ResultT;
}
+
+ listSchematicNames(collection: CollectionDescription): string[] {
+ const allNames = new Set();
+ this._hosts.forEach(host => {
+ try {
+ host.listSchematicNames(collection.description).forEach(name => allNames.add(name));
+ } catch (_) {}
+ });
+
+ return [...allNames];
+ }
}
diff --git a/packages/angular_devkit/schematics/tools/file-system-engine-host-base.ts b/packages/angular_devkit/schematics/tools/file-system-engine-host-base.ts
index 1a21a4b1e7..037e45b750 100644
--- a/packages/angular_devkit/schematics/tools/file-system-engine-host-base.ts
+++ b/packages/angular_devkit/schematics/tools/file-system-engine-host-base.ts
@@ -16,7 +16,6 @@ import {
import { dirname, isAbsolute, join, resolve } from 'path';
import { Url } from 'url';
import {
- FileSystemCollection,
FileSystemCollectionDesc,
FileSystemCollectionDescription,
FileSystemSchematicContext,
@@ -89,10 +88,10 @@ export abstract class FileSystemEngineHostBase implements
private _transforms: OptionTransform