@@ -77,6 +77,7 @@ You can read more about issue submission guidelines here: https://github.com/ang
**Anything else relevant?**
+
diff --git a/.github/ISSUE_TEMPLATE/2-feature-request.md b/.github/ISSUE_TEMPLATE/2-feature-request.md
index 9210f5135779..f129bc107360 100644
--- a/.github/ISSUE_TEMPLATE/2-feature-request.md
+++ b/.github/ISSUE_TEMPLATE/2-feature-request.md
@@ -1,8 +1,8 @@
---
name: "\U0001F680 Feature request"
about: Suggest a feature for Angular CLI
-
---
+
-
# 🚀 Feature request
-
### Command (mark with an `x`)
+
+
- [ ] new
- [ ] build
- [ ] serve
@@ -36,12 +36,13 @@ Existing issues often contain information about workarounds, resolution, or prog
- [ ] doc
### Description
- A clear and concise description of the problem or missing capability...
+ A clear and concise description of the problem or missing capability...
### Describe the solution you'd like
- If you have a solution in mind, please describe it.
+ If you have a solution in mind, please describe it.
### Describe alternatives you've considered
+
Have you considered any alternative solutions or workarounds?
diff --git a/.github/ISSUE_TEMPLATE/3-docs-bug.md b/.github/ISSUE_TEMPLATE/3-docs-bug.md
index 7cd9ec28753a..7270bb2a963f 100644
--- a/.github/ISSUE_TEMPLATE/3-docs-bug.md
+++ b/.github/ISSUE_TEMPLATE/3-docs-bug.md
@@ -1,7 +1,6 @@
---
-name: "📚 Docs or angular.io issue report"
+name: '📚 Docs or angular.io issue report'
about: Report an issue in Angular's documentation or angular.io application
-
---
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
diff --git a/.github/ISSUE_TEMPLATE/4-security-issue-disclosure.md b/.github/ISSUE_TEMPLATE/4-security-issue-disclosure.md
index 70736318d2a3..a5c2c1707fda 100644
--- a/.github/ISSUE_TEMPLATE/4-security-issue-disclosure.md
+++ b/.github/ISSUE_TEMPLATE/4-security-issue-disclosure.md
@@ -1,7 +1,6 @@
---
name: ⚠️ Security issue disclosure
about: Report a security issue in Angular Framework, Material, or CLI
-
---
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
diff --git a/.github/ISSUE_TEMPLATE/5-support-request.md b/.github/ISSUE_TEMPLATE/5-support-request.md
index cdbd2e887db7..509f8d4797bc 100644
--- a/.github/ISSUE_TEMPLATE/5-support-request.md
+++ b/.github/ISSUE_TEMPLATE/5-support-request.md
@@ -1,14 +1,13 @@
---
-name: "❓ Support request"
+name: '❓ Support request'
about: Questions and requests for support
-
---
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
Please do not file questions or support requests on the GitHub issues tracker.
-You can get your questions answered using other communication channels. Please see:
+You can get your questions answered using other communication channels. Please see:
https://github.com/angular/angular-cli/blob/master/CONTRIBUTING.md#question
Thank you!
diff --git a/.github/ISSUE_TEMPLATE/6-angular-framework.md b/.github/ISSUE_TEMPLATE/6-angular-framework.md
index 8a689c55de35..8ab207b2389f 100644
--- a/.github/ISSUE_TEMPLATE/6-angular-framework.md
+++ b/.github/ISSUE_TEMPLATE/6-angular-framework.md
@@ -1,7 +1,6 @@
---
-name: "⚡Angular Framework"
+name: '⚡Angular Framework'
about: Issues and feature requests for Angular Framework
-
---
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
diff --git a/.github/ISSUE_TEMPLATE/7-angular-material.md b/.github/ISSUE_TEMPLATE/7-angular-material.md
index fab3fe5b67c8..10b27db5c86f 100644
--- a/.github/ISSUE_TEMPLATE/7-angular-material.md
+++ b/.github/ISSUE_TEMPLATE/7-angular-material.md
@@ -1,7 +1,6 @@
---
name: "\U0001F48E Angular Material"
about: Issues and feature requests for Angular Material
-
---
🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑
diff --git a/.github/SAVED_REPLIES.md b/.github/SAVED_REPLIES.md
index 29e19832903c..466b8ad5ee52 100644
--- a/.github/SAVED_REPLIES.md
+++ b/.github/SAVED_REPLIES.md
@@ -4,52 +4,52 @@ The following are canned responses that the Angular CLI team should use to close
Since GitHub currently doesn't allow us to have a repository-wide or organization-wide list of [saved replies](https://help.github.com/articles/working-with-saved-replies/), these replies need to be maintained by individual team members. Since the responses can be modified in the future, all responses are versioned to simplify the process of keeping the responses up to date.
-
## Angular CLI: Already Fixed (v1)
+
```
Thanks for reporting this issue. Luckily, it has already been fixed in one of the recent releases. Please update to the most recent version to resolve the problem.
If the problem persists in your application after upgrading, please open a new issue, provide a simple repository reproducing the problem, and describe the difference between the expected and current behavior. You can use `ng new repro-app` to create a new project where you reproduce the problem.
```
-
## Angular CLI: Don't Understand (v1)
+
```
I'm sorry, but we don't understand the problem you are reporting.
If the problem persists, please open a new issue, provide a simple repository reproducing the problem, and describe the difference between the expected and current behavior. You can use `ng new repro-app` to create a new project where you reproduce the problem.
```
-
## Angular CLI: Duplicate (v1.1)
+
```
Thanks for reporting this issue. However, this issue is a duplicate of #. Please subscribe to that issue for future updates.
```
-
## Angular CLI: Insufficient Information Provided (v1)
+
```
Thanks for reporting this issue. However, you didn't provide sufficient information for us to understand and reproduce the problem. Please check out [our submission guidelines](https://github.com/angular/angular-cli/blob/master/CONTRIBUTING.md#-submitting-an-issue) to understand why we can't act on issues that are lacking important information.
If the problem persists, please file a new issue and ensure you provide all of the required information when filling out the issue template.
```
-
## Angular CLI: NPM install issue (v1)
+
```
This seems like a problem with your node/npm and not with Angular CLI.
Please have a look at the [fixing npm permissions page](https://docs.npmjs.com/getting-started/fixing-npm-permissions), [common errors page](https://docs.npmjs.com/troubleshooting/common-errors), [npm issue tracker](https://github.com/npm/npm/issues), or open a new issue if the problem you are experiencing isn't known.
```
-
## Angular CLI: Issue Outside of Angular CLI (v1.1)
+
```
I'm sorry, but this issue is not caused by Angular CLI. Please contact the author(s) of the project or file an issue on their issue tracker.
```
-
## Angular CLI: Non-reproducible (v1)
+
```
I'm sorry, but we can't reproduce the problem following the instructions you provided.
Remember that we have a large number of issues to resolve, and have only a limited amount of time to reproduce your issue.
@@ -60,24 +60,24 @@ If the problem persists, please open a new issue following [our submission guide
A good way to make a minimal repro is to create a new app via `ng new repro-app` and adding the minimum possible code to show the problem. Then you can push this repository to github and link it here.
```
-
## Angular CLI: Obsolete (v1)
+
```
Thanks for reporting this issue. This issue is now obsolete due to changes in the recent releases. Please update to the most recent Angular CLI version.
If the problem persists after upgrading, please open a new issue, provide a simple repository reproducing the problem, and describe the difference between the expected and current behavior.
```
-
## Angular CLI: Support Request (v1)
+
```
Hello, we reviewed this issue and determined that it doesn't fall into the bug report or feature request category. This issue tracker is not suitable for support requests, please repost your issue on [StackOverflow](http://stackoverflow.com/) using tag `angular-cli`.
If you are wondering why we don't resolve support issues via the issue tracker, please [check out this explanation](https://github.com/angular/angular-cli/blob/master/CONTRIBUTING.md#-got-a-question-or-problem).
```
-
## Angular CLI: Static Analysis errors (v1)
+
```
Hello, errors like `Error encountered resolving symbol values statically` mean that there has been some problem in statically analyzing your app.
@@ -93,6 +93,7 @@ In that case, please open an issue in https://github.com/angular/angular.
```
## Angular CLI: Lockfiles (v1)
+
```
I'd like to remind everyone that **you only have reproducible installs if you use a lockfile**. Both [NPM v5+](https://docs.npmjs.com/files/package-locks) and [Yarn](https://yarnpkg.com/lang/en/docs/yarn-lock/) support lockfiles. If your CI works one day but not the next and you did not change your code or `package.json`, it is likely because one of your dependencies had a bad release and you did not have a lockfile.
diff --git a/.github/angular-robot.yml b/.github/angular-robot.yml
index 546301497bd3..e4a402d300b3 100644
--- a/.github/angular-robot.yml
+++ b/.github/angular-robot.yml
@@ -7,11 +7,11 @@ merge:
# set to true to disable
disabled: false
# the name of the status
- context: "ci/angular: merge status"
+ context: 'ci/angular: merge status'
# text to show when all checks pass
- successText: "All checks passed!"
+ successText: 'All checks passed!'
# text to show when some checks are failing
- failureText: "The following checks are failing:"
+ failureText: 'The following checks are failing:'
# comment that will be added to a PR when there is a conflict, leave empty or set to false to disable
mergeConflictComment: >-
@@ -20,7 +20,7 @@ merge:
Please help to unblock it by resolving these conflicts. Thanks!
# label to monitor
- mergeLabel: "action: merge"
+ mergeLabel: 'action: merge'
# list of checks that will determine if the merge label can be added
checks:
@@ -30,28 +30,28 @@ merge:
requireReviews: true
# list of labels that a PR needs to have, checked with a regexp (e.g. "target:" will work for the label "target: major")
requiredLabels:
- - "target: *"
- - "cla: yes"
+ - 'target: *'
+ - 'cla: yes'
# list of labels that a PR shouldn't have, checked after the required labels with a regexp
forbiddenLabels:
- - "action: cleanup"
- - "action: review"
- - "PR state: blocked"
- - "cla: no"
+ - 'action: cleanup'
+ - 'action: review'
+ - 'PR state: blocked'
+ - 'cla: no'
# list of PR statuses that need to be successful
requiredStatuses:
- - "ci/circleci: build"
- - "ci/circleci: setup"
- - "ci/circleci: lint"
- - "ci/circleci: validate"
- - "ci/circleci: test"
- - "ci/circleci: e2e-cli-win"
- - "ci/circleci: e2e-cli"
- - "ci/circleci: test-browsers"
- - "ci/angular: size"
- - "cla/google"
+ - 'ci/circleci: build'
+ - 'ci/circleci: setup'
+ - 'ci/circleci: lint'
+ - 'ci/circleci: validate'
+ - 'ci/circleci: test'
+ - 'ci/circleci: e2e-cli-win'
+ - 'ci/circleci: e2e-cli'
+ - 'ci/circleci: test-browsers'
+ - 'ci/angular: size'
+ - 'cla/google'
# the comment that will be added when the merge label is added despite failing checks, leave empty or set to false to disable
# {{MERGE_LABEL}} will be replaced by the value of the mergeLabel option
@@ -78,30 +78,24 @@ triage:
defaultMilestone: 12,
# arrays of labels that determine if an issue has been triaged by the caretaker
l1TriageLabels:
- -
- - "comp: *"
+ - - 'comp: *'
# arrays of labels that determine if an issue has been fully triaged
l2TriageLabels:
- -
- - "type: bug/fix"
- - "severity*"
- - "freq*"
- - "comp: *"
- -
- - "type: feature"
- - "comp: *"
- -
- - "type: refactor"
- - "comp: *"
- -
- - "type: RFC / Discussion / question"
- - "comp: *"
- -
- - "type: docs"
- - "comp: *"
+ - - 'type: bug/fix'
+ - 'severity*'
+ - 'freq*'
+ - 'comp: *'
+ - - 'type: feature'
+ - 'comp: *'
+ - - 'type: refactor'
+ - 'comp: *'
+ - - 'type: RFC / Discussion / question'
+ - 'comp: *'
+ - - 'type: docs'
+ - 'comp: *'
# Size checking
size:
- circleCiStatusName: "ci/circleci: e2e-cli"
+ circleCiStatusName: 'ci/circleci: e2e-cli'
maxSizeIncrease: 10000
comment: false
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 6499bb344192..cc8aa2b2c506 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -1,16 +1,16 @@
version: 2
updates:
- - package-ecosystem: "npm"
- directory: "/"
+ - package-ecosystem: 'npm'
+ directory: '/'
schedule:
- interval: "daily"
+ interval: 'daily'
commit-message:
- prefix: "build"
+ prefix: 'build'
labels:
- - "comp: build & ci"
- - "target: patch"
- - "action: merge"
+ - 'comp: build & ci'
+ - 'target: patch'
+ - 'action: merge'
# Disable version updates
# This does not affect security updates
open-pull-requests-limit: 0
diff --git a/.monorepo.json b/.monorepo.json
index cab101ad56e0..0cf9710d62e8 100644
--- a/.monorepo.json
+++ b/.monorepo.json
@@ -41,12 +41,9 @@
"Angular CLI": "http://github.com/angular/angular-cli"
},
"packages": {
- "@_/benchmark": {
- },
- "@_/builders": {
- },
- "devkit": {
- },
+ "@_/benchmark": {},
+ "@_/builders": {},
+ "devkit": {},
"@angular/cli": {
"name": "Angular CLI",
"section": "Tooling",
diff --git a/.ng-dev/commit-message.ts b/.ng-dev/commit-message.ts
index 06bd8eb244fc..98b1f02495fd 100644
--- a/.ng-dev/commit-message.ts
+++ b/.ng-dev/commit-message.ts
@@ -1,5 +1,9 @@
// tslint:disable-next-line: no-implicit-dependencies
-import { COMMIT_TYPES, CommitMessageConfig, ScopeRequirement } from '@angular/dev-infra-private/commit-message/config';
+import {
+ COMMIT_TYPES,
+ CommitMessageConfig,
+ ScopeRequirement,
+} from '@angular/dev-infra-private/commit-message/config';
import { packages } from '../lib/packages';
/**
@@ -16,7 +20,5 @@ export const commitMessage: CommitMessageConfig = {
maxLineLength: Infinity,
minBodyLength: 0,
minBodyLengthTypeExcludes: ['docs'],
- scopes: [
- ...Object.keys(packages),
- ],
+ scopes: [...Object.keys(packages)],
};
diff --git a/.ng-dev/format.ts b/.ng-dev/format.ts
index 39479cbdbe66..3480c241199b 100644
--- a/.ng-dev/format.ts
+++ b/.ng-dev/format.ts
@@ -5,6 +5,6 @@ import { FormatConfig } from '@angular/dev-infra-private/format/config';
*/
export const format: FormatConfig = {
'prettier': {
- matchers: ['**/*.{ts,js,json,yml,yaml,md}']
+ matchers: ['**/*.{ts,js,json,yml,yaml,md}'],
},
-}
+};
diff --git a/.ng-dev/merge.ts b/.ng-dev/merge.ts
index eb41a469caad..24dde02bac87 100644
--- a/.ng-dev/merge.ts
+++ b/.ng-dev/merge.ts
@@ -7,13 +7,11 @@ import { release } from './release';
* Configuration for the merge tool in `ng-dev`. This sets up the labels which
* are respected by the merge script (e.g. the target labels).
*/
-export const merge: DevInfraMergeConfig['merge'] = async api => {
+export const merge: DevInfraMergeConfig['merge'] = async (api) => {
return {
githubApiMerge: {
default: 'rebase',
- labels: [
- {pattern: 'squash commits', method: 'squash'},
- ],
+ labels: [{ pattern: 'squash commits', method: 'squash' }],
},
claSignedLabel: 'cla: yes',
mergeReadyLabel: /^action: merge(-assistance)?/,
diff --git a/bin/README.md b/bin/README.md
index 6f3d6c17fbd2..8995780c706b 100644
--- a/bin/README.md
+++ b/bin/README.md
@@ -6,11 +6,11 @@ Each file in this directory follows this pattern:
1. JavaScript only.
1. Requires `../lib/bootstrap-local.js` to bootstrap TypeScript and Node integration.
-1. Requires `../lib/packages` and use the package metadata to find the binary script for the
-package the script is bootstrapping.
+1. Requires `../lib/packages` and use the package metadata to find the binary script for the
+ package the script is bootstrapping.
1. Call out main, or simply require the file if it has no export.
-`devkit-admin` does not follow this pattern as it needs to setup logging and run some localized
+`devkit-admin` does not follow this pattern as it needs to setup logging and run some localized
logic.
In order to add a new script, you should make sure it's in the root `package.json`, so people
diff --git a/docs/README.md b/docs/README.md
index a8f139c01847..1aa9fc8f9262 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,6 +1,6 @@
# `/docs` Folder
-This folder is used for all documentation. It contains a number of subfolders with short
+This folder is used for all documentation. It contains a number of subfolders with short
descriptions here.
## `/docs/design`
diff --git a/docs/design/analytics.md b/docs/design/analytics.md
index 1658f5d4b91a..88fcd37b8247 100644
--- a/docs/design/analytics.md
+++ b/docs/design/analytics.md
@@ -1,20 +1,23 @@
# Usage Metrics Gathering
+
This document list exactly what is gathered and how.
Any change to analytics should most probably include a change to this document.
# Pageview
+
Each command creates a pageview with the path `/command/${commandName}/${subcommandName}`. IE.
`ng generate component my-component --dryRun` would create a page view with the path
`/command/generate/@schematics_angular/component`.
We use page views to keep track of sessions more effectively, and to tag events to a page.
-Project names and target names will be removed.
+Project names and target names will be removed.
The command `ng run some-project:lint:some-configuration` will create a page view with the path
`/command/run`.
# Dimensions
+
Google Analytics Custom Dimensions are used to track system values and flag values. These
dimensions are aggregated automatically on the backend.
@@ -37,6 +40,7 @@ PROJECT NAME TO BUILD OR A MODULE NAME.**
Note: There's a limit of 20 custom dimensions.
### List Of All Dimensions
+
| Id | Flag | Type |
|:---:|:---|:---|
@@ -65,6 +69,7 @@ Note: There's a limit of 20 custom dimensions.
# Metrics
### List of All Metrics
+
| Id | Flag | Type |
|:---:|:---|:---|
@@ -86,12 +91,14 @@ Note: There's a limit of 20 custom dimensions.
# Operating System and Node Version
+
A User Agent string is built to "fool" Google Analytics into reading the Operating System and
version fields from it. The base dimensions are used for those.
Node version is our App ID, but a dimension is also used to get the numeric MAJOR.MINOR of node.
# Debugging
+
Using `DEBUG=universal-analytics` will report all calls to the universal-analytics library,
including queuing events and sending them to the server.
@@ -105,6 +112,7 @@ Using `DEBUG=ng:analytics:log` will show what we actually send to GA.
See [the `debug` NPM library](https://www.npmjs.com/package/debug) for more information.
# Disabling Usage Analytics
+
There are 2 ways of disabling usage analytics:
1. using `ng analytics off` (or changing the global configuration file yourself). This is the same
@@ -115,9 +123,10 @@ There are 2 ways of disabling usage analytics:
below).
# CI
+
A special user named `ci` is used for analytics for tracking CI information. This is a convention
and is in no way enforced.
Running on CI by default will disable analytics (because of a lack of TTY on STDIN/OUT). It can be
manually enabled using either a global configuration with a value of `ci`, or using the
-`NG_CLI_ANALYTICS=ci` environment variable.
+`NG_CLI_ANALYTICS=ci` environment variable.
diff --git a/docs/design/build-system.md b/docs/design/build-system.md
index 93df444fa2ce..fe730f3f9fdd 100644
--- a/docs/design/build-system.md
+++ b/docs/design/build-system.md
@@ -8,6 +8,7 @@ This document describes a top level view of the functionality in `@angular-devki
Deprecated or soon to be removed features are not described here.
In broad strokes the main areas are:
+
- loading and processing sources
- code splitting
- production optimizations
@@ -16,7 +17,6 @@ In broad strokes the main areas are:
Many tools are used in this process, and most of these steps happen within a [Webpack](https://webpack.js.org/) build.
We maintain a number of Webpack-centric plugins in this repository, some of these are public but most are private since they are very specific to our setup.
-
## Overview diagram
Below is a diagram of processing sources go through.
@@ -31,7 +31,6 @@ Relative paths, such as `./raw-css-loader.ts`, refer to internal plugins, while
Sources for Angular CLI browser apps are comprised of TypeScript files, style sheets, assets, scripts, and third party dependencies.
A given build will load these sources from disk, process them, and bundle them together.
-
### TypeScript and Ahead-Of-Time Compilation
Angular builds rely heavily on TypeScript-specific functionality for [Ahead-of-Time template compilation](https://angular.io/guide/aot-compiler) (AOT).
@@ -58,20 +57,17 @@ Global stylesheets are injected into the `index.html` file, while component styl
The build system supports plain CSS stylesheets as well as the Sass, LESS and Stylus CSS pre-processors.
Stylesheet processing functionality is provided by `sass-loader`, `less-loader`, `stylus-loader`, `postcss-loader`, `postcss-import`, augmented in the build system by custom webpack plugins.
-
### Assets
Assets in the build system refer specifically to a list of files or directories that are meant to be copied verbatim as build artifacts.
These files are not processed and commonly include images, favicons, pdfs and other generic file types.
They are loaded into the compilation using `copy-webpack-plugin`.
-
### Scripts
Scripts in the build system refer specifically to JavaScript files that are meant to be loaded directly on `index.html` without being processed.
They are loaded into the compilation using a custom webpack plugin.
-
### Third party dependencies
Third party dependencies are mostly inside `node_modules` and are referenced via imports in source files.
@@ -89,7 +85,6 @@ Once the actual JavaScript file is determined, it is loaded into the compilation
This resolution strategy supports the [Angular Package Format](https://docs.google.com/document/d/1CZC2rcpxffTDfRDs6p1cfbmKNLA6x5O-NtkJglDaBVs/edit#heading=h.k0mh3o8u5hx).
-
## Code splitting
Code is automatically split into different files (or chunks, for js files) based on a few different triggers.
@@ -102,13 +97,11 @@ If multiple asynchronous chunks contain a reference to the same module, it is pl
There is also a special chunk called `runtime` that contains the module loading logic and is loaded before the others.
-
## Optimizations
The build system contains optimizations aimed at improving the performance (for development builds) or the size of artifacts (for production builds).
These are often mutually exclusive and thus we cannot just default to always using them.
-
### Development optimizations
Development optimizations focus on reducing rebuild time on watched builds.
@@ -125,7 +118,6 @@ In development however, we skip the CSS extraction and leave it as JavaScript co
Watched builds split the processing load of TypeScript compilation between file emission on the main process and type checking on a forked process.
Large projects can also opt-out of AOT compilation for faster rebuilds.
-
### Production optimizations
Angular CLI focuses on enabling tree-shaking (removing unused modules) and dead code elimination (removing unused module code).
@@ -153,7 +145,6 @@ Modules that were concatenated when lazy modules are not present might not be co
Aside from tree-shaking, scripts and styles (as defined in the sources above) also undergo optimizations via [Terser](https://github.com/terser/terser) and [CleanCSS](https://github.com/jakubpawlowicz/clean-css) respectively.
-
## Post-processing steps
There are some steps that are meant to operate over whole applications and thus happen after the compilation finishes and outputs files.
@@ -161,29 +152,31 @@ The steps are described in the order in which they are executed during a build.
The execution order was determined based on the complexity of the step with a primary goal of minimizing the repetition of computationally expensive operations.
### Differential Loading
+
Differential loading is a strategy that allows your web application to support multiple browsers, but only load the necessary code that the browser needs.
When differential loading is enabled, the CLI generates two distinct variants of application bundles.
-* The first contains ES2015 syntax, takes advantage of built-in support in modern browsers, ships fewer polyfills, and results in a smaller total size.
-* The second contains code in the older ES5 syntax, along with all necessary polyfills for Angular to function. This results in a larger total size, but supports older browsers.
+- The first contains ES2015 syntax, takes advantage of built-in support in modern browsers, ships fewer polyfills, and results in a smaller total size.
+- The second contains code in the older ES5 syntax, along with all necessary polyfills for Angular to function. This results in a larger total size, but supports older browsers.
This process as designed has the advantage that only one full compilation of the application in ES2015 syntax is required.
This removes a large amount of otherwise unnecessary and duplicate processing such as module resolution and dead code elimination.
It also guarantees that the application is ES5 compliant including third-party code.
The two variants of application bundles are created by the following steps:
-1) A full build of the application is performed using an ES2015 output target.
-The application's global stylesheets, scripts, and assets are also processed during this step via the full build. These elements are reused for both of application variants.
-2) A copy of the JavaScript output application files are transformed (commonly referred to as down-leveled) to ES5 compatible syntax.
-ES2015+ syntax elements such as classes are converted into functionally equivalent ES5 code structures.
-3) An additional ES5-only polyfills file is generated that contains the required Angular polyfills for ES5-only browsers.
-4) A single index HTML file is created that references both application variants and is designed to only load the appropriate files for each browser.
+
+1. A full build of the application is performed using an ES2015 output target.
+ The application's global stylesheets, scripts, and assets are also processed during this step via the full build. These elements are reused for both of application variants.
+2. A copy of the JavaScript output application files are transformed (commonly referred to as down-leveled) to ES5 compatible syntax.
+ ES2015+ syntax elements such as classes are converted into functionally equivalent ES5 code structures.
+3. An additional ES5-only polyfills file is generated that contains the required Angular polyfills for ES5-only browsers.
+4. A single index HTML file is created that references both application variants and is designed to only load the appropriate files for each browser.
To support loading the file sets in the appropriate browsers, the HTML `script` element's `type` and `nomodule` attributes are leveraged.
Browsers will only load a script with a known type.
The ES2015 files are referenced using a type of `module` which is only supported on browsers that support ES2015+ code.
Since browsers that do not support ES2015+ code also do not support the `module` script type, these scripts are ignored for browsers that cannot parse and execute the ES2015 code.
Browsers that support the `module` script type also support the `nomodule` attribute.
-This attribute instructs a browser that supports module scripts to ignore the script with the attribute. There is one browser exception in this case: Safari 10.1.
+This attribute instructs a browser that supports module scripts to ignore the script with the attribute. There is one browser exception in this case: Safari 10.1.
This browser supports module scripts but does not support the `nomodule` attribute.
To support this case, a special polyfill script is included to provide a workaround for the browser.
This arrangement of script elements ensures that ES5-only browsers will only execute the ES5 script files and browsers that support ES2015+ will only execute the ES2015 script files.
@@ -198,4 +191,4 @@ This sort of localization produces one application for each locale, each in thei
The third and last post-processing step is the creation of a [service worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API).
A listing of final application files is taken, fingerprinted according to their content, and added to the service worker manifest.
-This must be the last step because it needs each application file to not be modified further.
\ No newline at end of file
+This must be the last step because it needs each application file to not be modified further.
diff --git a/docs/design/deployurl-basehref.md b/docs/design/deployurl-basehref.md
index 160975423aeb..71a804c073e4 100644
--- a/docs/design/deployurl-basehref.md
+++ b/docs/design/deployurl-basehref.md
@@ -1,18 +1,18 @@
-| | Deploy URL | Base HREF |
-|--|:--:|:--:|
-| Initial scripts (index.html) | ✅ 👍 | ✅ 👍 |
-| Initial stylesheets (index.html) | ✅ 👍 | ✅ 👍 |
-| Lazy scripts (routes/import()/etc.) | ✅ 👍 | ✅ 👍 |
-| Processed CSS resources (images/fonts/etc.) | ✅ 👍 | ✅ 👍 |
-| Relative template (HTML) assets | ❌ 👎 | ✅ 👍 |
-| Angular Router Default Base (APP_BASE_HREF) | ❌ | ✅ *1 |
-| Single reference in deployed Application | ❌ 👎 | ✅ 👍 |
-| Special resource logic within CLI | ✅ 👎 | ❌ 👍 |
-| Relative fetch/XMLHttpRequest | ❌ | ✅ |
+| | Deploy URL | Base HREF |
+| ------------------------------------------- | :--------: | :-------: |
+| Initial scripts (index.html) | ✅ 👍 | ✅ 👍 |
+| Initial stylesheets (index.html) | ✅ 👍 | ✅ 👍 |
+| Lazy scripts (routes/import()/etc.) | ✅ 👍 | ✅ 👍 |
+| Processed CSS resources (images/fonts/etc.) | ✅ 👍 | ✅ 👍 |
+| Relative template (HTML) assets | ❌ 👎 | ✅ 👍 |
+| Angular Router Default Base (APP_BASE_HREF) | ❌ | ✅ \*1 |
+| Single reference in deployed Application | ❌ 👎 | ✅ 👍 |
+| Special resource logic within CLI | ✅ 👎 | ❌ 👍 |
+| Relative fetch/XMLHttpRequest | ❌ | ✅ |
✅ - has/affects the item/trait
❌ - does not have/affect the item/trait
👍 - favorable behavior
👎 - unfavorable behavior
-*1 -- Users with more complicated setups may need to manually configure the `APP_BASE_HREF` token within the application. (e.g., application routing base is `/` but assets/scripts/etc. are at `/assets/`)
\ No newline at end of file
+\*1 -- Users with more complicated setups may need to manually configure the `APP_BASE_HREF` token within the application. (e.g., application routing base is `/` but assets/scripts/etc. are at `/assets/`)
diff --git a/docs/design/ngConfig.md b/docs/design/ngConfig.md
index bfb7377a992a..17be6f3a0070 100644
--- a/docs/design/ngConfig.md
+++ b/docs/design/ngConfig.md
@@ -4,11 +4,11 @@
Currently, a project scaffolded with the CLI has no way of specifying options and configurations affecting their projects. There are ways to affect the build (with the `angular-cli-build.js` file), but the following questions cannot be answered without actual project options:
-* Where in my directory is my karma.conf file?
-* What is my firebase database URL?
-* Where is my client code?
-* How can I use a different lazy-loading boundary prefix (or none at all)?
-* Any other backend I want to run prior to `ng serve`?
+- Where in my directory is my karma.conf file?
+- What is my firebase database URL?
+- Where is my client code?
+- How can I use a different lazy-loading boundary prefix (or none at all)?
+- Any other backend I want to run prior to `ng serve`?
# Proposed Solution
@@ -18,7 +18,6 @@ One solution would be to keep the data in the `package.json`. Unfortunately, the
Instead of polluting the package file, a `.angular-cli.json` file will be created that contains all the values. Access to that file will be allowed to the user if he knows the structure of the file (unknown keys will be kept but ignored), and it's easy to read and write.
-
## Fallback
There should be two `.angular-cli.json` files; one for the project and a general one. The general one should contain information that can be useful when scaffolding new apps, or informations about the user.
@@ -39,7 +38,7 @@ Every PR that would change the schema should include the update to the `d.ts`.
The new command `get` should be used to output values on the terminal. It takes a set of flags and an optional array of [paths](#path);
-* `--glob` or `-g`; the path follows a glob format, where `*` can be replaced by any amount of characters and `?` by a single character. This will output `name=value` for each values matched.
+- `--glob` or `-g`; the path follows a glob format, where `*` can be replaced by any amount of characters and `?` by a single character. This will output `name=value` for each values matched.
Otherwise, outputs the value of the path passed in. If multiple paths are passed in, they follow the format of `name=value`.
@@ -47,14 +46,14 @@ Otherwise, outputs the value of the path passed in. If multiple paths are passed
The new command `set` should be used to set values in the local configuration file. It takes a set of flags and an optional array of `[path](#path)=value`;
-* `--global`; sets the value in the global configuration.
-* `--remove`; removes the key (no value should be passed in).
+- `--global`; sets the value in the global configuration.
+- `--remove`; removes the key (no value should be passed in).
The schema needs to be taken into account when setting the value of the field;
-* If the field is a number, the string received from the command line is parsed. `NaN` throws an error.
-* If the field is an object, an error is thrown.
-* If the path is inside an object but the object hasn't been defined yet, sets the object with empty values (use the schema to create a valid object).
+- If the field is a number, the string received from the command line is parsed. `NaN` throws an error.
+- If the field is an object, an error is thrown.
+- If the path is inside an object but the object hasn't been defined yet, sets the object with empty values (use the schema to create a valid object).
#### Path
@@ -77,8 +76,12 @@ A simple API would return the TypeScript interface:
```typescript
class Config {
// ...
- get local(): ICliConfig { /* ... */ }
- get global(): ICliConfig { /* ... */ }
+ get local(): ICliConfig {
+ /* ... */
+ }
+ get global(): ICliConfig {
+ /* ... */
+ }
}
```
@@ -115,14 +118,14 @@ The following stands true:
```typescript
const config = new Config(/* ... */);
-console.log(config.local.key1.key2.value); // 0, even if it doesn't exist.
-console.log(config.local.key1.key2.value2); // 2, local overrides.
-console.log(config.local.key1.key2.value3); // 3.
-console.log(config.local.key1.key2.value4); // Schema's default value.
+console.log(config.local.key1.key2.value); // 0, even if it doesn't exist.
+console.log(config.local.key1.key2.value2); // 2, local overrides.
+console.log(config.local.key1.key2.value3); // 3.
+console.log(config.local.key1.key2.value4); // Schema's default value.
-console.log(config.global.key1.key2.value); // 0.
-console.log(config.global.key1.key2.value2); // 1, only global.
-console.log(config.global.key1.key2.value3); // Schema's default value.
+console.log(config.global.key1.key2.value); // 0.
+console.log(config.global.key1.key2.value2); // 1, only global.
+console.log(config.global.key1.key2.value3); // Schema's default value.
config.local.key1.key2.value = 1;
// Now the value is 1 inside the local. Global stays the same.
@@ -132,7 +135,7 @@ config.local.key1.key2.value3 = 5;
config.global.key1.key2.value4 = 99;
// The local config stays the same.
-console.log(config.local.key1.key2.value4); // 99, the global value.
+console.log(config.local.key1.key2.value4); // 99, the global value.
-config.save(); // Commits if there's a change to global and/or local.
+config.save(); // Commits if there's a change to global and/or local.
```
diff --git a/docs/design/third-party-libraries.md b/docs/design/third-party-libraries.md
index 0428efe62832..69ac6a7c8de5 100644
--- a/docs/design/third-party-libraries.md
+++ b/docs/design/third-party-libraries.md
@@ -10,18 +10,18 @@ with metadata that we expect. This document explores ways to improve on the proc
The following use cases need to be supported by `ng install`:
1. Support for _any_ thirdparties, ultimately falling back to running `npm install` only and
-doing nothing else, if necessary.
+ doing nothing else, if necessary.
1. Not a new package manager.
1. Metadata storage by thirdparties in `package.json`. This must be accessible by plugins for
-the build process or even when scaffolding.
+ the build process or even when scaffolding.
1. Proper configuration of SystemJs in the browser.
1. SystemJS configuration managed by the user needs to be kept separated from the autogenerated
-part.
+ part.
1. The build process right now is faulty because the `tmp/` directory used by Broccoli is
-inside the project. TypeScript when using `moduleResolution: "node"` can resolve the
-`node_modules` directory (since it's in an ancestor folder), which means that TypeScript
-compiles properly, but the build does not copy files used by TypeScript to `dist/`. We need
-to proper map the imports and move them to `tmp` before compiling, then to `dist/` properly.
+ inside the project. TypeScript when using `moduleResolution: "node"` can resolve the
+ `node_modules` directory (since it's in an ancestor folder), which means that TypeScript
+ compiles properly, but the build does not copy files used by TypeScript to `dist/`. We need
+ to proper map the imports and move them to `tmp` before compiling, then to `dist/` properly.
1. Potentially hook into scaffolding.
1. Potentially hook into the build.
1. Safe uninstall path.
@@ -34,27 +34,32 @@ Here's a few stories that should work right off:
$ ng new my-app && cd my-app/
$ ng install jquery
```
+
^(this makes jQuery available in the index)
```sh
$ ng install angularfire2
> Please specify your Firebase database URL [my-app.firebaseio.com]: _
```
+
^(makes firebase available and provided to the App)
```sh
$ ng install angularfire2 --dbUrl=my-firebase-db.example.com
```
+
^(skip prompts for values passed on the command line)
```sh
$ ng install angularfire2 --quiet
```
+
^(using `--quiet` to skip all prompts and use default values)
```sh
$ ng install less
```
+
^(now compiles CSS files with less for the appropriate extensions)
# Proposed Solution
@@ -80,13 +85,16 @@ The `install` task will perform the following subtasks:
These packages can be used to wrap libraries that we want to support but can't update
easily, like Jasmine or LESS.
+
1. **Install typings.** See the [Typings](#typings) section.
1. **Run `postinstall` scripts.**
# Proof of Concept
+
A proof of concept is being developed.
# Hooks
+
The third party library can implement hooks into the scaffolding, and the build system. The
CLI's tasks will look for the proper hooks prior to running and execute them.
@@ -96,12 +104,14 @@ checking for the `package['angular-cli']['hooks']['${hookName}']`. The hooks are
tree, there is no guarantee for the order of execution.
## Install Hooks
+
The only tricky part here is install hooks. The installed package should recursively call
its `(pre|post|)install` hooks only on packages that are newly installed. It should call
`(pre|post|)reinstall` on those who were already installed. A map of the currently installed
packages should be kept before performing `npm install`.
# appData
+
The `angular-cli` key in the generated app should be used for Angular CLI specific data.
This includes the CLI configuration itself, as well as third-parties library configuration.
@@ -137,11 +147,12 @@ in the data without user interaction. The special strings `${...}` can be used t
with special values in the default string values. The values are taken from the `package.json`.
We use a declarative style to enforce sensible defaults and make sure developers think about
-this. *In the case where developers want more complex interaction, they can use the
-install/uninstall hooks to prompt users.* But 3rd party libraries developers need to be aware
+this. _In the case where developers want more complex interaction, they can use the
+install/uninstall hooks to prompt users._ But 3rd party libraries developers need to be aware
that those hooks might not prompt users (no STDIN) and throw an error.
# Providers
+
Adding Angular providers to the app should be seamless. The install process will create a
`providers.js` from all the providers contained in all the dependencies. The User can disclude
providers it doesn't want.
@@ -163,15 +174,18 @@ ng providers database angularfirebase2
Or, alternatively, the user can add its own providers and dependencies to its components.
# Dependencies
+
Because dependencies are handled by `npm`, we don't have to handle it.
# Typings
+
Typings should be added, but failure to find typings should not be a failure of installation. The
user might still want to install custom typings himself in the worst case.
The `typings` package can be used to install/verify that typings exist. If the typings do not exist natively, we should tell the user to install the ambient version if he wants to.
# Index.html
+
We do not touch the `index.html` file during the installation task. The default page should
link to a SystemJS configuration file that is auto generated by the CLI and not user
configurable (see SystemJS below). If the user install a third party library, like jQuery, and
@@ -181,6 +195,7 @@ The `index.html` also includes a section to configure SystemJS that can be manag
This is separate from the generated code.
# SystemJS
+
It is important that SystemJS works without any modifications by the user. It is also important
to leave the liberty to the user to change the SystemJS configuration so that it fits their needs.
@@ -190,6 +205,7 @@ being pulled from a CDN in production. During the `ng build` process for product
SystemJS configuration script will be rebuilt to fetch from the CDN.
# Upgrade Strategy
+
The upgrade process simply uses NPM. If new appData is added, it should be added manually using
a migration hook for `postinstall`.
diff --git a/docs/process/bazel.md b/docs/process/bazel.md
index fb540e7b61ea..fe136061fe25 100644
--- a/docs/process/bazel.md
+++ b/docs/process/bazel.md
@@ -52,7 +52,6 @@ Then you will find the intermediate test files in `bazel-out/k8-fastbuild/bin`,
Tests that are sharded, via the `shard_count` attribute, can fail if you reduce the number of tests or focus only a few.
This will cause some shards to execute 0 tests, which makes the exit with an error code.
-
Tests that are marked as flaky, via the `flaky` attribute, will repeat when they fail.
This will cause any focused test to be repeated multiple time, since the presence of focused tests
causes jasmine to exit with a non-zero exit code.
@@ -67,4 +66,3 @@ with the yarn workspace symlinks in node_modules.
1. Yarn workspaces is not compatible with Bazel-managed deps
[(#12736)](https://github.com/angular/angular-cli/issues/12736)
-
diff --git a/docs/process/release.md b/docs/process/release.md
index 1be2420ecec3..f9dd8b3f40dc 100644
--- a/docs/process/release.md
+++ b/docs/process/release.md
@@ -2,9 +2,10 @@
1. Clone the Angular-CLI repo. A local copy works just fine.
1. Create an upstream remote:
- ```bash
- $ git remote add upstream https://github.com/angular/angular-cli.git
- ```
+
+```bash
+$ git remote add upstream https://github.com/angular/angular-cli.git
+```
# Caretaker
@@ -16,21 +17,22 @@ Each shift consists of two caretakers. The primary caretaker is responsible for
merging PRs to master and patch whereas the secondary caretaker is responsible
for the release. Primary-secondary pairs are as follows:
-Primary | Secondary
---------|----------
-Alan | Doug
-Charles | Keen
-Filipe | Joey
+| Primary | Secondary |
+| ------- | --------- |
+| Alan | Doug |
+| Charles | Keen |
+| Filipe | Joey |
## Merging PRs
The list of PRs which are currently ready to merge (approved with passing status checks) can
be found with [this search](https://github.com/angular/angular-cli/pulls?q=is%3Apr+is%3Aopen+label%3A%22PR+action%3A+merge%22+-is%3Adraft).
This list should be checked daily and any ready PRs should be merged. For each PR, check the
-`target` label to understand where it should be merged to. You can find which branches a specific
+`target` label to understand where it should be merged to. You can find which branches a specific
PR will be merged into with the `yarn ng-dev pr check-target-branches ` command.
When ready to merge a PR, run the following command:
+
```
yarn ng-dev pr merge
```
@@ -85,7 +87,7 @@ git push upstream --follow-tags
**This can ONLY be done by a Google employee.**
Log in to the Wombat publishing service using your own github and google.com
-account to publish. This enforces the login is done using 2Factor auth.
+account to publish. This enforces the login is done using 2Factor auth.
Run `npm login --registry https://wombat-dressing-room.appspot.com`:
@@ -107,12 +109,14 @@ For the first release of a major version, follow the instructions in
[Publishing a Major Version](#publishing-a-major-version) section.
For non-major release, check out the patch branch (e.g. `9.1.x`), then run:
+
```bash
rm -rf node_modules/ && yarn install --frozen-lockfile # Reload dependencies
yarn admin publish --tag latest
```
If also publishing a prerelease, check out `master`, then run:
+
```bash
rm -rf node_modules/ && yarn install --frozen-lockfile # Reload dependencies
yarn admin publish --tag next
@@ -153,7 +157,7 @@ using the `--githubToken` flag. You just then have to confirm the draft.
**For each released version**:
-Update `version` in root [`package.json`](/package.json#L3) to the *next* release version.
+Update `version` in root [`package.json`](/package.json#L3) to the _next_ release version.
```sh
git checkout -b release-bump-vXX
diff --git a/docs/specifications/schematic-prompts.md b/docs/specifications/schematic-prompts.md
index 08092ef20235..a7c83e6e6d94 100644
--- a/docs/specifications/schematic-prompts.md
+++ b/docs/specifications/schematic-prompts.md
@@ -1,8 +1,8 @@
# Schematic Prompts
-Schematic prompts provide the ability to introduce user interaction into the schematic execution. The schematic runtime supports the ability to allow schematic options to be configured to display a customizable question to the user and then use the response as the value for the option. These prompts are displayed before the execution of the schematic. This allows users direct the operation of the schematic without requiring indepth knowledge of the full spectrum of options available to the user.
+Schematic prompts provide the ability to introduce user interaction into the schematic execution. The schematic runtime supports the ability to allow schematic options to be configured to display a customizable question to the user and then use the response as the value for the option. These prompts are displayed before the execution of the schematic. This allows users direct the operation of the schematic without requiring indepth knowledge of the full spectrum of options available to the user.
-To enable this capability, the JSON Schema used to define the schematic's options supports extensions to allow the declarative definition of the prompts and their respective behavior. No additional logic or changes are required to the JavaScript for a schematic to support the prompts.
+To enable this capability, the JSON Schema used to define the schematic's options supports extensions to allow the declarative definition of the prompts and their respective behavior. No additional logic or changes are required to the JavaScript for a schematic to support the prompts.
## Basic Usage
@@ -10,67 +10,69 @@ To illustrate the addition of a prompt to an existing schematic the following ex
```json
{
- "properties": {
- "name": {
- "type": "string",
- "minLength": 1,
- "default": "world"
- },
- "useColor": {
- "type": "boolean"
- }
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "default": "world"
+ },
+ "useColor": {
+ "type": "boolean"
}
+ }
}
```
-Suppose it would be preferred if the user was asked for their name. This can be accomplished by augmenting the `name` property definition with an `x-prompt` field.
+Suppose it would be preferred if the user was asked for their name. This can be accomplished by augmenting the `name` property definition with an `x-prompt` field.
+
```json
"x-prompt": "What is your name?"
```
-In most cases, only the text of the prompt is required. To minimize the amount of necessary configuration, the above _shorthand_ form is supported and will typically be all that is required. Full details regarding the _longhand_ form can be found in the **Configuration Reference** section.
-Adding a prompt to allow the user to decided whether the schematic will use color when executing its hello action is also very similar. The schema with both prompts would be as follows:
+In most cases, only the text of the prompt is required. To minimize the amount of necessary configuration, the above _shorthand_ form is supported and will typically be all that is required. Full details regarding the _longhand_ form can be found in the **Configuration Reference** section.
+
+Adding a prompt to allow the user to decided whether the schematic will use color when executing its hello action is also very similar. The schema with both prompts would be as follows:
+
```json
{
- "properties": {
- "name": {
- "type": "string",
- "minLength": 1,
- "default": "world",
- "x-prompt": "What is your name?"
- },
- "useColor": {
- "type": "boolean",
- "x-prompt": "Would you like the response in color?"
- }
+ "properties": {
+ "name": {
+ "type": "string",
+ "minLength": 1,
+ "default": "world",
+ "x-prompt": "What is your name?"
+ },
+ "useColor": {
+ "type": "boolean",
+ "x-prompt": "Would you like the response in color?"
}
+ }
}
```
Prompts have several different types which provide the ability to display an input method that best represents the schematic option's potential values.
-* `confirmation` - A **yes** or **no** question; ideal for boolean options
-* `input` - textual input; ideal for string or number options
-* `list` - a predefined set of items which may be selected
+- `confirmation` - A **yes** or **no** question; ideal for boolean options
+- `input` - textual input; ideal for string or number options
+- `list` - a predefined set of items which may be selected
-When using the _shorthand_ form, the most appropriate type will automatically be selected based on the property's schema. In the example, the `name` prompt will use an `input` type because it it is a `string` property. The `useColor` prompt will use a `confirmation` type because it is a boolean property with `yes` corresponding to `true` and `no` corresponding to `false`.
+When using the _shorthand_ form, the most appropriate type will automatically be selected based on the property's schema. In the example, the `name` prompt will use an `input` type because it it is a `string` property. The `useColor` prompt will use a `confirmation` type because it is a boolean property with `yes` corresponding to `true` and `no` corresponding to `false`.
-It is also important that the response from the user conforms to the contraints of the property. By specifying constraints using the JSON schema, the prompt runtime will automatically validate the response provided by the user. If the value is not acceptable, the user will be asked to enter a new value. This ensures that any values passed to the schematic will meet the expectations of the schematic's implementation and removes the need to add additional checks within the schematic's code.
+It is also important that the response from the user conforms to the contraints of the property. By specifying constraints using the JSON schema, the prompt runtime will automatically validate the response provided by the user. If the value is not acceptable, the user will be asked to enter a new value. This ensures that any values passed to the schematic will meet the expectations of the schematic's implementation and removes the need to add additional checks within the schematic's code.
-## Configuration Reference
+## Configuration Reference
-The `x-prompt` field supports two alternatives to enable a prompt for a schematic option. A shorthand form when additional customization is not required and a longhand form providing the ability for more control over the prompt. All user responses are validated against the property's schema. For example, string type properties can use a minimum length or regular expression constraint to control the allowed values. In the event the response fails validation, the user will be asked to enter a new value.
+The `x-prompt` field supports two alternatives to enable a prompt for a schematic option. A shorthand form when additional customization is not required and a longhand form providing the ability for more control over the prompt. All user responses are validated against the property's schema. For example, string type properties can use a minimum length or regular expression constraint to control the allowed values. In the event the response fails validation, the user will be asked to enter a new value.
### Longhand Form
-In the this form, the `x-prompt` field is an object with subfields that can be used to customize the behavior of the prompt. Note that some fields only apply to specific prompt types.
-
-| Field | Data Value | Default |
-|-|-|-|
-| `type` | `confirmation`, `input`, `list` | see shorthand section for details
-| `message` | string | N/A (required)
-| `items` | string and/or `label`/`value` object pair | only valid with type `list`
+In the this form, the `x-prompt` field is an object with subfields that can be used to customize the behavior of the prompt. Note that some fields only apply to specific prompt types.
+| Field | Data Value | Default |
+| --------- | ----------------------------------------- | --------------------------------- |
+| `type` | `confirmation`, `input`, `list` | see shorthand section for details |
+| `message` | string | N/A (required) |
+| `items` | string and/or `label`/`value` object pair | only valid with type `list` |
### Shorthand Form
@@ -78,44 +80,44 @@ In the this form, the `x-prompt` field is an object with subfields that can be u
For this usage, the type of the prompt is determined by the type of the containing property.
-| Property Schema | Prompt Type | Notes |
-|-|:-:|:-:|
-| `"type": "boolean"` | `confirmation` | |
-| `"type": "string"` | `input` | |
-| `"type": "number"` | `input` | only valid numbers accepted |
-| `"type": "integer"` | `input` | only valid numbers accepted |
-| `"enum": [...]` | `list` | enum members become list selections
+| Property Schema | Prompt Type | Notes |
+| ------------------- | :------------: | :---------------------------------: |
+| `"type": "boolean"` | `confirmation` | |
+| `"type": "string"` | `input` | |
+| `"type": "number"` | `input` | only valid numbers accepted |
+| `"type": "integer"` | `input` | only valid numbers accepted |
+| `"enum": [...]` | `list` | enum members become list selections |
### `x-prompt` Schema
```json
{
- "oneOf": [
- { "type": "string" },
- {
- "type": "object",
- "properties": {
- "type": { "type": "string" },
- "message": { "type": "string" },
- "items": {
- "type": "array",
- "items": {
- "oneOf": [
- { "type": "string" },
- {
- "type": "object",
- "properties": {
- "label": { "type": "string" },
- "value": { }
- },
- "required": [ "value" ]
- }
- ]
- }
- }
- },
- "required": [ "message" ]
+ "oneOf": [
+ { "type": "string" },
+ {
+ "type": "object",
+ "properties": {
+ "type": { "type": "string" },
+ "message": { "type": "string" },
+ "items": {
+ "type": "array",
+ "items": {
+ "oneOf": [
+ { "type": "string" },
+ {
+ "type": "object",
+ "properties": {
+ "label": { "type": "string" },
+ "value": {}
+ },
+ "required": ["value"]
+ }
+ ]
+ }
}
- ]
+ },
+ "required": ["message"]
+ }
+ ]
}
-```
\ No newline at end of file
+```
diff --git a/docs/specifications/update.md b/docs/specifications/update.md
index da02a01a7cac..00f1d3f2819b 100644
--- a/docs/specifications/update.md
+++ b/docs/specifications/update.md
@@ -1,4 +1,3 @@
-
# Update Command
`ng update` is a new command in the CLI to update one or multiple packages, its peer dependencies, and the peer dependencies that depends on it.
@@ -11,16 +10,16 @@ If there are inconsistencies, for example if peer dependencies cannot be matches
ng update [options]
```
-You can specify more than one package. Each package follows the convention of `[@scope/]packageName[@version-range-or-dist-tag]`. Packages not found in your dependencies will trigger an error. Any package that has a higher version in your `package.json` will trigger an error.
+You can specify more than one package. Each package follows the convention of `[@scope/]packageName[@version-range-or-dist-tag]`. Packages not found in your dependencies will trigger an error. Any package that has a higher version in your `package.json` will trigger an error.
-| Flag | Argument | Description |
-|---|---|---|
-| `--all` | `boolean` | If true, implies that all dependencies should be updated. Defaults is false, using dependencies from the command line instead. |
-| `--force` | `boolean` | If true, skip the verification step and perform the update even if some peer dependencies would be invalidated. Peer dependencies errors will still be shown as warning. Defaults to false. |
-| `--next` | `boolean` | If true, allows version discovery to include Beta and RC. Defaults to false. |
-| `--migrate-only` | `boolean` | If true, don't change the `package.json` file, only apply migration scripts. |
-| `--from` | `version` | Apply migrations from a certain version number. |
-| `--to` | `version` | Apply migrations up to a certain version number (inclusive). By default will update to the installed version. |
+| Flag | Argument | Description |
+| ---------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `--all` | `boolean` | If true, implies that all dependencies should be updated. Defaults is false, using dependencies from the command line instead. |
+| `--force` | `boolean` | If true, skip the verification step and perform the update even if some peer dependencies would be invalidated. Peer dependencies errors will still be shown as warning. Defaults to false. |
+| `--next` | `boolean` | If true, allows version discovery to include Beta and RC. Defaults to false. |
+| `--migrate-only` | `boolean` | If true, don't change the `package.json` file, only apply migration scripts. |
+| `--from` | `version` | Apply migrations from a certain version number. |
+| `--to` | `version` | Apply migrations up to a certain version number (inclusive). By default will update to the installed version. |
## Details
@@ -28,39 +27,37 @@ The schematic performs the following steps, in order:
1. Get all installed package names and versions from the `package.json` into `dependencyMap: Map`.
1. From that map, fetch all `package.json` from the NPM repository, which contains all versions, and gather them in a `Map`.
- 1. At the same time, update the `Map<>` with the version of the package which is believed to be installed (largest version number matching the version range).
- 1. **WARNING**: this might not be the exact installed versions, unfortunately. We should have a proper `package-lock.json` loader, and support `yarn.lock` as well, but these are stretch goals (and where do we stop).
-1. For each packages mentioned on the command line, update to the target version (by default largest non-beta non-rc version):
-
- ```python
- # ARGV The packages being requested by the user.
- # NPM A map of package name to a map of version to PackageJson structure.
- # V A map of package name to available versions.
- # PKG A map of package name to PackageJson structure, for the installed versions.
- # next A flag for the "--next" command line argument.
-
- # First add all updating packages' peer dependencies. This should be recursive but simplified
- # here for readability.
- ARGV += [ NPM[p][max([ v for v in V[p] if (not is_beta(v) or next) ])].peerDependencies
- for p in ARGV ]
-
- for p in ARGV:
- x = max([ v for v in V[p] if (not is_beta(v) or next) ])
-
- for other in set(PKG.keys()) - set([ p ]):
- # Verify all packages' peer dependencies.
- if has(other.peerDependencies, p) and !compatible(x, other.peerDependencies[p]):
- showError('Cannot update dependency "%s": "%s" is incompatible with the updated dependency' % (x, other))
-
- if any( has(other.peerDependencies, peer) and !compatible(x, other.peerDependencies[peer])
- for peer in PKG[p].peerDependencies.keys() ):
- showError('Cannot update dependency "%s": "%s" depends on an incompatible peer dependency' % (x, other))
-
- update_package_json(p, x)
+1. At the same time, update the `Map<>` with the version of the package which is believed to be installed (largest version number matching the version range).
+1. **WARNING**: this might not be the exact installed versions, unfortunately. We should have a proper `package-lock.json` loader, and support `yarn.lock` as well, but these are stretch goals (and where do we stop).
+1. For each packages mentioned on the command line, update to the target version (by default largest non-beta non-rc version):
+
+```python
+# ARGV The packages being requested by the user.
+# NPM A map of package name to a map of version to PackageJson structure.
+# V A map of package name to available versions.
+# PKG A map of package name to PackageJson structure, for the installed versions.
+# next A flag for the "--next" command line argument.
+
+# First add all updating packages' peer dependencies. This should be recursive but simplified
+# here for readability.
+ARGV += [ NPM[p][max([ v for v in V[p] if (not is_beta(v) or next) ])].peerDependencies
+ for p in ARGV ]
+
+for p in ARGV:
+ x = max([ v for v in V[p] if (not is_beta(v) or next) ])
+
+ for other in set(PKG.keys()) - set([ p ]):
+ # Verify all packages' peer dependencies.
+ if has(other.peerDependencies, p) and !compatible(x, other.peerDependencies[p]):
+ showError('Cannot update dependency "%s": "%s" is incompatible with the updated dependency' % (x, other))
+
+ if any( has(other.peerDependencies, peer) and !compatible(x, other.peerDependencies[peer])
+ for peer in PKG[p].peerDependencies.keys() ):
+ showError('Cannot update dependency "%s": "%s" depends on an incompatible peer dependency' % (x, other))
+
+ update_package_json(p, x)
```
-
-
## Library Developers
Libraries are responsible for defining their own update schematics. The `ng update` tool will update the package.json, and if it detects the `"ng-update"` key in package.json of the library, will run the update schematic on it (with version information metadata).
@@ -71,14 +68,15 @@ If a library does not define the `"ng-update"` key in their package.json, they a
In order to implement migrations in a library, the author must add the `ng-update` key to its `package.json`. This key contains the following fields:
-| Field Name | Type | Description |
-|---|---|---|
-| `requirements` | `{ [packageName: string]: VersionRange }` | A map of package names to version to check for minimal requirement. If one of the libraries listed here does not match the version range specified in `requirements`, an error will be shown to the user to manually update those libraries. For example, `@angular/core` does not support updates from versions earlier than 5, so this field would be `{ '@angular/core': '>= 5' }`.
-| `migrations` | `string` | A relative path (or resolved using Node module resolution) to a Schematics collection definition. |
-| `packageGroup` | `string[]` | A list of npm packages that are to be grouped together. When running the update schematic it will automatically include all packages as part of the packageGroup in the update (if the user also installed them). |
-| `packageGroupName` | `string` | The name of the packageGroup to use. By default, uses the first package in the packageGroup. The packageGroupName needs to be part of the packageGroup and should be a valid package name. |
+| Field Name | Type | Description |
+| ------------------ | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `requirements` | `{ [packageName: string]: VersionRange }` | A map of package names to version to check for minimal requirement. If one of the libraries listed here does not match the version range specified in `requirements`, an error will be shown to the user to manually update those libraries. For example, `@angular/core` does not support updates from versions earlier than 5, so this field would be `{ '@angular/core': '>= 5' }`. |
+| `migrations` | `string` | A relative path (or resolved using Node module resolution) to a Schematics collection definition. |
+| `packageGroup` | `string[]` | A list of npm packages that are to be grouped together. When running the update schematic it will automatically include all packages as part of the packageGroup in the update (if the user also installed them). |
+| `packageGroupName` | `string` | The name of the packageGroup to use. By default, uses the first package in the packageGroup. The packageGroupName needs to be part of the packageGroup and should be a valid package name. |
#### Example given:
+
Library my-lib wants to have 2 steps to update from version 4 -> 4.5 and 4.5 to 5. It would add this information in its `package.json`:
```json
@@ -150,10 +148,11 @@ There might be additional packages that are outdated.
I have a dependency on Angular, Material and CLI. I want to update the CLI, then Angular, then Material in separate steps.
#### Details
+
1. `ng update @angular/cli`.
-Updates the CLI and packages that have a peer dependencies on the CLI (none), running refactoring tools from CLI 1 to 6.
+ Updates the CLI and packages that have a peer dependencies on the CLI (none), running refactoring tools from CLI 1 to 6.
1. `ng update @angular/core`.
-Updates the Core package and all packages that have a peer dependency on it. This can get tricky if `@angular/material` get caught in the update because the version installed does not directly allow the new version of `@angular/core`. In this case
+ Updates the Core package and all packages that have a peer dependency on it. This can get tricky if `@angular/material` get caught in the update because the version installed does not directly allow the new version of `@angular/core`. In this case
### Complex Case
@@ -182,10 +181,9 @@ ng update @angular/material
```
- update `@angular/material` to latest version, that should be compatible with the current `@angular/core`.
-- if that version is not compatible with you
+- if that version is not compatible with you
- tell the user about a higher version that requires an update to `@angular/core`.
-
## Notes
1. if someone is on CLI 1.5, the command is not supported. The user needs to update to `@angular/cli@latest`, then `ng update @angular/cli`. Post install hook will check versions of cli configuration and show a message to run the `ng update` command.
diff --git a/etc/api/angular_devkit/architect/src/index.d.ts b/etc/api/angular_devkit/architect/src/index.d.ts
index ec27026f5791..d0a373871592 100644
--- a/etc/api/angular_devkit/architect/src/index.d.ts
+++ b/etc/api/angular_devkit/architect/src/index.d.ts
@@ -13,7 +13,7 @@ export interface BuilderContext {
logger: logging.LoggerApi;
target?: Target;
workspaceRoot: string;
- addTeardown(teardown: () => (Promise | void)): void;
+ addTeardown(teardown: () => Promise | void): void;
getBuilderNameForTarget(target: Target): Promise;
getProjectMetadata(projectName: string): Promise;
getProjectMetadata(target: Target): Promise;
@@ -44,10 +44,10 @@ export declare type BuilderOutputLike = AsyncIterable | Subscriba
export declare type BuilderProgress = json.JsonObject & RealBuilderProgress & TypedBuilderProgress;
-export declare type BuilderProgressReport = BuilderProgress & ({
+export declare type BuilderProgressReport = BuilderProgress & {
target?: Target;
builder: BuilderInfo;
-});
+};
export declare type BuilderRegistry = experimental.jobs.Registry;
@@ -79,7 +79,7 @@ export declare function targetFromTargetString(str: string): Target;
export declare function targetStringFromTarget({ project, target, configuration }: Target): string;
-export declare type TypedBuilderProgress = ({
+export declare type TypedBuilderProgress = {
state: BuilderProgressState.Stopped;
} | {
state: BuilderProgressState.Error;
@@ -92,4 +92,4 @@ export declare type TypedBuilderProgress = ({
status?: string;
current: number;
total?: number;
-});
+};
diff --git a/etc/api/angular_devkit/core/src/_golden-api.d.ts b/etc/api/angular_devkit/core/src/_golden-api.d.ts
index 10390f0ff530..35a04b710a1e 100644
--- a/etc/api/angular_devkit/core/src/_golden-api.d.ts
+++ b/etc/api/angular_devkit/core/src/_golden-api.d.ts
@@ -596,7 +596,7 @@ export declare class PartiallyOrderedSet implements Set {
get size(): number;
[Symbol.iterator](): Generator;
protected _checkCircularDependencies(item: T, deps: Set): void;
- add(item: T, deps?: (Set | T[])): this;
+ add(item: T, deps?: Set | T[]): this;
clear(): void;
delete(item: T): boolean;
entries(): IterableIterator<[T, T]>;
diff --git a/lib/bootstrap-local.js b/lib/bootstrap-local.js
index c377a4b67152..c6441e56f47d 100644
--- a/lib/bootstrap-local.js
+++ b/lib/bootstrap-local.js
@@ -27,7 +27,7 @@ debugLocal('starting bootstrap local');
// This processes any extended configs
const compilerOptions = ts.getParsedCommandLineOfConfigFile(
path.join(__dirname, '../tsconfig-test.json'),
- { },
+ {},
ts.sys,
).options;
@@ -38,8 +38,10 @@ if (process.env['DEVKIT_PROFILING']) {
try {
profiler = require('v8-profiler-node8');
} catch (err) {
- throw new Error(`Could not require 'v8-profiler-node8'. You must install it separetely with` +
- `'npm install v8-profiler-node8 --no-save.\n\nOriginal error:\n\n${err}`);
+ throw new Error(
+ `Could not require 'v8-profiler-node8'. You must install it separetely with` +
+ `'npm install v8-profiler-node8 --no-save.\n\nOriginal error:\n\n${err}`,
+ );
}
profiler.startProfiling();
@@ -73,7 +75,6 @@ if (process.env['DEVKIT_LONG_STACK_TRACE']) {
global._DevKitIsLocal = true;
global._DevKitRoot = path.resolve(__dirname, '..');
-
const oldRequireTs = require.extensions['.ts'];
require.extensions['.ts'] = function (m, filename) {
// If we're in node module, either call the old hook or simply compile the
@@ -105,7 +106,6 @@ require.extensions['.ts'] = function (m, filename) {
}
};
-
require.extensions['.ejs'] = function (m, filename) {
debugBuildEjs(filename);
@@ -121,7 +121,6 @@ const builtinModules = Object.keys(process.binding('natives'));
const packages = require('./packages').packages;
// If we're running locally, meaning npm linked. This is basically "developer mode".
if (!__dirname.match(new RegExp(`\\${path.sep}node_modules\\${path.sep}`))) {
-
// We mock the module loader so that we can fake our packages when running locally.
const Module = require('module');
const oldLoad = Module._load;
@@ -144,7 +143,7 @@ if (!__dirname.match(new RegExp(`\\${path.sep}node_modules\\${path.sep}`))) {
} else if (resolved && resolved.match(/[\\\/]node_modules[\\\/]/)) {
return resolved;
} else {
- const match = Object.keys(packages).find(pkgName => request.startsWith(pkgName + '/'));
+ const match = Object.keys(packages).find((pkgName) => request.startsWith(pkgName + '/'));
if (match) {
const p = path.join(packages[match].root, request.substr(match.length));
return oldResolve.call(this, p, parent);
@@ -169,7 +168,10 @@ if (!__dirname.match(new RegExp(`\\${path.sep}node_modules\\${path.sep}`))) {
// This script has the be synchronous, so we spawnSync instead of, say, requiring the runner and calling
// the method directly.
- const tmpJsonSchemaPath = path.join(tmpRoot, maybeTsPath.replace(/[^0-9a-zA-Z.]/g, '_'));
+ const tmpJsonSchemaPath = path.join(
+ tmpRoot,
+ maybeTsPath.replace(/[^0-9a-zA-Z.]/g, '_'),
+ );
try {
if (!fs.existsSync(tmpJsonSchemaPath)) {
const quicktypeRunnerPath = path.join(__dirname, '../tools/quicktype_runner.js');
diff --git a/lib/packages.ts b/lib/packages.ts
index b4b35784fcfc..cbedc40cb958 100644
--- a/lib/packages.ts
+++ b/lib/packages.ts
@@ -17,11 +17,10 @@ import * as ts from 'typescript';
const distRoot = path.join(__dirname, '../dist');
const { packages: monorepoPackages } = require('../.monorepo.json');
-
export interface PackageInfo {
name: string;
root: string;
- bin: { [name: string]: string};
+ bin: { [name: string]: string };
relative: string;
main: string;
dist: string;
@@ -41,7 +40,6 @@ export interface PackageInfo {
}
export type PackageMap = { [name: string]: PackageInfo };
-
export function loadRootPackageJson() {
return require('../package.json');
}
@@ -77,11 +75,12 @@ function loadPackageJson(p: string) {
case 'keywords':
const a = pkg[key] || [];
const b = Object.keys(
- root[key].concat(a).reduce((acc: {[k: string]: boolean}, curr: string) => {
+ root[key].concat(a).reduce((acc: { [k: string]: boolean }, curr: string) => {
acc[curr] = true;
return acc;
- }, {}));
+ }, {}),
+ );
pkg[key] = b;
break;
@@ -103,54 +102,53 @@ function loadPackageJson(p: string) {
return pkg;
}
-
function _findAllPackageJson(dir: string, exclude: RegExp): string[] {
const result: string[] = [];
- fs.readdirSync(dir)
- .forEach(fileName => {
- const p = path.join(dir, fileName);
-
- if (exclude.test(p)) {
- return;
- } else if (/[\/\\]node_modules[\/\\]/.test(p)) {
- return;
- } else if (fileName == 'package.json') {
- result.push(p);
- } else if (fs.statSync(p).isDirectory() && fileName != 'node_modules') {
- result.push(..._findAllPackageJson(p, exclude));
- }
- });
+ fs.readdirSync(dir).forEach((fileName) => {
+ const p = path.join(dir, fileName);
+
+ if (exclude.test(p)) {
+ return;
+ } else if (/[\/\\]node_modules[\/\\]/.test(p)) {
+ return;
+ } else if (fileName == 'package.json') {
+ result.push(p);
+ } else if (fs.statSync(p).isDirectory() && fileName != 'node_modules') {
+ result.push(..._findAllPackageJson(p, exclude));
+ }
+ });
return result;
}
-
const tsConfigPath = path.join(__dirname, '../tsconfig.json');
const tsConfig = ts.readConfigFile(tsConfigPath, ts.sys.readFile);
-const pattern = '^('
- + (tsConfig.config.exclude as string[])
- .map(ex => path.join(path.dirname(tsConfigPath), ex))
- .map(ex => '('
- + ex
- .replace(/[\-\[\]{}()+?./\\^$|]/g, '\\$&')
- .replace(/(\\\\|\\\/)\*\*/g, '((\/|\\\\).+?)?')
- .replace(/\*/g, '[^/\\\\]*')
- + ')')
- .join('|')
- + ')($|/|\\\\)';
+const pattern =
+ '^(' +
+ (tsConfig.config.exclude as string[])
+ .map((ex) => path.join(path.dirname(tsConfigPath), ex))
+ .map(
+ (ex) =>
+ '(' +
+ ex
+ .replace(/[\-\[\]{}()+?./\\^$|]/g, '\\$&')
+ .replace(/(\\\\|\\\/)\*\*/g, '((/|\\\\).+?)?')
+ .replace(/\*/g, '[^/\\\\]*') +
+ ')',
+ )
+ .join('|') +
+ ')($|/|\\\\)';
const excludeRe = new RegExp(pattern);
// Find all the package.json that aren't excluded from tsconfig.
const packageJsonPaths = _findAllPackageJson(path.join(__dirname, '..'), excludeRe)
// Remove the root package.json.
- .filter(p => p != path.join(__dirname, '../package.json'));
-
+ .filter((p) => p != path.join(__dirname, '../package.json'));
function _exec(cmd: string) {
return execSync(cmd).toString().trim();
}
-
let gitShaCache: string;
function _getSnapshotHash(_pkg: PackageInfo): string {
if (!gitShaCache) {
@@ -160,7 +158,6 @@ function _getSnapshotHash(_pkg: PackageInfo): string {
return gitShaCache;
}
-
const stableVersion = loadRootPackageJson().version;
const experimentalVersion = stableToExperimentalVersion(stableVersion);
@@ -178,71 +175,68 @@ export function stableToExperimentalVersion(stable: string): string {
// All the supported packages. Go through the packages directory and create a map of
// name => PackageInfo. This map is partial as it lacks some information that requires the
// map itself to finish building.
-export const packages: PackageMap =
- packageJsonPaths
- .map(pkgPath => ({ root: path.dirname(pkgPath) }))
- .reduce((packages: PackageMap, pkg) => {
- const pkgRoot = pkg.root;
- const packageJson = loadPackageJson(path.join(pkgRoot, 'package.json'));
- const name = packageJson['name'];
- if (!name) {
- // Only build the entry if there's a package name.
- return packages;
- }
- if (!(name in monorepoPackages)) {
- throw new Error(
- `Package ${name} found in ${JSON.stringify(pkg.root)}, not found in .monorepo.json.`,
- );
- }
-
- const bin: {[name: string]: string} = {};
- Object.keys(packageJson['bin'] || {}).forEach(binName => {
- let p = path.resolve(pkg.root, packageJson['bin'][binName]);
- if (!fs.existsSync(p)) {
- p = p.replace(/\.js$/, '.ts');
- }
- bin[binName] = p;
- });
-
- const experimental = !!packageJson.private || !!packageJson.experimental;
-
- packages[name] = {
- build: path.join(distRoot, pkgRoot.substr(path.dirname(__dirname).length)),
- dist: path.join(distRoot, name),
- root: pkgRoot,
- relative: path.relative(path.dirname(__dirname), pkgRoot),
- main: path.resolve(pkgRoot, 'src/index.ts'),
- private: !!packageJson.private,
- experimental,
- // yarn doesn't take kindly to @ in tgz filenames
- // https://github.com/yarnpkg/yarn/issues/6339
- tar: path.join(distRoot, name.replace(/\/|@/g, '_') + '.tgz'),
- bin,
- name,
- packageJson,
-
- snapshot: !!monorepoPackages[name].snapshotRepo,
- snapshotRepo: monorepoPackages[name].snapshotRepo,
- get snapshotHash() {
- return _getSnapshotHash(this);
- },
-
- dependencies: [],
- reverseDependencies: [],
- version: experimental ? experimentalVersion : stableVersion,
- };
-
+export const packages: PackageMap = packageJsonPaths
+ .map((pkgPath) => ({ root: path.dirname(pkgPath) }))
+ .reduce((packages: PackageMap, pkg) => {
+ const pkgRoot = pkg.root;
+ const packageJson = loadPackageJson(path.join(pkgRoot, 'package.json'));
+ const name = packageJson['name'];
+ if (!name) {
+ // Only build the entry if there's a package name.
return packages;
- }, {});
+ }
+ if (!(name in monorepoPackages)) {
+ throw new Error(
+ `Package ${name} found in ${JSON.stringify(pkg.root)}, not found in .monorepo.json.`,
+ );
+ }
+
+ const bin: { [name: string]: string } = {};
+ Object.keys(packageJson['bin'] || {}).forEach((binName) => {
+ let p = path.resolve(pkg.root, packageJson['bin'][binName]);
+ if (!fs.existsSync(p)) {
+ p = p.replace(/\.js$/, '.ts');
+ }
+ bin[binName] = p;
+ });
+ const experimental = !!packageJson.private || !!packageJson.experimental;
+
+ packages[name] = {
+ build: path.join(distRoot, pkgRoot.substr(path.dirname(__dirname).length)),
+ dist: path.join(distRoot, name),
+ root: pkgRoot,
+ relative: path.relative(path.dirname(__dirname), pkgRoot),
+ main: path.resolve(pkgRoot, 'src/index.ts'),
+ private: !!packageJson.private,
+ experimental,
+ // yarn doesn't take kindly to @ in tgz filenames
+ // https://github.com/yarnpkg/yarn/issues/6339
+ tar: path.join(distRoot, name.replace(/\/|@/g, '_') + '.tgz'),
+ bin,
+ name,
+ packageJson,
+
+ snapshot: !!monorepoPackages[name].snapshotRepo,
+ snapshotRepo: monorepoPackages[name].snapshotRepo,
+ get snapshotHash() {
+ return _getSnapshotHash(this);
+ },
+
+ dependencies: [],
+ reverseDependencies: [],
+ version: experimental ? experimentalVersion : stableVersion,
+ };
+
+ return packages;
+ }, {});
// Update with dependencies.
for (const pkgName of Object.keys(packages)) {
const pkg = packages[pkgName];
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 || {});
+ pkg.dependencies = Object.keys(packages).filter((name) => {
+ return name in (pkgJson.dependencies || {}) || name in (pkgJson.devDependencies || {});
});
- pkg.dependencies.forEach(depName => packages[depName].reverseDependencies.push(pkgName));
+ pkg.dependencies.forEach((depName) => packages[depName].reverseDependencies.push(pkgName));
}
diff --git a/packages/README.md b/packages/README.md
index eb38cb395147..aab7eadc1c92 100644
--- a/packages/README.md
+++ b/packages/README.md
@@ -4,5 +4,5 @@ This folder is the root of all defined packages in this repository.
Packages that are marked as `private: true` will not be published to NPM.
-This folder includes a directory for every scope in NPM, without the `@` sign. Then one folder
+This folder includes a directory for every scope in NPM, without the `@` sign. Then one folder
per package, which contains the `package.json`.
diff --git a/packages/angular/cli/README.md b/packages/angular/cli/README.md
index 96b40aacbad5..954dcd7d702c 100644
--- a/packages/angular/cli/README.md
+++ b/packages/angular/cli/README.md
@@ -1,6 +1,7 @@
## Angular CLI
+
[![Dependency Status][david-badge]][david-badge-url]
[![devDependency Status][david-dev-badge]][david-dev-badge-url]
@@ -14,7 +15,6 @@
[![GitHub forks](https://img.shields.io/github/forks/angular/angular-cli.svg?style=social&label=Fork)](https://github.com/angular/angular-cli/fork)
[![GitHub stars](https://img.shields.io/github/stars/angular/angular-cli.svg?style=social&label=Star)](https://github.com/angular/angular-cli)
-
## Note
If you are updating from a beta or RC version, check out our [1.0 Update Guide](https://github.com/angular/angular-cli/wiki/stories-1.0-update).
@@ -30,25 +30,27 @@ with NPM 5.5.1 or higher.
## Table of Contents
-* [Installation](#installation)
-* [Usage](#usage)
-* [Generating a New Project](#generating-and-serving-an-angular-project-via-a-development-server)
-* [Generating Components, Directives, Pipes and Services](#generating-components-directives-pipes-and-services)
-* [Updating Angular CLI](#updating-angular-cli)
-* [Development Hints for working on Angular CLI](#development-hints-for-working-on-angular-cli)
-* [Documentation](#documentation)
-* [License](#license)
+- [Installation](#installation)
+- [Usage](#usage)
+- [Generating a New Project](#generating-and-serving-an-angular-project-via-a-development-server)
+- [Generating Components, Directives, Pipes and Services](#generating-components-directives-pipes-and-services)
+- [Updating Angular CLI](#updating-angular-cli)
+- [Development Hints for working on Angular CLI](#development-hints-for-working-on-angular-cli)
+- [Documentation](#documentation)
+- [License](#license)
## Installation
**BEFORE YOU INSTALL:** please read the [prerequisites](#prerequisites)
### Install Globally
+
```bash
npm install -g @angular/cli
```
### Install Locally
+
```bash
npm install @angular/cli
```
@@ -58,6 +60,7 @@ To run a locally installed version of the angular-cli, you can call `ng` command
Alternatively, you can install [npx](https://www.npmjs.com/package/npx) and run `npx ng ` within the local directory where `npm install @angular/cli` was run, which will use the locally installed angular-cli.
### Install Specific Version (Example: 6.1.1)
+
```bash
npm install -g @angular/cli@6.1.1
```
@@ -75,6 +78,7 @@ ng new PROJECT-NAME
cd PROJECT-NAME
ng serve
```
+
Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
You can configure the default HTTP host and port used by the development server with two command-line options :
@@ -102,33 +106,32 @@ ng g component ./newer-cmp
ng g component feature/new-cmp
# and your component will be generated in src/app/feature/new-cmp
```
-You can find all possible blueprints in the table below:
-
-Scaffold | Usage
---- | ---
-[Component](https://angular.io/cli/generate#component) | `ng g component my-new-component`
-[Directive](https://angular.io/cli/generate#directive) | `ng g directive my-new-directive`
-[Pipe](https://angular.io/cli/generate#pipe) | `ng g pipe my-new-pipe`
-[Service](https://angular.io/cli/generate#service) | `ng g service my-new-service`
-[Class](https://angular.io/cli/generate#class) | `ng g class my-new-class`
-[Guard](https://angular.io/cli/generate#guard) | `ng g guard my-new-guard`
-[Interface](https://angular.io/cli/generate#interface) | `ng g interface my-new-interface`
-[Enum](https://angular.io/cli/generate#enum) | `ng g enum my-new-enum`
-[Module](https://angular.io/cli/generate#module) | `ng g module my-module`
-
+You can find all possible blueprints in the table below:
+| Scaffold | Usage |
+| ------------------------------------------------------ | --------------------------------- |
+| [Component](https://angular.io/cli/generate#component) | `ng g component my-new-component` |
+| [Directive](https://angular.io/cli/generate#directive) | `ng g directive my-new-directive` |
+| [Pipe](https://angular.io/cli/generate#pipe) | `ng g pipe my-new-pipe` |
+| [Service](https://angular.io/cli/generate#service) | `ng g service my-new-service` |
+| [Class](https://angular.io/cli/generate#class) | `ng g class my-new-class` |
+| [Guard](https://angular.io/cli/generate#guard) | `ng g guard my-new-guard` |
+| [Interface](https://angular.io/cli/generate#interface) | `ng g interface my-new-interface` |
+| [Enum](https://angular.io/cli/generate#enum) | `ng g enum my-new-enum` |
+| [Module](https://angular.io/cli/generate#module) | `ng g module my-module` |
angular-cli will add reference to `components`, `directives` and `pipes` automatically in the `app.module.ts`. If you need to add this references to another custom module, follow these steps:
- 1. `ng g module new-module` to create a new module
- 2. call `ng g component new-module/new-component`
+1. `ng g module new-module` to create a new module
+2. call `ng g component new-module/new-component`
This should add the new `component`, `directive` or `pipe` reference to the `new-module` you've created.
### Updating Angular CLI
If you're using Angular CLI `1.0.0-beta.28` or less, you need to uninstall `angular-cli` package. It should be done due to changing of package's name and scope from `angular-cli` to `@angular/cli`:
+
```bash
npm uninstall -g angular-cli
npm uninstall --save-dev angular-cli
@@ -137,6 +140,7 @@ npm uninstall --save-dev angular-cli
To update Angular CLI to a new version, you must update both the global package and your project's local package.
Global package:
+
```bash
npm uninstall -g @angular/cli
npm cache verify
@@ -145,6 +149,7 @@ npm install -g @angular/cli@latest
```
Local project package:
+
```bash
rm -rf node_modules dist # use rmdir /S/Q node_modules dist in Windows Command Prompt; use rm -r -fo node_modules,dist in Windows PowerShell
npm install --save-dev @angular/cli@latest
@@ -155,7 +160,6 @@ If you are updating to 1.0 from a beta or RC version, check out our [1.0 Update
You can find more details about changes between versions in [the Releases tab on GitHub](https://github.com/angular/angular-cli/releases).
-
## Development Hints for working on Angular CLI
### Working with master
@@ -231,15 +235,17 @@ For more informations about Node.js debugging in VS Code, see the related [VS Co
In order to investigate performance issues, CPU profiling is often useful.
To capture a CPU profiling, you can:
+
1. install the v8-profiler-node8 dependency: `npm install v8-profiler-node8 --no-save`
1. set the NG_CLI_PROFILING Environment variable to the file name you want:
- * on Unix systems (Linux & Mac OS X): ̀`export NG_CLI_PROFILING=my-profile`
- * on Windows: ̀̀`setx NG_CLI_PROFILING my-profile`
+ - on Unix systems (Linux & Mac OS X): ̀`export NG_CLI_PROFILING=my-profile`
+ - on Windows: ̀̀`setx NG_CLI_PROFILING my-profile`
Then, just run the ng command on which you want to capture a CPU profile.
You will then obtain a `my-profile.cpuprofile` file in the folder from which you ran the ng command.
You can use the Chrome Devtools to process it. To do so:
+
1. open `chrome://inspect/#devices` in Chrome
1. click on "Open dedicated DevTools for Node"
1. go to the "profiler" tab
@@ -256,7 +262,6 @@ The documentation for the Angular CLI is located on our [documentation website](
[MIT](https://github.com/angular/angular-cli/blob/master/LICENSE)
-
[travis-badge]: https://travis-ci.org/angular/angular-cli.svg?branch=master
[travis-badge-url]: https://travis-ci.org/angular/angular-cli
[david-badge]: https://david-dm.org/angular/angular-cli.svg
@@ -266,4 +271,3 @@ The documentation for the Angular CLI is located on our [documentation website](
[npm-badge]: https://img.shields.io/npm/v/@angular/cli.svg
[npm-badge-url]: https://www.npmjs.com/package/@angular/cli
[license-url]: https://github.com/angular/angular-cli/blob/master/LICENSE
-
diff --git a/packages/angular/cli/bin/postinstall/analytics-prompt.js b/packages/angular/cli/bin/postinstall/analytics-prompt.js
index 04121439939e..b24c319ede10 100644
--- a/packages/angular/cli/bin/postinstall/analytics-prompt.js
+++ b/packages/angular/cli/bin/postinstall/analytics-prompt.js
@@ -10,7 +10,7 @@ try {
analytics
.hasGlobalAnalyticsConfiguration()
- .then(hasGlobalConfig => {
+ .then((hasGlobalConfig) => {
if (!hasGlobalConfig) {
return analytics.promptGlobalAnalytics();
}
diff --git a/packages/angular/cli/commands/add-impl.ts b/packages/angular/cli/commands/add-impl.ts
index dd309030f928..f9103af4d8ae 100644
--- a/packages/angular/cli/commands/add-impl.ts
+++ b/packages/angular/cli/commands/add-impl.ts
@@ -170,9 +170,7 @@ export class AddCommand extends SchematicCommand {
collectionName = manifest.name;
if (await this.hasMismatchedPeer(manifest)) {
- spinner.warn(
- 'Package has unmet peer dependencies. Adding the package may not succeed.',
- );
+ spinner.warn('Package has unmet peer dependencies. Adding the package may not succeed.');
} else {
spinner.succeed(`Package information loaded.`);
}
@@ -215,12 +213,9 @@ export class AddCommand extends SchematicCommand {
packageManager,
options.registry ? [`--registry="${options.registry}"`] : undefined,
);
- const resolvedCollectionPath = require.resolve(
- join(collectionName, 'package.json'),
- {
- paths: [tempPath],
- },
- );
+ const resolvedCollectionPath = require.resolve(join(collectionName, 'package.json'), {
+ paths: [tempPath],
+ });
collectionName = dirname(resolvedCollectionPath);
} else {
diff --git a/packages/angular/cli/commands/add.json b/packages/angular/cli/commands/add.json
index 014ec5ab4d6b..99cd82d897fb 100644
--- a/packages/angular/cli/commands/add.json
+++ b/packages/angular/cli/commands/add.json
@@ -42,8 +42,7 @@
"default": false
}
},
- "required": [
- ]
+ "required": []
},
{
"$ref": "./definitions.json#/definitions/interactive"
diff --git a/packages/angular/cli/commands/add.md b/packages/angular/cli/commands/add.md
index 465438a4e5b2..09cd2e239d76 100644
--- a/packages/angular/cli/commands/add.md
+++ b/packages/angular/cli/commands/add.md
@@ -2,6 +2,7 @@ Adds the npm package for a published library to your workspace, and configures
the project in the current working directory (or the default project if you are
not in a project directory) to use that library, as specified by the library's schematic.
For example, adding `@angular/pwa` configures your project for PWA support:
+
```bash
ng add @angular/pwa
```
diff --git a/packages/angular/cli/commands/analytics-impl.ts b/packages/angular/cli/commands/analytics-impl.ts
index c5703e0680e1..d27032f30d23 100644
--- a/packages/angular/cli/commands/analytics-impl.ts
+++ b/packages/angular/cli/commands/analytics-impl.ts
@@ -15,7 +15,6 @@ import { Command } from '../models/command';
import { Arguments } from '../models/interface';
import { ProjectSetting, Schema as AnalyticsCommandSchema, SettingOrProject } from './analytics';
-
export class AnalyticsCommand extends Command {
public async run(options: AnalyticsCommandSchema & Arguments) {
// Our parser does not support positional enums (won't report invalid parameters). Do the
@@ -34,10 +33,14 @@ export class AnalyticsCommand extends Command {
return 2;
}
- } else if (options.settingOrProject == SettingOrProject.Project
- && options.projectSetting === undefined) {
- this.logger.error(`Argument ${JSON.stringify(options.settingOrProject)} requires a second `
- + `argument of one of the following value: on, off.`);
+ } else if (
+ options.settingOrProject == SettingOrProject.Project &&
+ options.projectSetting === undefined
+ ) {
+ this.logger.error(
+ `Argument ${JSON.stringify(options.settingOrProject)} requires a second ` +
+ `argument of one of the following value: on, off.`,
+ );
return 2;
}
diff --git a/packages/angular/cli/commands/analytics-long.md b/packages/angular/cli/commands/analytics-long.md
index 60e0d86686e8..87b9925d1473 100644
--- a/packages/angular/cli/commands/analytics-long.md
+++ b/packages/angular/cli/commands/analytics-long.md
@@ -1,7 +1,8 @@
-The value of *settingOrProject* is one of the following.
-* "on" : Enables analytics gathering and reporting for the user.
-* "off" : Disables analytics gathering and reporting for the user.
-* "ci" : Enables analytics and configures reporting for use with Continuous Integration,
-which uses a common CI user.
-* "prompt" : Prompts the user to set the status interactively.
-* "project" : Sets the default status for the project to the *projectSetting* value, which can be any of the other values. The *projectSetting* argument is ignored for all other values of *settingOrProject*.
\ No newline at end of file
+The value of _settingOrProject_ is one of the following.
+
+- "on" : Enables analytics gathering and reporting for the user.
+- "off" : Disables analytics gathering and reporting for the user.
+- "ci" : Enables analytics and configures reporting for use with Continuous Integration,
+ which uses a common CI user.
+- "prompt" : Prompts the user to set the status interactively.
+- "project" : Sets the default status for the project to the _projectSetting_ value, which can be any of the other values. The _projectSetting_ argument is ignored for all other values of _settingOrProject_.
diff --git a/packages/angular/cli/commands/analytics.json b/packages/angular/cli/commands/analytics.json
index e34234d0e39d..ee2612b20399 100644
--- a/packages/angular/cli/commands/analytics.json
+++ b/packages/angular/cli/commands/analytics.json
@@ -14,13 +14,7 @@
{
"properties": {
"settingOrProject": {
- "enum": [
- "on",
- "off",
- "ci",
- "project",
- "prompt"
- ],
+ "enum": ["on", "off", "ci", "project", "prompt"],
"description": "Directly enables or disables all usage analytics for the user, or prompts the user to set the status interactively, or sets the default status for the project.",
"$default": {
"$source": "argv",
@@ -28,11 +22,7 @@
}
},
"projectSetting": {
- "enum": [
- "on",
- "off",
- "prompt"
- ],
+ "enum": ["on", "off", "prompt"],
"description": "Sets the default analytics enablement status for the project.",
"$default": {
"$source": "argv",
@@ -40,9 +30,7 @@
}
}
},
- "required": [
- "settingOrProject"
- ]
+ "required": ["settingOrProject"]
},
{ "$ref": "./definitions.json#/definitions/base" }
]
diff --git a/packages/angular/cli/commands/build.json b/packages/angular/cli/commands/build.json
index 2dbe778cafed..df9d93b85a19 100644
--- a/packages/angular/cli/commands/build.json
+++ b/packages/angular/cli/commands/build.json
@@ -4,7 +4,7 @@
"description": "Compiles an Angular app into an output directory named dist/ at the given output path. Must be executed from within a workspace directory.",
"$longDescription": "./build-long.md",
- "$aliases": [ "b" ],
+ "$aliases": ["b"],
"$scope": "in",
"$type": "architect",
"$impl": "./build-impl#BuildCommand",
diff --git a/packages/angular/cli/commands/config-impl.ts b/packages/angular/cli/commands/config-impl.ts
index cf5211ce5ba3..3e8022d18e22 100644
--- a/packages/angular/cli/commands/config-impl.ts
+++ b/packages/angular/cli/commands/config-impl.ts
@@ -9,21 +9,20 @@ import { JsonValue, tags } from '@angular-devkit/core';
import { v4 as uuidV4 } from 'uuid';
import { Command } from '../models/command';
import { Arguments, CommandScope } from '../models/interface';
-import {
- getWorkspaceRaw,
- migrateLegacyGlobalConfig,
- validateWorkspace,
-} from '../utilities/config';
+import { getWorkspaceRaw, migrateLegacyGlobalConfig, validateWorkspace } from '../utilities/config';
import { JSONFile, parseJson } from '../utilities/json-file';
import { Schema as ConfigCommandSchema } from './config';
-const validCliPaths = new Map string) | undefined>([
+const validCliPaths = new Map<
+ string,
+ ((arg: string | number | boolean | undefined) => string) | undefined
+>([
['cli.warnings.versionMismatch', undefined],
['cli.defaultCollection', undefined],
['cli.packageManager', undefined],
['cli.analytics', undefined],
['cli.analyticsSharing.tracking', undefined],
- ['cli.analyticsSharing.uuid', v => v ? `${v}` : uuidV4()],
+ ['cli.analyticsSharing.uuid', (v) => (v ? `${v}` : uuidV4())],
]);
/**
@@ -54,12 +53,12 @@ function parseJsonPath(path: string): (string | number)[] {
const indices = match[2]
.slice(1, -1)
.split('][')
- .map(x => (/^\d$/.test(x) ? +x : x.replace(/\"|\'/g, '')));
+ .map((x) => (/^\d$/.test(x) ? +x : x.replace(/\"|\'/g, '')));
result.push(...indices);
}
}
- return result.filter(fragment => fragment != null);
+ return result.filter((fragment) => fragment != null);
}
function normalizeValue(value: string | undefined | boolean | number): JsonValue | undefined {
@@ -93,7 +92,7 @@ export class ConfigCommand extends Command {
We found a global configuration that was used in Angular CLI 1.
It has been automatically migrated.`);
}
- } catch { }
+ } catch {}
}
if (options.value == undefined) {
diff --git a/packages/angular/cli/commands/config-long.md b/packages/angular/cli/commands/config-long.md
index 5f6052b3894a..7f44f63b3b32 100644
--- a/packages/angular/cli/commands/config-long.md
+++ b/packages/angular/cli/commands/config-long.md
@@ -10,4 +10,4 @@ while on the command line options can be given in either camelCase or dash-case.
For further details, see [Workspace Configuration](guide/workspace-config).
-For configuration of CLI usage analytics, see [Gathering an Viewing CLI Usage Analytics](./usage-analytics-gathering).
\ No newline at end of file
+For configuration of CLI usage analytics, see [Gathering an Viewing CLI Usage Analytics](./usage-analytics-gathering).
diff --git a/packages/angular/cli/commands/config.json b/packages/angular/cli/commands/config.json
index 95a1f874119b..bec13fca4c0f 100644
--- a/packages/angular/cli/commands/config.json
+++ b/packages/angular/cli/commands/config.json
@@ -36,8 +36,7 @@
"aliases": ["g"]
}
},
- "required": [
- ]
+ "required": []
},
{ "$ref": "./definitions.json#/definitions/base" }
]
diff --git a/packages/angular/cli/commands/definitions.json b/packages/angular/cli/commands/definitions.json
index 5da8c67159a2..a18355349f46 100644
--- a/packages/angular/cli/commands/definitions.json
+++ b/packages/angular/cli/commands/definitions.json
@@ -16,9 +16,7 @@
"configuration": {
"description": "One or more named builder configurations as a comma-separated list as specified in the \"configurations\" section of angular.json.\nThe builder uses the named configurations to run the given target.\nFor more information, see https://angular.io/guide/workspace-config#alternate-build-configurations.\nSetting this explicitly overrides the \"--prod\" flag.",
"type": "string",
- "aliases": [
- "c"
- ]
+ "aliases": ["c"]
},
"prod": {
"description": "Shorthand for \"--configuration=production\".\nSet the build configuration to the production target.\nBy default, the production target is set up in the workspace configuration such that all builds make use of bundling, limited tree-shaking, and also limited dead code elimination.",
@@ -43,13 +41,13 @@
"dryRun": {
"type": "boolean",
"default": false,
- "aliases": [ "d" ],
+ "aliases": ["d"],
"description": "Run through and reports activity without writing out results."
},
"force": {
"type": "boolean",
"default": false,
- "aliases": [ "f" ],
+ "aliases": ["f"],
"description": "Force overwriting of existing files."
}
}
diff --git a/packages/angular/cli/commands/deploy-long.md b/packages/angular/cli/commands/deploy-long.md
index afe619565c0a..9d13ad2a9890 100644
--- a/packages/angular/cli/commands/deploy-long.md
+++ b/packages/angular/cli/commands/deploy-long.md
@@ -19,4 +19,4 @@ For example:
}
}
}
- ```
\ No newline at end of file
+```
diff --git a/packages/angular/cli/commands/deploy.json b/packages/angular/cli/commands/deploy.json
index 31f6d8e7e4c5..cc7c860dde1c 100644
--- a/packages/angular/cli/commands/deploy.json
+++ b/packages/angular/cli/commands/deploy.json
@@ -22,9 +22,7 @@
"configuration": {
"description": "One or more named builder configurations as a comma-separated list as specified in the \"configurations\" section of angular.json.\nThe builder uses the named configurations to run the given target.\nFor more information, see https://angular.io/guide/workspace-config#alternate-build-configurations.",
"type": "string",
- "aliases": [
- "c"
- ]
+ "aliases": ["c"]
}
},
"required": []
diff --git a/packages/angular/cli/commands/doc-impl.ts b/packages/angular/cli/commands/doc-impl.ts
index 2b1aa87f22de..bc0611812c6d 100644
--- a/packages/angular/cli/commands/doc-impl.ts
+++ b/packages/angular/cli/commands/doc-impl.ts
@@ -39,7 +39,7 @@ export class DocCommand extends Command {
/* tslint:disable-next-line:no-implicit-dependencies */
const currentNgVersion = (await import('@angular/core')).VERSION.major;
domain = `v${currentNgVersion}.angular.io`;
- } catch (e) { }
+ } catch (e) {}
}
let searchUrl = `https://${domain}/api?query=${options.keyword}`;
diff --git a/packages/angular/cli/commands/doc.json b/packages/angular/cli/commands/doc.json
index de6cf2ff6323..bb01549c6099 100644
--- a/packages/angular/cli/commands/doc.json
+++ b/packages/angular/cli/commands/doc.json
@@ -4,7 +4,7 @@
"description": "Opens the official Angular documentation (angular.io) in a browser, and searches for a given keyword.",
"$longDescription": "",
- "$aliases": [ "d" ],
+ "$aliases": ["d"],
"$type": "native",
"$impl": "./doc-impl#DocCommand",
@@ -26,7 +26,7 @@
"default": false,
"description": "Search all of angular.io. Otherwise, searches only API reference documentation."
},
- "version" : {
+ "version": {
"oneOf": [
{
"type": "number",
@@ -39,8 +39,7 @@
"description": "Contains the version of Angular to use for the documentation. If not provided, the command uses your current Angular core version."
}
},
- "required": [
- ]
+ "required": []
},
{ "$ref": "./definitions.json#/definitions/base" }
]
diff --git a/packages/angular/cli/commands/e2e-impl.ts b/packages/angular/cli/commands/e2e-impl.ts
index 388360ad7095..730d09a1fbf0 100644
--- a/packages/angular/cli/commands/e2e-impl.ts
+++ b/packages/angular/cli/commands/e2e-impl.ts
@@ -9,7 +9,6 @@ import { ArchitectCommand } from '../models/architect-command';
import { Arguments } from '../models/interface';
import { Schema as E2eCommandSchema } from './e2e';
-
export class E2eCommand extends ArchitectCommand {
public readonly target = 'e2e';
public readonly multiTarget = true;
diff --git a/packages/angular/cli/commands/e2e-long.md b/packages/angular/cli/commands/e2e-long.md
index 6b651df713d9..369b0c71e443 100644
--- a/packages/angular/cli/commands/e2e-long.md
+++ b/packages/angular/cli/commands/e2e-long.md
@@ -1,2 +1,2 @@
Must be executed from within a workspace directory.
-When a project name is not supplied, it will execute for all projects.
\ No newline at end of file
+When a project name is not supplied, it will execute for all projects.
diff --git a/packages/angular/cli/commands/e2e.json b/packages/angular/cli/commands/e2e.json
index e8777a361bc3..a8c8cccc4b62 100644
--- a/packages/angular/cli/commands/e2e.json
+++ b/packages/angular/cli/commands/e2e.json
@@ -4,7 +4,7 @@
"description": "Builds and serves an Angular app, then runs end-to-end tests.",
"$longDescription": "./e2e-long.md",
- "$aliases": [ "e" ],
+ "$aliases": ["e"],
"$scope": "in",
"$type": "architect",
"$impl": "./e2e-impl#E2eCommand",
diff --git a/packages/angular/cli/commands/easter-egg.json b/packages/angular/cli/commands/easter-egg.json
index b42b12b1156e..79d9e1bb2edf 100644
--- a/packages/angular/cli/commands/easter-egg.json
+++ b/packages/angular/cli/commands/easter-egg.json
@@ -8,7 +8,5 @@
"$impl": "./easter-egg-impl#AwesomeCommand",
"type": "object",
- "allOf": [
- { "$ref": "./definitions.json#/definitions/base" }
- ]
+ "allOf": [{ "$ref": "./definitions.json#/definitions/base" }]
}
diff --git a/packages/angular/cli/commands/generate-impl.ts b/packages/angular/cli/commands/generate-impl.ts
index 40e81d1e5d5c..ca893d5888d8 100644
--- a/packages/angular/cli/commands/generate-impl.ts
+++ b/packages/angular/cli/commands/generate-impl.ts
@@ -53,7 +53,7 @@ export class GenerateCommand extends SchematicCommand {
}
}
- this.description.options.forEach(option => {
+ this.description.options.forEach((option) => {
if (option.name == 'schematic') {
option.subcommands = subcommands;
}
@@ -90,7 +90,9 @@ export class GenerateCommand extends SchematicCommand {
);
}
- private async parseSchematicInfo(options: GenerateCommandSchema): Promise<[string, string | undefined]> {
+ private async parseSchematicInfo(
+ options: GenerateCommandSchema,
+ ): Promise<[string, string | undefined]> {
let collectionName = await this.getDefaultSchematicCollection();
let schematicName = options.schematic;
@@ -107,7 +109,7 @@ export class GenerateCommand extends SchematicCommand {
this.logger.info('');
// Find the generate subcommand.
- const subcommand = this.description.options.filter(x => x.subcommands)[0];
+ const subcommand = this.description.options.filter((x) => x.subcommands)[0];
if (Object.keys((subcommand && subcommand.subcommands) || {}).length == 1) {
this.logger.info(`\nTo see help for a schematic run:`);
this.logger.info(colors.cyan(` ng generate --help`));
diff --git a/packages/angular/cli/commands/generate.json b/packages/angular/cli/commands/generate.json
index 833fe78436b3..53228340abd4 100644
--- a/packages/angular/cli/commands/generate.json
+++ b/packages/angular/cli/commands/generate.json
@@ -4,7 +4,7 @@
"description": "Generates and/or modifies files based on a schematic.",
"$longDescription": "",
- "$aliases": [ "g" ],
+ "$aliases": ["g"],
"$scope": "in",
"$type": "schematics",
"$impl": "./generate-impl#GenerateCommand",
@@ -22,8 +22,7 @@
}
}
},
- "required": [
- ]
+ "required": []
},
{ "$ref": "./definitions.json#/definitions/base" },
{ "$ref": "./definitions.json#/definitions/schematic" },
diff --git a/packages/angular/cli/commands/help-long.md b/packages/angular/cli/commands/help-long.md
index b104a1a6c03e..cc4b790f906e 100644
--- a/packages/angular/cli/commands/help-long.md
+++ b/packages/angular/cli/commands/help-long.md
@@ -1,7 +1,7 @@
- For help with individual commands, use the `--help` or `-h` option with the command.
+For help with individual commands, use the `--help` or `-h` option with the command.
- For example,
+For example,
- ```sh
- ng help serve
- ```
+```sh
+ng help serve
+```
diff --git a/packages/angular/cli/commands/help.json b/packages/angular/cli/commands/help.json
index 266a6d72aa6d..a6513118d0e4 100644
--- a/packages/angular/cli/commands/help.json
+++ b/packages/angular/cli/commands/help.json
@@ -9,7 +9,5 @@
"$impl": "./help-impl#HelpCommand",
"type": "object",
- "allOf": [
- { "$ref": "./definitions.json#/definitions/base" }
- ]
+ "allOf": [{ "$ref": "./definitions.json#/definitions/base" }]
}
diff --git a/packages/angular/cli/commands/lint-long.md b/packages/angular/cli/commands/lint-long.md
index 1588c8438fff..d6a4ee0f79b8 100644
--- a/packages/angular/cli/commands/lint-long.md
+++ b/packages/angular/cli/commands/lint-long.md
@@ -17,4 +17,4 @@ For example:
}
}
}
- ```
\ No newline at end of file
+```
diff --git a/packages/angular/cli/commands/lint.json b/packages/angular/cli/commands/lint.json
index e157fe583f57..824632e79f76 100644
--- a/packages/angular/cli/commands/lint.json
+++ b/packages/angular/cli/commands/lint.json
@@ -24,9 +24,7 @@
"configuration": {
"description": "One or more named builder configurations as a comma-separated list as specified in the \"configurations\" section of angular.json.\nThe builder uses the named configurations to run the given target.\nFor more information, see https://angular.io/guide/workspace-config#alternate-build-configurations.",
"type": "string",
- "aliases": [
- "c"
- ]
+ "aliases": ["c"]
}
},
"required": []
diff --git a/packages/angular/cli/commands/new-impl.ts b/packages/angular/cli/commands/new-impl.ts
index e4448a9178a0..53646a1296d4 100644
--- a/packages/angular/cli/commands/new-impl.ts
+++ b/packages/angular/cli/commands/new-impl.ts
@@ -10,13 +10,12 @@ import { Arguments } from '../models/interface';
import { SchematicCommand } from '../models/schematic-command';
import { Schema as NewCommandSchema } from './new';
-
export class NewCommand extends SchematicCommand {
public readonly allowMissingWorkspace = true;
schematicName = 'ng-new';
async initialize(options: NewCommandSchema & Arguments) {
- this.collectionName = options.collection || await this.getDefaultSchematicCollection();
+ this.collectionName = options.collection || (await this.getDefaultSchematicCollection());
return super.initialize(options);
}
@@ -37,5 +36,4 @@ export class NewCommand extends SchematicCommand {
force: !!options.force,
});
}
-
}
diff --git a/packages/angular/cli/commands/new.json b/packages/angular/cli/commands/new.json
index 640104d61524..90efa76056be 100644
--- a/packages/angular/cli/commands/new.json
+++ b/packages/angular/cli/commands/new.json
@@ -4,7 +4,7 @@
"description": "Creates a new workspace and an initial Angular application.",
"$longDescription": "./new.md",
- "$aliases": [ "n" ],
+ "$aliases": ["n"],
"$scope": "out",
"$type": "schematic",
"$impl": "./new-impl#NewCommand",
@@ -15,13 +15,13 @@
"properties": {
"collection": {
"type": "string",
- "aliases": [ "c" ],
+ "aliases": ["c"],
"description": "A collection of schematics to use in generating the initial application."
},
"verbose": {
"type": "boolean",
"default": false,
- "aliases": [ "v" ],
+ "aliases": ["v"],
"description": "Add more details to output logging."
}
},
diff --git a/packages/angular/cli/commands/new.md b/packages/angular/cli/commands/new.md
index 5d344b5d4312..0d8699958041 100644
--- a/packages/angular/cli/commands/new.md
+++ b/packages/angular/cli/commands/new.md
@@ -3,14 +3,14 @@ Creates and initializes a new Angular application that is the default project fo
Provides interactive prompts for optional configuration, such as adding routing support.
All prompts can safely be allowed to default.
-* The new workspace folder is given the specified project name, and contains configuration files at the top level.
+- The new workspace folder is given the specified project name, and contains configuration files at the top level.
-* By default, the files for a new initial application (with the same name as the workspace) are placed in the `src/` subfolder. Corresponding end-to-end tests are placed in the `e2e/` subfolder.
+- By default, the files for a new initial application (with the same name as the workspace) are placed in the `src/` subfolder. Corresponding end-to-end tests are placed in the `e2e/` subfolder.
-* The new application's configuration appears in the `projects` section of the `angular.json` workspace configuration file, under its project name.
+- The new application's configuration appears in the `projects` section of the `angular.json` workspace configuration file, under its project name.
-* Subsequent applications that you generate in the workspace reside in the `projects/` subfolder.
+- Subsequent applications that you generate in the workspace reside in the `projects/` subfolder.
If you plan to have multiple applications in the workspace, you can create an empty workspace by setting the `--createApplication` option to false.
You can then use `ng generate application` to create an initial application.
-This allows a workspace name different from the initial app name, and ensures that all applications reside in the `/projects` subfolder, matching the structure of the configuration file.
\ No newline at end of file
+This allows a workspace name different from the initial app name, and ensures that all applications reside in the `/projects` subfolder, matching the structure of the configuration file.
diff --git a/packages/angular/cli/commands/run-long.md b/packages/angular/cli/commands/run-long.md
index a95bbd78a27a..65a307fcd771 100644
--- a/packages/angular/cli/commands/run-long.md
+++ b/packages/angular/cli/commands/run-long.md
@@ -13,4 +13,4 @@ Execute the command using the following format.
```
ng run project:target[:configuration]
-```
\ No newline at end of file
+```
diff --git a/packages/angular/cli/commands/run.json b/packages/angular/cli/commands/run.json
index cd269a7b34b2..f4e2287dbf35 100644
--- a/packages/angular/cli/commands/run.json
+++ b/packages/angular/cli/commands/run.json
@@ -24,11 +24,10 @@
"configuration": {
"description": "One or more named builder configurations as a comma-separated list as specified in the \"configurations\" section of angular.json.\nThe builder uses the named configurations to run the given target.\nFor more information, see https://angular.io/guide/workspace-config#alternate-build-configurations.",
"type": "string",
- "aliases": [ "c" ]
+ "aliases": ["c"]
}
},
- "required": [
- ]
+ "required": []
},
{
"$ref": "./definitions.json#/definitions/base"
diff --git a/packages/angular/cli/commands/serve.json b/packages/angular/cli/commands/serve.json
index 8926362231d1..efc7ba4089ae 100644
--- a/packages/angular/cli/commands/serve.json
+++ b/packages/angular/cli/commands/serve.json
@@ -4,7 +4,7 @@
"description": "Builds and serves your app, rebuilding on file changes.",
"$longDescription": "",
- "$aliases": [ "s" ],
+ "$aliases": ["s"],
"$scope": "in",
"$type": "architect",
"$impl": "./serve-impl#ServeCommand",
diff --git a/packages/angular/cli/commands/test-long.md b/packages/angular/cli/commands/test-long.md
index 64dae312ab47..25086c174e15 100644
--- a/packages/angular/cli/commands/test-long.md
+++ b/packages/angular/cli/commands/test-long.md
@@ -1,2 +1,2 @@
Takes the name of the project, as specified in the `projects` section of the `angular.json` workspace configuration file.
-When a project name is not supplied, it will execute for all projects.
\ No newline at end of file
+When a project name is not supplied, it will execute for all projects.
diff --git a/packages/angular/cli/commands/test.json b/packages/angular/cli/commands/test.json
index a9ebb3f8044c..5fb4ce014c48 100644
--- a/packages/angular/cli/commands/test.json
+++ b/packages/angular/cli/commands/test.json
@@ -4,7 +4,7 @@
"description": "Runs unit tests in a project.",
"$longDescription": "./test-long.md",
- "$aliases": [ "t" ],
+ "$aliases": ["t"],
"$scope": "in",
"$type": "architect",
"$impl": "./test-impl#TestCommand",
diff --git a/packages/angular/cli/commands/update-impl.ts b/packages/angular/cli/commands/update-impl.ts
index da5b343c9af5..0d885305e584 100644
--- a/packages/angular/cli/commands/update-impl.ts
+++ b/packages/angular/cli/commands/update-impl.ts
@@ -43,7 +43,7 @@ const pickManifest = require('npm-pick-manifest') as (
const NG_VERSION_9_POST_MSG = colors.cyan(
'\nYour project has been updated to Angular version 9!\n' +
- 'For more info, please see: https://v9.angular.io/guide/updating-to-version-9',
+ 'For more info, please see: https://v9.angular.io/guide/updating-to-version-9',
);
const UPDATE_SCHEMATIC_COLLECTION = path.join(
@@ -68,17 +68,14 @@ export class UpdateCommand extends Command {
async initialize() {
this.packageManager = await getPackageManager(this.context.root);
- this.workflow = new NodeWorkflow(
- this.context.root,
- {
- packageManager: this.packageManager,
- // __dirname -> favor @schematics/update from this package
- // Otherwise, use packages from the active workspace (migrations)
- resolvePaths: [__dirname, this.context.root],
- schemaValidation: true,
- engineHostCreator: (options) => new SchematicEngineHost(options.resolvePaths),
- },
- );
+ this.workflow = new NodeWorkflow(this.context.root, {
+ packageManager: this.packageManager,
+ // __dirname -> favor @schematics/update from this package
+ // Otherwise, use packages from the active workspace (migrations)
+ resolvePaths: [__dirname, this.context.root],
+ schemaValidation: true,
+ engineHostCreator: (options) => new SchematicEngineHost(options.resolvePaths),
+ });
}
private async executeSchematic(
@@ -90,7 +87,7 @@ export class UpdateCommand extends Command {
let logs: string[] = [];
const files = new Set();
- const reporterSubscription = this.workflow.reporter.subscribe(event => {
+ const reporterSubscription = this.workflow.reporter.subscribe((event) => {
// Strip leading slash to prevent confusion.
const eventPath = event.path.startsWith('/') ? event.path.substr(1) : event.path;
@@ -120,11 +117,11 @@ export class UpdateCommand extends Command {
}
});
- const lifecycleSubscription = this.workflow.lifeCycle.subscribe(event => {
+ const lifecycleSubscription = this.workflow.lifeCycle.subscribe((event) => {
if (event.kind == 'end' || event.kind == 'post-tasks-start') {
if (!error) {
// Output the logging queue, no error happened.
- logs.forEach(log => this.logger.info(` ${log}`));
+ logs.forEach((log) => this.logger.info(` ${log}`));
logs = [];
}
}
@@ -147,12 +144,14 @@ export class UpdateCommand extends Command {
return { success: !error, files };
} catch (e) {
if (e instanceof UnsuccessfulWorkflowExecution) {
- this.logger.error(`${colors.symbols.cross} Migration failed. See above for further details.\n`);
+ this.logger.error(
+ `${colors.symbols.cross} Migration failed. See above for further details.\n`,
+ );
} else {
const logPath = writeErrorToLogFile(e);
this.logger.fatal(
`${colors.symbols.cross} Migration failed: ${e.message}\n` +
- ` See "${logPath}" for further details.\n`,
+ ` See "${logPath}" for further details.\n`,
);
}
@@ -170,7 +169,7 @@ export class UpdateCommand extends Command {
commit?: boolean,
): Promise {
const collection = this.workflow.engine.createCollection(collectionPath);
- const name = collection.listSchematicNames().find(name => name === migrationName);
+ const name = collection.listSchematicNames().find((name) => name === migrationName);
if (!name) {
this.logger.error(`Cannot find migration '${migrationName}' in '${packageName}'.`);
@@ -223,15 +222,13 @@ export class UpdateCommand extends Command {
return true;
}
- this.logger.info(
- colors.cyan(`** Executing migrations of package '${packageName}' **\n`),
- );
+ this.logger.info(colors.cyan(`** Executing migrations of package '${packageName}' **\n`));
return this.executePackageMigrations(migrations, packageName, commit);
}
private async executePackageMigrations(
- migrations: Iterable<{ name: string; description: string; collection: { name: string }}>,
+ migrations: Iterable<{ name: string; description: string; collection: { name: string } }>,
packageName: string,
commit = false,
): Promise {
@@ -239,8 +236,9 @@ export class UpdateCommand extends Command {
const [title, ...description] = migration.description.split('. ');
this.logger.info(
- colors.cyan(colors.symbols.pointer) + ' ' +
- colors.bold(title.endsWith('.') ? title : title + '.'),
+ colors.cyan(colors.symbols.pointer) +
+ ' ' +
+ colors.bold(title.endsWith('.') ? title : title + '.'),
);
if (description.length) {
@@ -278,10 +276,11 @@ export class UpdateCommand extends Command {
await ensureCompatibleNpm(this.context.root);
// Check if the current installed CLI version is older than the latest version.
- if (!disableVersionCheck && await this.checkCLILatestVersion(options.verbose, options.next)) {
+ if (!disableVersionCheck && (await this.checkCLILatestVersion(options.verbose, options.next))) {
this.logger.warn(
- `The installed local Angular CLI version is older than the latest ${options.next ? 'pre-release' : 'stable'} version.\n` +
- 'Installing a temporary version to perform the update.',
+ `The installed local Angular CLI version is older than the latest ${
+ options.next ? 'pre-release' : 'stable'
+ } version.\n` + 'Installing a temporary version to perform the update.',
);
return runTempPackageBin(
@@ -299,9 +298,10 @@ export class UpdateCommand extends Command {
};
if (options.all) {
- const updateCmd = this.packageManager === PackageManager.Yarn
- ? `'yarn upgrade-interactive' or 'yarn upgrade'`
- : `'${this.packageManager} update'`;
+ const updateCmd =
+ this.packageManager === PackageManager.Yarn
+ ? `'yarn upgrade-interactive' or 'yarn upgrade'`
+ : `'${this.packageManager} update'`;
this.logger.warn(`
'--all' functionality has been removed as updating multiple packages at once is not recommended.
@@ -324,7 +324,7 @@ export class UpdateCommand extends Command {
return 1;
}
- if (packages.some(v => v.name === packageIdentifier.name)) {
+ if (packages.some((v) => v.name === packageIdentifier.name)) {
this.logger.error(`Duplicate package '${packageIdentifier.name}' specified.`);
return 1;
@@ -391,7 +391,9 @@ export class UpdateCommand extends Command {
if (options.migrateOnly) {
if (!options.from && typeof options.migrateOnly !== 'string') {
- this.logger.error('"from" option is required when using the "migrate-only" option without a migration name.');
+ this.logger.error(
+ '"from" option is required when using the "migrate-only" option without a migration name.',
+ );
return 1;
} else if (packages.length !== 1) {
@@ -508,10 +510,10 @@ export class UpdateCommand extends Command {
if (success) {
if (
- packageName === '@angular/core'
- && options.from
- && +options.from.split('.')[0] < 9
- && (options.to || packageNode.version).split('.')[0] === '9'
+ packageName === '@angular/core' &&
+ options.from &&
+ +options.from.split('.')[0] < 9 &&
+ (options.to || packageNode.version).split('.')[0] === '9'
) {
this.logger.info(NG_VERSION_9_POST_MSG);
}
@@ -622,10 +624,12 @@ export class UpdateCommand extends Command {
};
const updateTo = updateVersions[currentMajorVersion];
- this.logger.error('Updating multiple major versions at once is not recommended. ' +
- `Run 'ng update @angular/cli@${updateTo}' in your workspace directory ` +
- `to update to latest '${updateTo}.x' version of '@angular/cli'.\n\n` +
- 'For more information about the update process, see https://update.angular.io/.');
+ this.logger.error(
+ 'Updating multiple major versions at once is not recommended. ' +
+ `Run 'ng update @angular/cli@${updateTo}' in your workspace directory ` +
+ `to update to latest '${updateTo}.x' version of '@angular/cli'.\n\n` +
+ 'For more information about the update process, see https://update.angular.io/.',
+ );
return 1;
}
@@ -653,7 +657,8 @@ export class UpdateCommand extends Command {
if (success && options.createCommits) {
const committed = this.commit(
- `Angular CLI update for packages - ${packagesToUpdate.join(', ')}`);
+ `Angular CLI update for packages - ${packagesToUpdate.join(', ')}`,
+ );
if (!committed) {
return 1;
}
@@ -744,7 +749,14 @@ export class UpdateCommand extends Command {
}
}
- if (migrations.some(m => m.package === '@angular/core' && m.to.split('.')[0] === '9' && +m.from.split('.')[0] < 9)) {
+ if (
+ migrations.some(
+ (m) =>
+ m.package === '@angular/core' &&
+ m.to.split('.')[0] === '9' &&
+ +m.from.split('.')[0] < 9,
+ )
+ ) {
this.logger.info(NG_VERSION_9_POST_MSG);
}
}
@@ -776,8 +788,7 @@ export class UpdateCommand extends Command {
try {
createCommit(message);
} catch (err) {
- this.logger.error(
- `Failed to commit update (${message}):\n${err.stderr}`);
+ this.logger.error(`Failed to commit update (${message}):\n${err.stderr}`);
return false;
}
@@ -786,8 +797,7 @@ export class UpdateCommand extends Command {
const hash = findCurrentGitSha();
const shortMessage = message.split('\n')[0];
if (hash) {
- this.logger.info(` Committed migration step (${getShortHash(hash)}): ${
- shortMessage}.`);
+ this.logger.info(` Committed migration step (${getShortHash(hash)}): ${shortMessage}.`);
} else {
// Commit was successful, but reading the hash was not. Something weird happened,
// but nothing that would stop the update. Just log the weirdness and continue.
@@ -800,7 +810,10 @@ export class UpdateCommand extends Command {
private checkCleanGit(): boolean {
try {
- const topLevel = execSync('git rev-parse --show-toplevel', { encoding: 'utf8', stdio: 'pipe' });
+ const topLevel = execSync('git rev-parse --show-toplevel', {
+ encoding: 'utf8',
+ stdio: 'pipe',
+ });
const result = execSync('git status --porcelain', { encoding: 'utf8', stdio: 'pipe' });
if (result.trim().length === 0) {
return true;
@@ -825,7 +838,7 @@ export class UpdateCommand extends Command {
/**
* Checks if the current installed CLI version is older than the latest version.
* @returns `true` when the installed version is older.
- */
+ */
private async checkCLILatestVersion(verbose = false, next = false): Promise {
const { version: installedCLIVersion } = require('../package.json');
@@ -871,7 +884,7 @@ function createCommit(message: string) {
*/
function findCurrentGitSha(): string | null {
try {
- const hash = execSync('git rev-parse HEAD', {encoding: 'utf8', stdio: 'pipe'});
+ const hash = execSync('git rev-parse HEAD', { encoding: 'utf8', stdio: 'pipe' });
return hash.trim();
} catch {
diff --git a/packages/angular/cli/commands/version-impl.ts b/packages/angular/cli/commands/version-impl.ts
index cdcb7e971139..ba2e07f7e293 100644
--- a/packages/angular/cli/commands/version-impl.ts
+++ b/packages/angular/cli/commands/version-impl.ts
@@ -51,19 +51,16 @@ export class VersionCommand extends Command {
];
const versions = packageNames
- .filter(x => patterns.some(p => p.test(x)))
- .reduce(
- (acc, name) => {
- if (name in acc) {
- return acc;
- }
+ .filter((x) => patterns.some((p) => p.test(x)))
+ .reduce((acc, name) => {
+ if (name in acc) {
+ return acc;
+ }
- acc[name] = this.getVersion(name);
+ acc[name] = this.getVersion(name);
- return acc;
- },
- {} as { [module: string]: string },
- );
+ return acc;
+ }, {} as { [module: string]: string });
const ngCliVersion = cliPackage.version;
let angularCoreVersion = '';
@@ -100,7 +97,7 @@ export class VersionCommand extends Command {
|___/
`
.split('\n')
- .map(x => colors.red(x))
+ .map((x) => colors.red(x))
.join('\n');
this.logger.info(asciiArt);
@@ -132,7 +129,7 @@ export class VersionCommand extends Command {
Package${namePad.slice(7)}Version
-------${namePad.replace(/ /g, '-')}------------------
${Object.keys(versions)
- .map(module => `${module}${namePad.slice(module.length)}${versions[module]}`)
+ .map((module) => `${module}${namePad.slice(module.length)}${versions[module]}`)
.sort()
.join('\n')}
`.replace(/^ {6}/gm, ''),
@@ -145,7 +142,7 @@ export class VersionCommand extends Command {
// Try to find the package in the workspace
try {
- packagePath = require.resolve(`${moduleName}/package.json`, { paths: [ this.context.root ]});
+ packagePath = require.resolve(`${moduleName}/package.json`, { paths: [this.context.root] });
} catch {}
// If not found, try to find within the CLI
diff --git a/packages/angular/cli/commands/version.json b/packages/angular/cli/commands/version.json
index 657cb14dce71..8f4c3ff1fdd1 100644
--- a/packages/angular/cli/commands/version.json
+++ b/packages/angular/cli/commands/version.json
@@ -4,12 +4,10 @@
"description": "Outputs Angular CLI version.",
"$longDescription": "",
- "$aliases": [ "v" ],
+ "$aliases": ["v"],
"$scope": "all",
"$impl": "./version-impl#VersionCommand",
"type": "object",
- "allOf": [
- { "$ref": "./definitions.json#/definitions/base" }
- ]
+ "allOf": [{ "$ref": "./definitions.json#/definitions/base" }]
}
diff --git a/packages/angular/cli/lib/cli/index.ts b/packages/angular/cli/lib/cli/index.ts
index 7cea5663c8d6..bb187c83f208 100644
--- a/packages/angular/cli/lib/cli/index.ts
+++ b/packages/angular/cli/lib/cli/index.ts
@@ -17,41 +17,38 @@ import { findWorkspaceFile } from '../../utilities/project';
export { VERSION, Version } from '../../models/version';
const debugEnv = process.env['NG_DEBUG'];
-const isDebug =
- debugEnv !== undefined &&
- debugEnv !== '0' &&
- debugEnv.toLowerCase() !== 'false';
+const isDebug = debugEnv !== undefined && debugEnv !== '0' && debugEnv.toLowerCase() !== 'false';
// tslint:disable: no-console
-export default async function(options: { testing?: boolean; cliArgs: string[] }) {
+export default async function (options: { testing?: boolean; cliArgs: string[] }) {
// This node version check ensures that the requirements of the project instance of the CLI are met
- const version = process.versions.node.split('.').map(part => Number(part));
+ const version = process.versions.node.split('.').map((part) => Number(part));
if (version[0] < 12 || (version[0] === 12 && version[1] < 14)) {
process.stderr.write(
`Node.js version ${process.version} detected.\n` +
- 'The Angular CLI requires a minimum v12.14.\n\n' +
- 'Please update your Node.js version or visit https://nodejs.org/ for additional instructions.\n',
+ 'The Angular CLI requires a minimum v12.14.\n\n' +
+ 'Please update your Node.js version or visit https://nodejs.org/ for additional instructions.\n',
);
return 3;
}
const logger = createConsoleLogger(isDebug, process.stdout, process.stderr, {
- info: s => (colors.enabled ? s : removeColor(s)),
- debug: s => (colors.enabled ? s : removeColor(s)),
- warn: s => (colors.enabled ? colors.bold.yellow(s) : removeColor(s)),
- error: s => (colors.enabled ? colors.bold.red(s) : removeColor(s)),
- fatal: s => (colors.enabled ? colors.bold.red(s) : removeColor(s)),
+ info: (s) => (colors.enabled ? s : removeColor(s)),
+ debug: (s) => (colors.enabled ? s : removeColor(s)),
+ warn: (s) => (colors.enabled ? colors.bold.yellow(s) : removeColor(s)),
+ error: (s) => (colors.enabled ? colors.bold.red(s) : removeColor(s)),
+ fatal: (s) => (colors.enabled ? colors.bold.red(s) : removeColor(s)),
});
// Redirect console to logger
- console.info = console.log = function(...args) {
+ console.info = console.log = function (...args) {
logger.info(format(...args));
};
- console.warn = function(...args) {
+ console.warn = function (...args) {
logger.warn(format(...args));
};
- console.error = function(...args) {
+ console.error = function (...args) {
logger.error(format(...args));
};
diff --git a/packages/angular/cli/lib/config/workspace-schema.json b/packages/angular/cli/lib/config/workspace-schema.json
index 43bd1e07ddb4..f6d816ea024e 100644
--- a/packages/angular/cli/lib/config/workspace-schema.json
+++ b/packages/angular/cli/lib/config/workspace-schema.json
@@ -27,7 +27,7 @@
"projects": {
"type": "object",
"patternProperties": {
- "^(?:@[a-zA-Z0-9_-]+\/)?[a-zA-Z0-9_-]+$": {
+ "^(?:@[a-zA-Z0-9_-]+/)?[a-zA-Z0-9_-]+$": {
"$ref": "#/definitions/project"
}
},
@@ -35,9 +35,7 @@
}
},
"additionalProperties": false,
- "required": [
- "version"
- ],
+ "required": ["version"],
"definitions": {
"cliOptions": {
"type": "object",
@@ -49,12 +47,7 @@
"packageManager": {
"description": "Specify which package manager tool to use.",
"type": "string",
- "enum": [
- "npm",
- "cnpm",
- "yarn",
- "pnpm"
- ]
+ "enum": ["npm", "cnpm", "yarn", "pnpm"]
},
"warnings": {
"description": "Control CLI specific console warnings",
@@ -67,10 +60,7 @@
}
},
"analytics": {
- "type": [
- "boolean",
- "string"
- ],
+ "type": ["boolean", "string"],
"description": "Share anonymous usage data with the Angular Team at Google."
},
"analyticsSharing": {
@@ -173,10 +163,7 @@
"projectType": {
"type": "string",
"description": "Project type.",
- "enum": [
- "application",
- "library"
- ]
+ "enum": ["application", "library"]
},
"architect": {
"type": "object",
@@ -191,37 +178,23 @@
}
}
},
- "required": [
- "root",
- "projectType"
- ],
+ "required": ["root", "projectType"],
"anyOf": [
{
- "required": [
- "architect"
- ],
+ "required": ["architect"],
"not": {
- "required": [
- "targets"
- ]
+ "required": ["targets"]
}
},
{
- "required": [
- "targets"
- ],
+ "required": ["targets"],
"not": {
- "required": [
- "architect"
- ]
+ "required": ["architect"]
}
},
{
"not": {
- "required": [
- "targets",
- "architect"
- ]
+ "required": ["targets", "architect"]
}
}
],
@@ -351,9 +324,7 @@
}
}
},
- "required": [
- "builder"
- ]
+ "required": ["builder"]
},
{
"type": "object",
@@ -561,9 +532,7 @@
"$ref": "#/definitions/schematicOptions"
}
},
- "required": [
- "version"
- ]
+ "required": ["version"]
}
}
-}
\ No newline at end of file
+}
diff --git a/packages/angular/cli/lib/init.ts b/packages/angular/cli/lib/init.ts
index cb1764824c87..598b628978a8 100644
--- a/packages/angular/cli/lib/init.ts
+++ b/packages/angular/cli/lib/init.ts
@@ -91,9 +91,7 @@ if (process.env['NG_CLI_PROFILING']) {
.version;
} catch (error) {
// tslint:disable-next-line no-console
- console.error(
- 'Version mismatch check skipped. Unable to retrieve local version: ' + error,
- );
+ console.error('Version mismatch check skipped. Unable to retrieve local version: ' + error);
}
}
@@ -134,17 +132,19 @@ if (process.env['NG_CLI_PROFILING']) {
}
return cli;
-})().then(cli => {
- return cli({
- cliArgs: process.argv.slice(2),
- inputStream: process.stdin,
- outputStream: process.stdout,
+})()
+ .then((cli) => {
+ return cli({
+ cliArgs: process.argv.slice(2),
+ inputStream: process.stdin,
+ outputStream: process.stdout,
+ });
+ })
+ .then((exitCode: number) => {
+ process.exit(exitCode);
+ })
+ .catch((err: Error) => {
+ // tslint:disable-next-line no-console
+ console.error('Unknown error: ' + err.toString());
+ process.exit(127);
});
-}).then((exitCode: number) => {
- process.exit(exitCode);
-})
-.catch((err: Error) => {
- // tslint:disable-next-line no-console
- console.error('Unknown error: ' + err.toString());
- process.exit(127);
-});
diff --git a/packages/angular/cli/models/analytics-collector.ts b/packages/angular/cli/models/analytics-collector.ts
index f68745040a5e..da775363f34f 100644
--- a/packages/angular/cli/models/analytics-collector.ts
+++ b/packages/angular/cli/models/analytics-collector.ts
@@ -85,10 +85,7 @@ export class AnalyticsCollector implements analytics.Analytics {
private readonly parameters: Record = {};
private readonly analyticsLogDebug = debug('ng:analytics:log');
- constructor(
- trackingId: string,
- userId: string,
- ) {
+ constructor(trackingId: string, userId: string) {
// API Version
this.parameters['v'] = '1';
// User ID
@@ -113,8 +110,12 @@ export class AnalyticsCollector implements analytics.Analytics {
this.parameters['cd' + analytics.NgCliAnalyticsDimensions.CpuCount] = os.cpus().length;
// Get the first CPU's speed. It's very rare to have multiple CPUs of different speed (in most
// non-ARM configurations anyway), so that's all we care about.
- this.parameters['cd' + analytics.NgCliAnalyticsDimensions.CpuSpeed] = Math.floor(os.cpus()[0].speed);
- this.parameters['cd' + analytics.NgCliAnalyticsDimensions.RamInGigabytes] = Math.round(os.totalmem() / (1024 * 1024 * 1024));
+ this.parameters['cd' + analytics.NgCliAnalyticsDimensions.CpuSpeed] = Math.floor(
+ os.cpus()[0].speed,
+ );
+ this.parameters['cd' + analytics.NgCliAnalyticsDimensions.RamInGigabytes] = Math.round(
+ os.totalmem() / (1024 * 1024 * 1024),
+ );
this.parameters['cd' + analytics.NgCliAnalyticsDimensions.NodeVersion] = nodeVersion;
}
@@ -128,7 +129,12 @@ export class AnalyticsCollector implements analytics.Analytics {
this.addToQueue('pageview', { dp, dh, dt, metrics, dimensions });
}
- timing(utc: string, utv: string, utt: string | number, options: analytics.TimingOptions = {}): void {
+ timing(
+ utc: string,
+ utv: string,
+ utt: string | number,
+ options: analytics.TimingOptions = {},
+ ): void {
const { label: utl, metrics, dimensions } = options;
this.addToQueue('timing', { utc, utv, utt, utl, metrics, dimensions });
}
@@ -163,7 +169,10 @@ export class AnalyticsCollector implements analytics.Analytics {
private addToQueue(eventType: 'pageview', parameters: PageviewParameters): void;
private addToQueue(eventType: 'timing', parameters: TimingParameters): void;
private addToQueue(eventType: 'screenview', parameters: ScreenviewParameters): void;
- private addToQueue(eventType: 'event' | 'pageview' | 'timing' | 'screenview', parameters: BaseParameters): void {
+ private addToQueue(
+ eventType: 'event' | 'pageview' | 'timing' | 'screenview',
+ parameters: BaseParameters,
+ ): void {
const { metrics, dimensions, ...restParameters } = parameters;
const data = {
...this.parameters,
@@ -180,21 +189,26 @@ export class AnalyticsCollector implements analytics.Analytics {
this.analyticsLogDebug('send event: %j', data);
return new Promise((resolve, reject) => {
- const request = https.request({
- host: 'www.google-analytics.com',
- method: 'POST',
- path: data.length > 1 ? '/batch' : '/collect',
- }, response => {
- if (response.statusCode !== 200) {
- reject(new Error(`Analytics reporting failed with status code: ${response.statusCode}.`));
-
- return;
- }
- });
+ const request = https.request(
+ {
+ host: 'www.google-analytics.com',
+ method: 'POST',
+ path: data.length > 1 ? '/batch' : '/collect',
+ },
+ (response) => {
+ if (response.statusCode !== 200) {
+ reject(
+ new Error(`Analytics reporting failed with status code: ${response.statusCode}.`),
+ );
+
+ return;
+ }
+ },
+ );
request.on('error', reject);
- const queryParameters = data.map(p => querystring.stringify(p)).join('\n');
+ const queryParameters = data.map((p) => querystring.stringify(p)).join('\n');
request.write(queryParameters);
request.end(resolve);
});
@@ -204,12 +218,14 @@ export class AnalyticsCollector implements analytics.Analytics {
* Creates the dimension and metrics variables to add to the queue.
* @private
*/
- private customVariables(options: analytics.CustomDimensionsAndMetricsOptions): Record {
+ private customVariables(
+ options: analytics.CustomDimensionsAndMetricsOptions,
+ ): Record {
const additionals: Record = {};
const { dimensions, metrics } = options;
- dimensions?.forEach((v, i) => additionals[`cd${i}`] = v);
- metrics?.forEach((v, i) => additionals[`cm${i}`] = v);
+ dimensions?.forEach((v, i) => (additionals[`cd${i}`] = v));
+ metrics?.forEach((v, i) => (additionals[`cm${i}`] = v));
return additionals;
}
@@ -282,7 +298,6 @@ function _buildUserAgentString() {
}
}
-
/**
* Get a language code.
* @private
@@ -311,7 +326,7 @@ function _getWindowsLanguageCode(): string | undefined {
// This is true on Windows XP, 7, 8 and 10 AFAIK. Would return empty string or fail if it
// doesn't work.
return execSync('wmic.exe os get locale').toString().trim();
- } catch { }
+ } catch {}
return undefined;
}
diff --git a/packages/angular/cli/models/analytics.ts b/packages/angular/cli/models/analytics.ts
index 037ff0599cf9..2002c9ad06c0 100644
--- a/packages/angular/cli/models/analytics.ts
+++ b/packages/angular/cli/models/analytics.ts
@@ -51,7 +51,7 @@ export const analyticsPackageSafelist = [
];
export function isPackageNameSafeForAnalytics(name: string): boolean {
- return analyticsPackageSafelist.some(pattern => {
+ return analyticsPackageSafelist.some((pattern) => {
if (typeof pattern == 'string') {
return pattern === name;
} else {
@@ -86,7 +86,6 @@ export function setAnalyticsConfig(level: 'global' | 'local', value: string | bo
config.save();
analyticsDebug('done');
-
}
/**
@@ -207,7 +206,7 @@ export async function hasGlobalAnalyticsConfiguration(): Promise {
if (analyticsConfig !== null && analyticsConfig !== undefined) {
return true;
}
- } catch { }
+ } catch {}
return false;
}
@@ -278,14 +277,13 @@ export async function getGlobalAnalytics(): Promise {
try {
const globalWorkspace = await getWorkspace('local');
- const analyticsConfig: string | undefined | null | { uid?: string } = globalWorkspace
- && globalWorkspace.getCli()
- && globalWorkspace.getCli()['analytics'];
+ const analyticsConfig: string | undefined | null | { uid?: string } =
+ globalWorkspace && globalWorkspace.getCli() && globalWorkspace.getCli()['analytics'];
if (analyticsConfig !== undefined) {
return true;
}
- } catch { }
+ } catch {}
return false;
}
@@ -300,7 +298,9 @@ export async function getWorkspaceAnalytics(): Promise {
this._registry = new json.schema.CoreSchemaRegistry();
this._registry.addPostTransform(json.schema.transforms.addUndefinedDefaults);
- this._registry.useXDeprecatedProvider(msg => this.logger.warn(msg));
+ this._registry.useXDeprecatedProvider((msg) => this.logger.warn(msg));
if (!this.workspace) {
this.logger.fatal('A workspace is required for this command.');
@@ -47,7 +47,10 @@ export abstract class ArchitectCommand<
return 1;
}
- this._architectHost = new WorkspaceNodeModulesArchitectHost(this.workspace, this.workspace.basePath);
+ this._architectHost = new WorkspaceNodeModulesArchitectHost(
+ this.workspace,
+ this.workspace.basePath,
+ );
this._architect = new Architect(this._architectHost, this._registry);
if (!this.target) {
@@ -82,14 +85,18 @@ export abstract class ArchitectCommand<
}
if (targetProjectNames.length === 0) {
- this.logger.fatal(this.missingTargetError || `No projects support the '${this.target}' target.`);
+ this.logger.fatal(
+ this.missingTargetError || `No projects support the '${this.target}' target.`,
+ );
return 1;
}
if (projectName && !targetProjectNames.includes(projectName)) {
- this.logger.fatal(this.missingTargetError ||
- `Project '${projectName}' does not support the '${this.target}' target.`);
+ this.logger.fatal(
+ this.missingTargetError ||
+ `Project '${projectName}' does not support the '${this.target}' target.`,
+ );
return 1;
}
@@ -117,7 +124,9 @@ export abstract class ArchitectCommand<
const builderLeftovers = parsedOptions['--'] || [];
leftoverMap.set(name, { optionDefs, parsedOptions });
- potentialProjectNames = new Set(builderLeftovers.filter(x => potentialProjectNames.has(x)));
+ potentialProjectNames = new Set(
+ builderLeftovers.filter((x) => potentialProjectNames.has(x)),
+ );
}
if (potentialProjectNames.size === 1) {
@@ -170,7 +179,9 @@ export abstract class ArchitectCommand<
// This is a special case where we just return.
return;
} else {
- this.logger.fatal(this.missingTargetError || 'Cannot determine project or target for command.');
+ this.logger.fatal(
+ this.missingTargetError || 'Cannot determine project or target for command.',
+ );
return 1;
}
@@ -203,10 +214,7 @@ export abstract class ArchitectCommand<
return await this.runArchitectTarget(options);
}
- protected async runSingleTarget(
- target: Target,
- targetOptions: string[],
- ) {
+ protected async runSingleTarget(target: Target, targetOptions: string[]) {
// We need to build the builderSpec twice because architect does not understand
// overrides separately (getting the configuration builds the whole project, including
// overrides).
@@ -222,7 +230,7 @@ export abstract class ArchitectCommand<
typeof builderDesc.optionSchema === 'object' && builderDesc.optionSchema.additionalProperties;
if (overrides['--'] && !allowAdditionalProperties) {
- (overrides['--'] || []).forEach(additional => {
+ (overrides['--'] || []).forEach((additional) => {
this.logger.fatal(`Unknown option: '${additional.split(/=/)[0]}'`);
});
@@ -230,7 +238,7 @@ export abstract class ArchitectCommand<
}
await this.reportAnalytics([this.description.name], {
- ...await this._architectHost.getOptionsForTarget(target) as unknown as T,
+ ...(((await this._architectHost.getOptionsForTarget(target)) as unknown) as T),
...overrides,
});
@@ -261,10 +269,7 @@ export abstract class ArchitectCommand<
// Running them in parallel would jumble the log messages.
let result = 0;
for (const project of this.getProjectNamesByTarget(this.target)) {
- result |= await this.runSingleTarget(
- { ...targetSpec, project } as Target,
- extra,
- );
+ result |= await this.runSingleTarget({ ...targetSpec, project } as Target, extra);
}
return result;
@@ -341,12 +346,15 @@ export abstract class ArchitectCommand<
if (commandOptions.prod) {
// The --prod flag will always be the first configuration, available to be overwritten
// by following configurations.
- this.logger.warn('Option "--prod" is deprecated: Use "--configuration production" instead.');
+ this.logger.warn(
+ 'Option "--prod" is deprecated: Use "--configuration production" instead.',
+ );
configuration = 'production';
}
if (commandOptions.configuration) {
- configuration =
- `${configuration ? `${configuration},` : ''}${commandOptions.configuration}`;
+ configuration = `${configuration ? `${configuration},` : ''}${
+ commandOptions.configuration
+ }`;
}
}
diff --git a/packages/angular/cli/models/command-runner.ts b/packages/angular/cli/models/command-runner.ts
index 3a7401b4852e..0b8b01fe4baa 100644
--- a/packages/angular/cli/models/command-runner.ts
+++ b/packages/angular/cli/models/command-runner.ts
@@ -61,7 +61,10 @@ export interface CommandMapOptions {
* Create the analytics instance.
* @private
*/
-async function _createAnalytics(workspace: boolean, skipPrompt = false): Promise {
+async function _createAnalytics(
+ workspace: boolean,
+ skipPrompt = false,
+): Promise {
let config = await getGlobalAnalytics();
// If in workspace and global analytics is enabled, defer to workspace level
if (workspace && config) {
@@ -119,7 +122,9 @@ export async function runCommand(
logger: logging.Logger,
workspace: AngularWorkspace | undefined,
commands: CommandMapOptions = standardCommands,
- options: { analytics?: analytics.Analytics; currentDirectory: string } = { currentDirectory: process.cwd() },
+ options: { analytics?: analytics.Analytics; currentDirectory: string } = {
+ currentDirectory: process.cwd(),
+ },
): Promise {
// This registry is exclusively used for flattening schemas, and not for validating.
const registry = new schema.CoreSchemaRegistry([]);
@@ -189,7 +194,7 @@ export async function runCommand(
const aliasDesc = await loadCommandDescription(name, commands[name], registry);
const aliases = aliasDesc.aliases;
- if (aliases && aliases.some(alias => alias === commandName)) {
+ if (aliases && aliases.some((alias) => alias === commandName)) {
commandName = name;
description = aliasDesc;
break;
@@ -233,8 +238,7 @@ export async function runCommand(
});
const analytics =
- options.analytics ||
- (await _createAnalytics(!!workspace, description.name === 'update'));
+ options.analytics || (await _createAnalytics(!!workspace, description.name === 'update'));
const context = {
workspace,
analytics,
diff --git a/packages/angular/cli/models/command.ts b/packages/angular/cli/models/command.ts
index 7f334aefe748..b9f49d0ec1a0 100644
--- a/packages/angular/cli/models/command.ts
+++ b/packages/angular/cli/models/command.ts
@@ -53,9 +53,8 @@ export abstract class Command
}
async printJsonHelp(): Promise {
- const replacer = (key: string, value: string) => key === 'name'
- ? strings.dasherize(value)
- : value;
+ const replacer = (key: string, value: string) =>
+ key === 'name' ? strings.dasherize(value) : value;
this.logger.info(JSON.stringify(this.description, replacer, 2));
return 0;
@@ -65,10 +64,11 @@ export abstract class Command
this.logger.info(this.description.description);
const name = this.description.name;
- const args = this.description.options.filter(x => x.positional !== undefined);
- const opts = this.description.options.filter(x => x.positional === undefined);
+ const args = this.description.options.filter((x) => x.positional !== undefined);
+ const opts = this.description.options.filter((x) => x.positional === undefined);
- const argDisplay = args && args.length > 0 ? ' ' + args.map(a => `<${a.name}>`).join(' ') : '';
+ const argDisplay =
+ args && args.length > 0 ? ' ' + args.map((a) => `<${a.name}>`).join(' ') : '';
const optionsDisplay = opts && opts.length > 0 ? ` [options]` : ``;
this.logger.info(`usage: ng ${name}${argDisplay}${optionsDisplay}`);
@@ -82,15 +82,15 @@ export abstract class Command
}
protected async printHelpOptions(options: Option[] = this.description.options) {
- const args = options.filter(opt => opt.positional !== undefined);
- const opts = options.filter(opt => opt.positional === undefined);
+ const args = options.filter((opt) => opt.positional !== undefined);
+ const opts = options.filter((opt) => opt.positional === undefined);
const formatDescription = (description: string) =>
` ${description.replace(/\n/g, '\n ')}`;
if (args.length > 0) {
this.logger.info(`arguments:`);
- args.forEach(o => {
+ args.forEach((o) => {
this.logger.info(` ${colors.cyan(o.name)}`);
if (o.description) {
this.logger.info(formatDescription(o.description));
@@ -103,12 +103,12 @@ export abstract class Command
}
this.logger.info(`options:`);
opts
- .filter(o => !o.hidden)
+ .filter((o) => !o.hidden)
.sort((a, b) => a.name.localeCompare(b.name))
- .forEach(o => {
+ .forEach((o) => {
const aliases =
o.aliases && o.aliases.length > 0
- ? '(' + o.aliases.map(a => `-${a}`).join(' ') + ')'
+ ? '(' + o.aliases.map((a) => `-${a}`).join(' ') + ')'
: '';
this.logger.info(` ${colors.cyan('--' + strings.dasherize(o.name))} ${aliases}`);
if (o.description) {
diff --git a/packages/angular/cli/models/interface.ts b/packages/angular/cli/models/interface.ts
index cb4bde347ce8..9c908d913247 100644
--- a/packages/angular/cli/models/interface.ts
+++ b/packages/angular/cli/models/interface.ts
@@ -39,7 +39,7 @@ export interface CommandInterface {
* Command constructor.
*/
export interface CommandConstructor {
- new(
+ new (
context: CommandContext,
description: CommandDescription,
logger: logging.Logger,
@@ -158,7 +158,7 @@ export interface Option {
/**
* Deprecation. If this flag is not false a warning will be shown on the console. Either `true`
* or a string to show the user as a notice.
- */
+ */
deprecated?: boolean | string;
}
diff --git a/packages/angular/cli/models/parser.ts b/packages/angular/cli/models/parser.ts
index 66e81aed78c7..b1e98d0b3f2a 100644
--- a/packages/angular/cli/models/parser.ts
+++ b/packages/angular/cli/models/parser.ts
@@ -9,7 +9,6 @@
import { BaseException, logging, strings } from '@angular-devkit/core';
import { Arguments, Option, OptionType, Value } from './interface';
-
export class ParseArgumentException extends BaseException {
constructor(
public readonly comments: string[],
@@ -20,7 +19,6 @@ export class ParseArgumentException extends BaseException {
}
}
-
function _coerceType(str: string | undefined, type: OptionType, v?: Value): Value | undefined {
switch (type) {
case OptionType.Any:
@@ -31,8 +29,8 @@ function _coerceType(str: string | undefined, type: OptionType, v?: Value): Valu
return _coerceType(str, OptionType.Boolean, v) !== undefined
? _coerceType(str, OptionType.Boolean, v)
: _coerceType(str, OptionType.Number, v) !== undefined
- ? _coerceType(str, OptionType.Number, v)
- : _coerceType(str, OptionType.String, v);
+ ? _coerceType(str, OptionType.Number, v)
+ : _coerceType(str, OptionType.String, v);
case OptionType.String:
return str || '';
@@ -66,8 +64,8 @@ function _coerceType(str: string | undefined, type: OptionType, v?: Value): Valu
return Array.isArray(v)
? v.concat(str || '')
: v === undefined
- ? [str || '']
- : [v + '', str || ''];
+ ? [str || '']
+ : [v + '', str || ''];
default:
return undefined;
@@ -93,18 +91,15 @@ function _coerce(str: string | undefined, o: Option | null, v?: Value): Value |
}
}
-
function _getOptionFromName(name: string, options: Option[]): Option | undefined {
- const camelName = /(-|_)/.test(name)
- ? strings.camelize(name)
- : name;
+ const camelName = /(-|_)/.test(name) ? strings.camelize(name) : name;
for (const option of options) {
if (option.name === name || option.name === camelName) {
return option;
}
- if (option.aliases.some(x => x === name || x === camelName)) {
+ if (option.aliases.some((x) => x === name || x === camelName)) {
return option;
}
}
@@ -121,14 +116,21 @@ function _removeLeadingDashes(key: string): string {
function _assignOption(
arg: string,
nextArg: string | undefined,
- { options, parsedOptions, leftovers, ignored, errors, warnings }: {
- options: Option[],
- parsedOptions: Arguments,
- positionals: string[],
- leftovers: string[],
- ignored: string[],
- errors: string[],
- warnings: string[],
+ {
+ options,
+ parsedOptions,
+ leftovers,
+ ignored,
+ errors,
+ warnings,
+ }: {
+ options: Option[];
+ parsedOptions: Arguments;
+ positionals: string[];
+ leftovers: string[];
+ ignored: string[];
+ errors: string[];
+ warnings: string[];
},
) {
const from = arg.startsWith('--') ? 2 : 1;
@@ -192,9 +194,9 @@ function _assignOption(
if (parsedOptions[option.name] !== v) {
if (parsedOptions[option.name] !== undefined && option.type !== OptionType.Array) {
warnings.push(
- `Option ${JSON.stringify(option.name)} was already specified with value `
- + `${JSON.stringify(parsedOptions[option.name])}. The new value ${JSON.stringify(v)} `
- + `will override it.`,
+ `Option ${JSON.stringify(option.name)} was already specified with value ` +
+ `${JSON.stringify(parsedOptions[option.name])}. The new value ${JSON.stringify(v)} ` +
+ `will override it.`,
);
}
@@ -203,7 +205,7 @@ function _assignOption(
} else {
let error = `Argument ${key} could not be parsed using value ${JSON.stringify(value)}.`;
if (option.enum) {
- error += ` Valid values are: ${option.enum.map(x => JSON.stringify(x)).join(', ')}.`;
+ error += ` Valid values are: ${option.enum.map((x) => JSON.stringify(x)).join(', ')}.`;
} else {
error += `Valid type(s) is: ${(option.types || [option.type]).join(', ')}`;
}
@@ -215,7 +217,7 @@ function _assignOption(
if (/^[a-z]+[A-Z]/.test(key)) {
warnings.push(
'Support for camel case arguments has been deprecated and will be removed in a future major version.\n' +
- `Use '--${strings.dasherize(key)}' instead of '--${key}'.`,
+ `Use '--${strings.dasherize(key)}' instead of '--${key}'.`,
);
}
}
@@ -223,7 +225,6 @@ function _assignOption(
return consumedNextArg;
}
-
/**
* Parse the arguments in a consistent way, but without having any option definition. This tries
* to assess what the user wants in a free form. For example, using `--name=false` will set the
@@ -261,7 +262,7 @@ export function parseFreeFormArguments(args: string[]): Arguments {
parsedOptions[name] = v;
}
} else if (arg.startsWith('-')) {
- arg.split('').forEach(x => parsedOptions[x] = true);
+ arg.split('').forEach((x) => (parsedOptions[x] = true));
} else {
leftovers.push(arg);
}
@@ -274,7 +275,6 @@ export function parseFreeFormArguments(args: string[]): Arguments {
return parsedOptions;
}
-
/**
* Parse the arguments in a consistent way, from a list of standardized options.
* The result object will have a key per option name, with the `_` key reserved for positional
@@ -357,7 +357,7 @@ export function parseArguments(
// simpler.
if (positionals.length > 0) {
let pos = 0;
- for (let i = 0; i < positionals.length;) {
+ for (let i = 0; i < positionals.length; ) {
let found = false;
let incrementPos = false;
let incrementI = true;
@@ -394,7 +394,7 @@ export function parseArguments(
}
if (warnings.length > 0 && logger) {
- warnings.forEach(message => logger.warn(message));
+ warnings.forEach((message) => logger.warn(message));
}
if (errors.length > 0) {
diff --git a/packages/angular/cli/models/parser_spec.ts b/packages/angular/cli/models/parser_spec.ts
index e57b852387a4..8cb844edb4f6 100644
--- a/packages/angular/cli/models/parser_spec.ts
+++ b/packages/angular/cli/models/parser_spec.ts
@@ -13,27 +13,47 @@ import { ParseArgumentException, parseArguments } from './parser';
describe('parseArguments', () => {
const options: Option[] = [
- { name: 'bool', aliases: [ 'b' ], type: OptionType.Boolean, description: '' },
- { name: 'num', aliases: [ 'n' ], type: OptionType.Number, description: '' },
- { name: 'str', aliases: [ 's' ], type: OptionType.String, description: '' },
- { name: 'strUpper', aliases: [ 'S' ], type: OptionType.String, description: '' },
+ { name: 'bool', aliases: ['b'], type: OptionType.Boolean, description: '' },
+ { name: 'num', aliases: ['n'], type: OptionType.Number, description: '' },
+ { name: 'str', aliases: ['s'], type: OptionType.String, description: '' },
+ { name: 'strUpper', aliases: ['S'], type: OptionType.String, description: '' },
{ name: 'helloWorld', aliases: [], type: OptionType.String, description: '' },
{ name: 'helloBool', aliases: [], type: OptionType.Boolean, description: '' },
- { name: 'arr', aliases: [ 'a' ], type: OptionType.Array, description: '' },
+ { name: 'arr', aliases: ['a'], type: OptionType.Array, description: '' },
{ name: 'p1', positional: 0, aliases: [], type: OptionType.String, description: '' },
{ name: 'p2', positional: 1, aliases: [], type: OptionType.String, description: '' },
{ name: 'p3', positional: 2, aliases: [], type: OptionType.Number, description: '' },
- { name: 't1', aliases: [], type: OptionType.Boolean,
- types: [OptionType.Boolean, OptionType.String], description: '' },
- { name: 't2', aliases: [], type: OptionType.Boolean,
- types: [OptionType.Boolean, OptionType.Number], description: '' },
- { name: 't3', aliases: [], type: OptionType.Number,
- types: [OptionType.Number, OptionType.Any], description: '' },
+ {
+ name: 't1',
+ aliases: [],
+ type: OptionType.Boolean,
+ types: [OptionType.Boolean, OptionType.String],
+ description: '',
+ },
+ {
+ name: 't2',
+ aliases: [],
+ type: OptionType.Boolean,
+ types: [OptionType.Boolean, OptionType.Number],
+ description: '',
+ },
+ {
+ name: 't3',
+ aliases: [],
+ type: OptionType.Number,
+ types: [OptionType.Number, OptionType.Any],
+ description: '',
+ },
{ name: 'e1', aliases: [], type: OptionType.String, enum: ['hello', 'world'], description: '' },
{ name: 'e2', aliases: [], type: OptionType.String, enum: ['hello', ''], description: '' },
- { name: 'e3', aliases: [], type: OptionType.Boolean,
- types: [OptionType.Boolean, OptionType.String], enum: ['json', true, false],
- description: '' },
+ {
+ name: 'e3',
+ aliases: [],
+ type: OptionType.Boolean,
+ types: [OptionType.Boolean, OptionType.String],
+ enum: ['json', true, false],
+ description: '',
+ },
];
const tests: { [test: string]: Partial | ['!!!', Partial, string[]] } = {
@@ -75,10 +95,15 @@ describe('parseArguments', () => {
'--bool val1 --etc --num val2 --v': [
'!!!',
{ bool: true, p1: 'val1', p2: 'val2', '--': ['--etc', '--v'] },
- ['--num' ],
+ ['--num'],
],
- '--bool val1 --etc --num=1 val2 --v': { bool: true, num: 1, p1: 'val1', p2: 'val2',
- '--': ['--etc', '--v'] },
+ '--bool val1 --etc --num=1 val2 --v': {
+ bool: true,
+ num: 1,
+ p1: 'val1',
+ p2: 'val2',
+ '--': ['--etc', '--v'],
+ },
'--arr=a d': { arr: ['a'], p1: 'd' },
'--arr=a --arr=b --arr c d': { arr: ['a', 'b', 'c'], p1: 'd' },
'--arr=1 --arr --arr c d': { arr: ['1', '', 'c'], p1: 'd' },
@@ -121,7 +146,7 @@ describe('parseArguments', () => {
'--e1=yellow': ['!!!', {}, ['--e1=yellow']],
'--e1': ['!!!', {}, ['--e1']],
'--e1 true': ['!!!', { p1: 'true' }, ['--e1']],
- '--e1=true': ['!!!', {}, ['--e1=true']],
+ '--e1=true': ['!!!', {}, ['--e1=true']],
'--e2 hello': { e2: 'hello' },
'--e2=hello': { e2: 'hello' },
'--e2 yellow': { p1: 'yellow', e2: '' },
@@ -138,13 +163,13 @@ describe('parseArguments', () => {
'--e3=true': { e3: true },
'a b c 1': { p1: 'a', p2: 'b', '--': ['c', '1'] },
- '-p=1 -c=prod': {'--': ['-p=1', '-c=prod'] },
- '--p --c': {'--': ['--p', '--c'] },
- '--p=123': {'--': ['--p=123'] },
- '--p -c': {'--': ['--p', '-c'] },
- '-p --c': {'--': ['-p', '--c'] },
- '-p --c 123': {'--': ['-p', '--c', '123'] },
- '--c 123 -p': {'--': ['--c', '123', '-p'] },
+ '-p=1 -c=prod': { '--': ['-p=1', '-c=prod'] },
+ '--p --c': { '--': ['--p', '--c'] },
+ '--p=123': { '--': ['--p=123'] },
+ '--p -c': { '--': ['--p', '-c'] },
+ '-p --c': { '--': ['-p', '--c'] },
+ '-p --c 123': { '--': ['-p', '--c', '123'] },
+ '--c 123 -p': { '--': ['--c', '123', '-p'] },
};
Object.entries(tests).forEach(([str, expected]) => {
@@ -172,14 +197,12 @@ describe('parseArguments', () => {
});
it('handles a flag being added multiple times', () => {
- const options = [
- { name: 'bool', aliases: [], type: OptionType.Boolean, description: '' },
- ];
+ const options = [{ name: 'bool', aliases: [], type: OptionType.Boolean, description: '' }];
const logger = new logging.Logger('');
const messages: string[] = [];
- logger.subscribe(entry => messages.push(entry.message));
+ logger.subscribe((entry) => messages.push(entry.message));
let result = parseArguments(['--bool'], options, logger);
expect(result).toEqual({ bool: true });
diff --git a/packages/angular/cli/models/schematic-command.ts b/packages/angular/cli/models/schematic-command.ts
index 99d2f13a95c1..944bcf98ac52 100644
--- a/packages/angular/cli/models/schematic-command.ts
+++ b/packages/angular/cli/models/schematic-command.ts
@@ -6,14 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
-import {
- logging,
- normalize,
- schema,
- strings,
- tags,
- workspaces,
-} from '@angular-devkit/core';
+import { logging, normalize, schema, strings, tags, workspaces } from '@angular-devkit/core';
import {
DryRunEvent,
UnsuccessfulWorkflowExecution,
@@ -89,7 +82,7 @@ export abstract class SchematicCommand<
schematic.description.schemaJson || {},
);
- this.description.options.push(...options.filter(x => !x.hidden));
+ this.description.options.push(...options.filter((x) => !x.hidden));
// Remove any user analytics from schematics that are NOT part of our safelist.
for (const o of this.description.options) {
@@ -104,7 +97,7 @@ export abstract class SchematicCommand<
await super.printHelp();
this.logger.info('');
- const subCommandOption = this.description.options.filter(x => x.subcommands)[0];
+ const subCommandOption = this.description.options.filter((x) => x.subcommands)[0];
if (!subCommandOption || !subCommandOption.subcommands) {
return 0;
@@ -116,7 +109,7 @@ export abstract class SchematicCommand<
this.logger.info('Available Schematics:');
const namesPerCollection: { [c: string]: string[] } = {};
- schematicNames.forEach(name => {
+ schematicNames.forEach((name) => {
let [collectionName, schematicName] = name.split(/:/, 2);
if (!schematicName) {
schematicName = collectionName;
@@ -131,11 +124,11 @@ export abstract class SchematicCommand<
});
const defaultCollection = await this.getDefaultSchematicCollection();
- Object.keys(namesPerCollection).forEach(collectionName => {
+ Object.keys(namesPerCollection).forEach((collectionName) => {
const isDefault = defaultCollection == collectionName;
this.logger.info(` Collection "${collectionName}"${isDefault ? ' (default)' : ''}:`);
- namesPerCollection[collectionName].forEach(schematicName => {
+ namesPerCollection[collectionName].forEach((schematicName) => {
this.logger.info(` ${schematicName}`);
});
});
@@ -148,7 +141,7 @@ export abstract class SchematicCommand<
}
async printHelpUsage() {
- const subCommandOption = this.description.options.filter(x => x.subcommands)[0];
+ const subCommandOption = this.description.options.filter((x) => x.subcommands)[0];
if (!subCommandOption || !subCommandOption.subcommands) {
return;
@@ -158,7 +151,7 @@ export abstract class SchematicCommand<
if (schematicNames.length == 1) {
this.logger.info(this.description.description);
- const opts = this.description.options.filter(x => x.positional === undefined);
+ const opts = this.description.options.filter((x) => x.positional === undefined);
const [collectionName, schematicName] = schematicNames[0].split(/:/)[0];
// Display if this is not the default collectionName,
@@ -169,10 +162,10 @@ export abstract class SchematicCommand<
: schematicNames[0];
const schematicOptions = subCommandOption.subcommands[schematicNames[0]].options;
- const schematicArgs = schematicOptions.filter(x => x.positional !== undefined);
+ const schematicArgs = schematicOptions.filter((x) => x.positional !== undefined);
const argDisplay =
schematicArgs.length > 0
- ? ' ' + schematicArgs.map(a => `<${strings.dasherize(a.name)}>`).join(' ')
+ ? ' ' + schematicArgs.map((a) => `<${strings.dasherize(a.name)}>`).join(' ')
: '';
this.logger.info(tags.oneLine`
@@ -214,16 +207,13 @@ export abstract class SchematicCommand<
}
return options
- .filter(o => o.format === 'path')
- .map(o => o.name)
- .reduce(
- (acc, curr) => {
- acc[curr] = workingDir;
-
- return acc;
- },
- {} as { [name: string]: string },
- );
+ .filter((o) => o.format === 'path')
+ .map((o) => o.name)
+ .reduce((acc, curr) => {
+ acc[curr] = workingDir;
+
+ return acc;
+ }, {} as { [name: string]: string });
}
/*
@@ -244,18 +234,22 @@ export abstract class SchematicCommand<
// A schema registry is required to allow customizing addUndefinedDefaults
registry: new schema.CoreSchemaRegistry(formats.standardFormats),
resolvePaths: this.workspace
- // Workspace
- ? this.collectionName === this.defaultCollectionName
- // Favor __dirname for @schematics/angular to use the build-in version
- ? [__dirname, process.cwd(), root]
+ ? // Workspace
+ this.collectionName === this.defaultCollectionName
+ ? // Favor __dirname for @schematics/angular to use the build-in version
+ [__dirname, process.cwd(), root]
: [process.cwd(), root, __dirname]
- // Global
- : [__dirname, process.cwd()],
+ : // Global
+ [__dirname, process.cwd()],
schemaValidation: true,
optionTransforms: [
// Add configuration file defaults
async (schematic, current) => ({
- ...(await getSchematicDefaults(schematic.collection.name, schematic.name, getProjectName())),
+ ...(await getSchematicDefaults(
+ schematic.collection.name,
+ schematic.name,
+ getProjectName(),
+ )),
...current,
}),
],
@@ -264,7 +258,11 @@ export abstract class SchematicCommand<
const getProjectName = () => {
if (this.workspace) {
- const projectNames = getProjectsByPath(this.workspace, process.cwd(), this.workspace.basePath);
+ const projectNames = getProjectsByPath(
+ this.workspace,
+ process.cwd(),
+ this.workspace.basePath,
+ );
if (projectNames.length === 1) {
return projectNames[0];
@@ -289,7 +287,7 @@ export abstract class SchematicCommand<
workflow.registry.addPostTransform(schema.transforms.addUndefinedDefaults);
workflow.registry.addSmartDefaultProvider('projectName', getProjectName);
- workflow.registry.useXDeprecatedProvider(msg => this.logger.warn(msg));
+ workflow.registry.useXDeprecatedProvider((msg) => this.logger.warn(msg));
let shouldReportAnalytics = true;
workflow.engineHost.registerOptionsTransform(async (_, options) => {
@@ -304,8 +302,8 @@ export abstract class SchematicCommand<
if (options.interactive !== false && isTTY()) {
workflow.registry.usePromptProvider((definitions: Array) => {
const questions: inquirer.QuestionCollection = definitions
- .filter(definition => !options.defaults || definition.default === undefined)
- .map(definition => {
+ .filter((definition) => !options.defaults || definition.default === undefined)
+ .map((definition) => {
const question: inquirer.Question = {
name: definition.id,
message: definition.message,
@@ -314,7 +312,7 @@ export abstract class SchematicCommand<
const validator = definition.validator;
if (validator) {
- question.validate = input => validator(input);
+ question.validate = (input) => validator(input);
// Filter allows transformation of the value prior to validation
question.filter = async (input) => {
@@ -349,13 +347,13 @@ export abstract class SchematicCommand<
break;
case 'list':
question.type = definition.multiselect ? 'checkbox' : 'list';
- (question as inquirer.CheckboxQuestion).choices = definition.items?.map(item => {
+ (question as inquirer.CheckboxQuestion).choices = definition.items?.map((item) => {
return typeof item == 'string'
? item
: {
- name: item.label,
- value: item.value,
- };
+ name: item.label,
+ value: item.value,
+ };
});
break;
default:
@@ -438,10 +436,11 @@ export abstract class SchematicCommand<
}
const allowAdditionalProperties =
- typeof schematic.description.schemaJson === 'object' && schematic.description.schemaJson.additionalProperties;
+ typeof schematic.description.schemaJson === 'object' &&
+ schematic.description.schemaJson.additionalProperties;
if (args['--'] && !allowAdditionalProperties) {
- args['--'].forEach(additional => {
+ args['--'].forEach((additional) => {
this.logger.fatal(`Unknown option: '${additional.split(/=/)[0]}'`);
});
@@ -492,11 +491,11 @@ export abstract class SchematicCommand<
}
});
- workflow.lifeCycle.subscribe(event => {
+ workflow.lifeCycle.subscribe((event) => {
if (event.kind == 'end' || event.kind == 'post-tasks-start') {
if (!error) {
// Output the logging queue, no error happened.
- loggingQueue.forEach(log => this.logger.info(log));
+ loggingQueue.forEach((log) => this.logger.info(log));
}
loggingQueue = [];
@@ -514,7 +513,7 @@ export abstract class SchematicCommand<
}
}
- return new Promise(resolve => {
+ return new Promise((resolve) => {
workflow
.execute({
collection: collectionName,
@@ -586,7 +585,7 @@ function getProjectsByPath(
const projects = Array.from(workspace.projects.entries())
.map(([name, project]) => [systemPath.resolve(root, project.root), name] as [string, string])
- .filter(tuple => isInside(tuple[0], path))
+ .filter((tuple) => isInside(tuple[0], path))
// Sort tuples by depth, with the deeper ones first. Since the first member is a path and
// we filtered all invalid paths, the longest will be the deepest (and in case of equality
// the sort is stable and the first declared project will win).
@@ -597,7 +596,7 @@ function getProjectsByPath(
} else if (projects.length > 1) {
const firstPath = projects[0][0];
- return projects.filter(v => v[0] === firstPath).map(v => v[1]);
+ return projects.filter((v) => v[0] === firstPath).map((v) => v[1]);
}
return [];
diff --git a/packages/angular/cli/src/commands/update/schematic/index.ts b/packages/angular/cli/src/commands/update/schematic/index.ts
index 21005571bd9d..ef7d2f914c3a 100644
--- a/packages/angular/cli/src/commands/update/schematic/index.ts
+++ b/packages/angular/cli/src/commands/update/schematic/index.ts
@@ -7,12 +7,7 @@
*/
import { logging, tags } from '@angular-devkit/core';
-import {
- Rule,
- SchematicContext,
- SchematicsException,
- Tree,
-} from '@angular-devkit/schematics';
+import { Rule, SchematicContext, SchematicsException, Tree } from '@angular-devkit/schematics';
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
import * as npa from 'npm-package-arg';
import * as semver from 'semver';
@@ -21,10 +16,9 @@ import { NpmRepositoryPackageJson } from './npm-package-json';
import { Dependency, JsonSchemaForNpmPackageJsonFiles } from './package-json';
import { Schema as UpdateSchema } from './schema';
-type VersionRange = string & { __VERSION_RANGE: void; };
+type VersionRange = string & { __VERSION_RANGE: void };
type PeerVersionTransform = string | ((range: string) => string);
-
// Angular guarantees that a major is compatible with its following major (so packages that depend
// on Angular 5 are also compatible with Angular 6). This is, in code, represented by verifying
// that all other packages that have a peer dependency of `"@angular/core": "^5.0.0"` actually
@@ -56,7 +50,6 @@ export function angularMajorCompatGuarantee(range: string) {
return semver.validRange(newRange) || range;
}
-
// This is a map of packageGroupName to range extending function. If it isn't found, the range is
// kept the same.
const knownPeerCompatibleList: { [name: string]: PeerVersionTransform } = {
@@ -79,7 +72,7 @@ interface PackageInfo {
interface UpdateMetadata {
packageGroupName?: string;
- packageGroup: { [ packageName: string ]: string };
+ packageGroup: { [packageName: string]: string };
requirements: { [packageName: string]: string };
migrations?: string;
}
@@ -111,8 +104,8 @@ function _updatePeerVersion(infoMap: Map, name: string, ran
function _validateForwardPeerDependencies(
name: string,
infoMap: Map,
- peers: {[name: string]: string},
- peersMeta: { [name: string]: { optional?: boolean }},
+ peers: { [name: string]: string },
+ peersMeta: { [name: string]: { optional?: boolean } },
logger: logging.LoggerApi,
next: boolean,
): boolean {
@@ -123,26 +116,31 @@ function _validateForwardPeerDependencies(
const isOptional = peersMeta[peer] && !!peersMeta[peer].optional;
if (!maybePeerInfo) {
if (!isOptional) {
- logger.warn([
- `Package ${JSON.stringify(name)} has a missing peer dependency of`,
- `${JSON.stringify(peer)} @ ${JSON.stringify(range)}.`,
- ].join(' '));
+ logger.warn(
+ [
+ `Package ${JSON.stringify(name)} has a missing peer dependency of`,
+ `${JSON.stringify(peer)} @ ${JSON.stringify(range)}.`,
+ ].join(' '),
+ );
}
continue;
}
- const peerVersion = maybePeerInfo.target && maybePeerInfo.target.packageJson.version
- ? maybePeerInfo.target.packageJson.version
- : maybePeerInfo.installed.version;
+ const peerVersion =
+ maybePeerInfo.target && maybePeerInfo.target.packageJson.version
+ ? maybePeerInfo.target.packageJson.version
+ : maybePeerInfo.installed.version;
logger.debug(` Range intersects(${range}, ${peerVersion})...`);
if (!semver.satisfies(peerVersion, range, { includePrerelease: next || undefined })) {
- logger.error([
- `Package ${JSON.stringify(name)} has an incompatible peer dependency to`,
- `${JSON.stringify(peer)} (requires ${JSON.stringify(range)},`,
- `would install ${JSON.stringify(peerVersion)})`,
- ].join(' '));
+ logger.error(
+ [
+ `Package ${JSON.stringify(name)} has an incompatible peer dependency to`,
+ `${JSON.stringify(peer)} (requires ${JSON.stringify(range)},`,
+ `would install ${JSON.stringify(peerVersion)})`,
+ ].join(' '),
+ );
validationFailed = true;
continue;
@@ -152,7 +150,6 @@ function _validateForwardPeerDependencies(
return validationFailed;
}
-
function _validateReversePeerDependencies(
name: string,
version: string,
@@ -188,12 +185,14 @@ function _validateReversePeerDependencies(
const extendedRange = _updatePeerVersion(infoMap, peer, range);
if (!semver.satisfies(version, extendedRange, { includePrerelease: next || undefined })) {
- logger.error([
- `Package ${JSON.stringify(installed)} has an incompatible peer dependency to`,
- `${JSON.stringify(name)} (requires`,
- `${JSON.stringify(range)}${extendedRange == range ? '' : ' (extended)'},`,
- `would install ${JSON.stringify(version)}).`,
- ].join(' '));
+ logger.error(
+ [
+ `Package ${JSON.stringify(installed)} has an incompatible peer dependency to`,
+ `${JSON.stringify(name)} (requires`,
+ `${JSON.stringify(range)}${extendedRange == range ? '' : ' (extended)'},`,
+ `would install ${JSON.stringify(version)}).`,
+ ].join(' '),
+ );
return true;
}
@@ -210,15 +209,15 @@ function _validateUpdatePackages(
logger: logging.LoggerApi,
): void {
logger.debug('Updating the following packages:');
- infoMap.forEach(info => {
+ infoMap.forEach((info) => {
if (info.target) {
logger.debug(` ${info.name} => ${info.target.version}`);
}
});
let peerErrors = false;
- infoMap.forEach(info => {
- const {name, target} = info;
+ infoMap.forEach((info) => {
+ const { name, target } = info;
if (!target) {
return;
}
@@ -227,22 +226,27 @@ function _validateUpdatePackages(
logger.debug(`${name}...`);
const { peerDependencies = {}, peerDependenciesMeta = {} } = target.packageJson;
- peerErrors = _validateForwardPeerDependencies(name, infoMap, peerDependencies,
- peerDependenciesMeta, pkgLogger, next) || peerErrors;
- peerErrors
- = _validateReversePeerDependencies(name, target.version, infoMap, pkgLogger, next)
- || peerErrors;
+ peerErrors =
+ _validateForwardPeerDependencies(
+ name,
+ infoMap,
+ peerDependencies,
+ peerDependenciesMeta,
+ pkgLogger,
+ next,
+ ) || peerErrors;
+ peerErrors =
+ _validateReversePeerDependencies(name, target.version, infoMap, pkgLogger, next) ||
+ peerErrors;
});
if (!force && peerErrors) {
- throw new SchematicsException(tags.stripIndents
- `Incompatible peer dependencies found.
+ throw new SchematicsException(tags.stripIndents`Incompatible peer dependencies found.
Peer dependency warnings when installing dependencies means that those dependencies might not work correctly together.
You can use the '--force' option to ignore incompatible peer dependencies and instead address these warnings later.`);
}
}
-
function _performUpdate(
tree: Tree,
context: SchematicContext,
@@ -270,16 +274,16 @@ function _performUpdate(
};
const toInstall = [...infoMap.values()]
- .map(x => [x.name, x.target, x.installed])
- // tslint:disable-next-line:no-non-null-assertion
- .filter(([name, target, installed]) => {
- return !!name && !!target && !!installed;
- }) as [string, PackageVersionInfo, PackageVersionInfo][];
+ .map((x) => [x.name, x.target, x.installed])
+ // tslint:disable-next-line:no-non-null-assertion
+ .filter(([name, target, installed]) => {
+ return !!name && !!target && !!installed;
+ }) as [string, PackageVersionInfo, PackageVersionInfo][];
toInstall.forEach(([name, target, installed]) => {
logger.info(
- `Updating package.json with dependency ${name} `
- + `@ ${JSON.stringify(target.version)} (was ${JSON.stringify(installed.version)})...`,
+ `Updating package.json with dependency ${name} ` +
+ `@ ${JSON.stringify(target.version)} (was ${JSON.stringify(installed.version)})...`,
);
if (packageJson.dependencies && packageJson.dependencies[name]) {
@@ -323,11 +327,9 @@ function _performUpdate(
return;
}
- const collection = (
- target.updateMetadata.migrations.match(/^[./]/)
- ? name + '/'
- : ''
- ) + target.updateMetadata.migrations;
+ const collection =
+ (target.updateMetadata.migrations.match(/^[./]/) ? name + '/' : '') +
+ target.updateMetadata.migrations;
externalMigrations.push({
package: name,
@@ -365,19 +367,20 @@ function _getUpdateMetadata(
const packageGroup = metadata['packageGroup'];
// Verify that packageGroup is an array of strings or an map of versions. This is not an error
// but we still warn the user and ignore the packageGroup keys.
- if (Array.isArray(packageGroup) && packageGroup.every(x => typeof x == 'string')) {
+ if (Array.isArray(packageGroup) && packageGroup.every((x) => typeof x == 'string')) {
result.packageGroup = packageGroup.reduce((group, name) => {
group[name] = packageJson.version;
return group;
}, result.packageGroup);
- } else if (typeof packageGroup == 'object' && packageGroup
- && Object.values(packageGroup).every(x => typeof x == 'string')) {
+ } else if (
+ typeof packageGroup == 'object' &&
+ packageGroup &&
+ Object.values(packageGroup).every((x) => typeof x == 'string')
+ ) {
result.packageGroup = packageGroup;
} else {
- logger.warn(
- `packageGroup metadata of package ${packageJson.name} is malformed. Ignoring.`,
- );
+ logger.warn(`packageGroup metadata of package ${packageJson.name} is malformed. Ignoring.`);
}
result.packageGroupName = Object.keys(result.packageGroup)[0];
@@ -390,12 +393,12 @@ function _getUpdateMetadata(
if (metadata['requirements']) {
const requirements = metadata['requirements'];
// Verify that requirements are
- if (typeof requirements != 'object'
- || Array.isArray(requirements)
- || Object.keys(requirements).some(name => typeof requirements[name] != 'string')) {
- logger.warn(
- `requirements metadata of package ${packageJson.name} is malformed. Ignoring.`,
- );
+ if (
+ typeof requirements != 'object' ||
+ Array.isArray(requirements) ||
+ Object.keys(requirements).some((name) => typeof requirements[name] != 'string')
+ ) {
+ logger.warn(`requirements metadata of package ${packageJson.name} is malformed. Ignoring.`);
} else {
result.requirements = requirements;
}
@@ -413,7 +416,6 @@ function _getUpdateMetadata(
return result;
}
-
function _usageMessage(
options: UpdateSchema,
infoMap: Map,
@@ -423,7 +425,10 @@ function _usageMessage(
const packagesToUpdate = [...infoMap.entries()]
.map(([name, info]) => {
const tag = options.next
- ? (info.npmPackageJson['dist-tags']['next'] ? 'next' : 'latest') : 'latest';
+ ? info.npmPackageJson['dist-tags']['next']
+ ? 'next'
+ : 'latest'
+ : 'latest';
const version = info.npmPackageJson['dist-tags'][tag];
const target = info.npmPackageJson.versions[version];
@@ -436,7 +441,7 @@ function _usageMessage(
};
})
.filter(({ info, version, target }) => {
- return (target && semver.compare(info.installed.version, version) < 0);
+ return target && semver.compare(info.installed.version, version) < 0;
})
.filter(({ target }) => {
return target['ng-update'];
@@ -445,8 +450,8 @@ function _usageMessage(
// Look for packageGroup.
if (target['ng-update'] && target['ng-update']['packageGroup']) {
const packageGroup = target['ng-update']['packageGroup'];
- const packageGroupName = target['ng-update']['packageGroupName']
- || target['ng-update']['packageGroup'][0];
+ const packageGroupName =
+ target['ng-update']['packageGroupName'] || target['ng-update']['packageGroup'][0];
if (packageGroupName) {
if (packageGroups.has(name)) {
return null;
@@ -465,8 +470,8 @@ function _usageMessage(
return [name, `${info.installed.version} -> ${version} `, command];
})
- .filter(x => x !== null)
- .sort((a, b) => a && b ? a[0].localeCompare(b[0]) : 0);
+ .filter((x) => x !== null)
+ .sort((a, b) => (a && b ? a[0].localeCompare(b[0]) : 0));
if (packagesToUpdate.length == 0) {
logger.info('We analyzed your package.json and everything seems to be in order. Good work!');
@@ -474,24 +479,21 @@ function _usageMessage(
return;
}
- logger.info(
- 'We analyzed your package.json, there are some packages to update:\n',
- );
+ logger.info('We analyzed your package.json, there are some packages to update:\n');
// Find the largest name to know the padding needed.
- let namePad = Math.max(...[...infoMap.keys()].map(x => x.length)) + 2;
+ let namePad = Math.max(...[...infoMap.keys()].map((x) => x.length)) + 2;
if (!Number.isFinite(namePad)) {
namePad = 30;
}
const pads = [namePad, 25, 0];
logger.info(
- ' '
- + ['Name', 'Version', 'Command to update'].map((x, i) => x.padEnd(pads[i])).join(''),
+ ' ' + ['Name', 'Version', 'Command to update'].map((x, i) => x.padEnd(pads[i])).join(''),
);
- logger.info(' ' + '-'.repeat(pads.reduce((s, x) => s += x, 0) + 20));
+ logger.info(' ' + '-'.repeat(pads.reduce((s, x) => (s += x), 0) + 20));
- packagesToUpdate.forEach(fields => {
+ packagesToUpdate.forEach((fields) => {
if (!fields) {
return;
}
@@ -500,14 +502,13 @@ function _usageMessage(
});
logger.info(
- `\nThere might be additional packages which don't provide 'ng update' capabilities that are outdated.\n`
- + `You can update the additional packages by running the update command of your package manager.`,
+ `\nThere might be additional packages which don't provide 'ng update' capabilities that are outdated.\n` +
+ `You can update the additional packages by running the update command of your package manager.`,
);
return;
}
-
function _buildPackageInfo(
tree: Tree,
packages: Map,
@@ -518,9 +519,7 @@ function _buildPackageInfo(
const name = npmPackageJson.name;
const packageJsonRange = allDependencies.get(name);
if (!packageJsonRange) {
- throw new SchematicsException(
- `Package ${JSON.stringify(name)} was not found in package.json.`,
- );
+ throw new SchematicsException(`Package ${JSON.stringify(name)} was not found in package.json.`);
}
// Find out the currently installed version. Either from the package.json or the node_modules/
@@ -533,10 +532,7 @@ function _buildPackageInfo(
}
if (!installedVersion) {
// Find the version from NPM that fits the range to max.
- installedVersion = semver.maxSatisfying(
- Object.keys(npmPackageJson.versions),
- packageJsonRange,
- );
+ installedVersion = semver.maxSatisfying(Object.keys(npmPackageJson.versions), packageJsonRange);
}
if (!installedVersion) {
@@ -573,10 +569,10 @@ function _buildPackageInfo(
const target: PackageVersionInfo | undefined = targetVersion
? {
- version: targetVersion,
- packageJson: npmPackageJson.versions[targetVersion],
- updateMetadata: _getUpdateMetadata(npmPackageJson.versions[targetVersion], logger),
- }
+ version: targetVersion,
+ packageJson: npmPackageJson.versions[targetVersion],
+ updateMetadata: _getUpdateMetadata(npmPackageJson.versions[targetVersion], logger),
+ }
: undefined;
// Check if there's an installed version.
@@ -593,7 +589,6 @@ function _buildPackageInfo(
};
}
-
function _buildPackageList(
options: UpdateSchema,
projectDeps: Map,
@@ -602,9 +597,7 @@ function _buildPackageList(
// Parse the packages options to set the targeted version.
const packages = new Map();
const commandLinePackages =
- (options.packages && options.packages.length > 0)
- ? options.packages
- : [];
+ options.packages && options.packages.length > 0 ? options.packages : [];
for (const pkg of commandLinePackages) {
// Split the version asked on command line.
@@ -628,7 +621,6 @@ function _buildPackageList(
return packages;
}
-
function _addPackageGroup(
tree: Tree,
packages: Map,
@@ -643,9 +635,10 @@ function _addPackageGroup(
const info = _buildPackageInfo(tree, packages, allDependencies, npmPackageJson, logger);
- const version = (info.target && info.target.version)
- || npmPackageJson['dist-tags'][maybePackage]
- || maybePackage;
+ const version =
+ (info.target && info.target.version) ||
+ npmPackageJson['dist-tags'][maybePackage] ||
+ maybePackage;
if (!npmPackageJson.versions[version]) {
return;
}
@@ -658,7 +651,7 @@ function _addPackageGroup(
if (!packageGroup) {
return;
}
- if (Array.isArray(packageGroup) && !packageGroup.some(x => typeof x != 'string')) {
+ if (Array.isArray(packageGroup) && !packageGroup.some((x) => typeof x != 'string')) {
packageGroup = packageGroup.reduce((acc, curr) => {
acc[curr] = maybePackage;
@@ -667,9 +660,10 @@ function _addPackageGroup(
}
// Only need to check if it's an object because we set it right the time before.
- if (typeof packageGroup != 'object'
- || packageGroup === null
- || Object.values(packageGroup).some(v => typeof v != 'string')
+ if (
+ typeof packageGroup != 'object' ||
+ packageGroup === null ||
+ Object.values(packageGroup).some((v) => typeof v != 'string')
) {
logger.warn(`packageGroup metadata of package ${npmPackageJson.name} is malformed.`);
@@ -677,9 +671,9 @@ function _addPackageGroup(
}
Object.keys(packageGroup)
- .filter(name => !packages.has(name)) // Don't override names from the command line.
- .filter(name => allDependencies.has(name)) // Remove packages that aren't installed.
- .forEach(name => {
+ .filter((name) => !packages.has(name)) // Don't override names from the command line.
+ .filter((name) => allDependencies.has(name)) // Remove packages that aren't installed.
+ .forEach((name) => {
packages.set(name, packageGroup[name]);
});
}
@@ -705,9 +699,10 @@ function _addPeerDependencies(
const info = _buildPackageInfo(tree, packages, allDependencies, npmPackageJson, logger);
- const version = (info.target && info.target.version)
- || npmPackageJson['dist-tags'][maybePackage]
- || maybePackage;
+ const version =
+ (info.target && info.target.version) ||
+ npmPackageJson['dist-tags'][maybePackage] ||
+ maybePackage;
if (!npmPackageJson.versions[version]) {
return;
}
@@ -736,7 +731,6 @@ function _addPeerDependencies(
}
}
-
function _getAllDependencies(tree: Tree): Array {
const packageJsonContent = tree.read('/package.json');
if (!packageJsonContent) {
@@ -751,9 +745,9 @@ function _getAllDependencies(tree: Tree): Array
}
return [
- ...Object.entries(packageJson.peerDependencies || {}) as Array<[string, VersionRange]>,
- ...Object.entries(packageJson.devDependencies || {}) as Array<[string, VersionRange]>,
- ...Object.entries(packageJson.dependencies || {}) as Array<[string, VersionRange]>,
+ ...(Object.entries(packageJson.peerDependencies || {}) as Array<[string, VersionRange]>),
+ ...(Object.entries(packageJson.devDependencies || {}) as Array<[string, VersionRange]>),
+ ...(Object.entries(packageJson.dependencies || {}) as Array<[string, VersionRange]>),
];
}
@@ -786,7 +780,7 @@ function isPkgFromRegistry(name: string, specifier: string): boolean {
return !!result.registry;
}
-export default function(options: UpdateSchema): Rule {
+export default function (options: UpdateSchema): Rule {
if (!options.packages) {
// We cannot just return this because we need to fetch the packages from NPM still for the
// help/guide to show.
@@ -810,48 +804,52 @@ export default function(options: UpdateSchema): Rule {
return async (tree: Tree, context: SchematicContext) => {
const logger = context.logger;
- const npmDeps = new Map(_getAllDependencies(tree).filter(([name, specifier]) => {
- try {
- return isPkgFromRegistry(name, specifier);
- } catch {
- logger.warn(`Package ${name} was not found on the registry. Skipping.`);
-
- return false;
- }
- }));
+ const npmDeps = new Map(
+ _getAllDependencies(tree).filter(([name, specifier]) => {
+ try {
+ return isPkgFromRegistry(name, specifier);
+ } catch {
+ logger.warn(`Package ${name} was not found on the registry. Skipping.`);
+
+ return false;
+ }
+ }),
+ );
const packages = _buildPackageList(options, npmDeps, logger);
// Grab all package.json from the npm repository. This requires a lot of HTTP calls so we
// try to parallelize as many as possible.
- const allPackageMetadata = await Promise.all(Array.from(npmDeps.keys()).map(depName => getNpmPackageJson(
- depName,
- logger,
- { registryUrl: options.registry, usingYarn, verbose: options.verbose },
- )));
+ const allPackageMetadata = await Promise.all(
+ Array.from(npmDeps.keys()).map((depName) =>
+ getNpmPackageJson(depName, logger, {
+ registryUrl: options.registry,
+ usingYarn,
+ verbose: options.verbose,
+ }),
+ ),
+ );
// Build a map of all dependencies and their packageJson.
- const npmPackageJsonMap = allPackageMetadata.reduce(
- (acc, npmPackageJson) => {
- // If the package was not found on the registry. It could be private, so we will just
- // ignore. If the package was part of the list, we will error out, but will simply ignore
- // if it's either not requested (so just part of package.json. silently) or if it's a
- // `--all` situation. There is an edge case here where a public package peer depends on a
- // private one, but it's rare enough.
- if (!npmPackageJson.name) {
- if (npmPackageJson.requestedName && packages.has(npmPackageJson.requestedName)) {
- throw new SchematicsException(
- `Package ${JSON.stringify(npmPackageJson.requestedName)} was not found on the `
- + 'registry. Cannot continue as this may be an error.');
- }
- } else {
- // If a name is present, it is assumed to be fully populated
- acc.set(npmPackageJson.name, npmPackageJson as NpmRepositoryPackageJson);
+ const npmPackageJsonMap = allPackageMetadata.reduce((acc, npmPackageJson) => {
+ // If the package was not found on the registry. It could be private, so we will just
+ // ignore. If the package was part of the list, we will error out, but will simply ignore
+ // if it's either not requested (so just part of package.json. silently) or if it's a
+ // `--all` situation. There is an edge case here where a public package peer depends on a
+ // private one, but it's rare enough.
+ if (!npmPackageJson.name) {
+ if (npmPackageJson.requestedName && packages.has(npmPackageJson.requestedName)) {
+ throw new SchematicsException(
+ `Package ${JSON.stringify(npmPackageJson.requestedName)} was not found on the ` +
+ 'registry. Cannot continue as this may be an error.',
+ );
}
+ } else {
+ // If a name is present, it is assumed to be fully populated
+ acc.set(npmPackageJson.name, npmPackageJson as NpmRepositoryPackageJson);
+ }
- return acc;
- },
- new Map(),
- );
+ return acc;
+ }, new Map());
// Augment the command line package list with packageGroups and forward peer dependencies.
// Each added package may uncover new package groups and peer dependencies, so we must
@@ -880,11 +878,7 @@ export default function(options: UpdateSchema): Rule {
return;
}
- const sublog = new logging.LevelCapLogger(
- 'validation',
- logger.createChild(''),
- 'warn',
- );
+ const sublog = new logging.LevelCapLogger('validation', logger.createChild(''), 'warn');
_validateUpdatePackages(packageInfoMap, !!options.force, !!options.next, sublog);
_performUpdate(tree, context, packageInfoMap, logger, !!options.migrateOnly);
diff --git a/packages/angular/cli/src/commands/update/schematic/index_spec.ts b/packages/angular/cli/src/commands/update/schematic/index_spec.ts
index bd0c42ebf58a..6db5433caec8 100644
--- a/packages/angular/cli/src/commands/update/schematic/index_spec.ts
+++ b/packages/angular/cli/src/commands/update/schematic/index_spec.ts
@@ -15,7 +15,6 @@ import { map } from 'rxjs/operators'; // tslint:disable-line: no-implicit-depend
import * as semver from 'semver';
import { angularMajorCompatGuarantee } from './index';
-
describe('angularMajorCompatGuarantee', () => {
[
'5.0.0',
@@ -27,7 +26,7 @@ describe('angularMajorCompatGuarantee', () => {
'6.1.0-beta.0',
'6.1.0-rc.0',
'6.10.11',
- ].forEach(golden => {
+ ].forEach((golden) => {
it('works with ' + JSON.stringify(golden), () => {
expect(semver.satisfies(golden, angularMajorCompatGuarantee('^5.0.0'))).toBeTruthy();
});
@@ -54,44 +53,63 @@ describe('@schematics/update', () => {
appTree = new UnitTestTree(new HostTree(host));
});
- it('ignores dependencies not hosted on the NPM registry', done => {
- const tree = new UnitTestTree(new HostTree(new virtualFs.test.TestHost({
- '/package.json': `{
+ it('ignores dependencies not hosted on the NPM registry', (done) => {
+ const tree = new UnitTestTree(
+ new HostTree(
+ new virtualFs.test.TestHost({
+ '/package.json': `{
"name": "blah",
"dependencies": {
"@angular-devkit-tests/update-base": "file:update-base-1.0.0.tgz"
}
}`,
- })));
+ }),
+ ),
+ );
- schematicRunner.runSchematicAsync('update', undefined, tree).pipe(
- map(t => {
- const packageJson = JSON.parse(t.readContent('/package.json'));
- expect(packageJson['dependencies']['@angular-devkit-tests/update-base'])
- .toBe('file:update-base-1.0.0.tgz');
- }),
- ).toPromise().then(done, done.fail);
+ schematicRunner
+ .runSchematicAsync('update', undefined, tree)
+ .pipe(
+ map((t) => {
+ const packageJson = JSON.parse(t.readContent('/package.json'));
+ expect(packageJson['dependencies']['@angular-devkit-tests/update-base']).toBe(
+ 'file:update-base-1.0.0.tgz',
+ );
+ }),
+ )
+ .toPromise()
+ .then(done, done.fail);
}, 45000);
it('should not error with yarn 2.0 protocols', async () => {
- const tree = new UnitTestTree(new HostTree(new virtualFs.test.TestHost({
- '/package.json': `{
+ const tree = new UnitTestTree(
+ new HostTree(
+ new virtualFs.test.TestHost({
+ '/package.json': `{
"name": "blah",
"dependencies": {
"src": "src@link:./src",
"@angular-devkit-tests/update-base": "1.0.0"
}
}`,
- })));
+ }),
+ ),
+ );
- const newTree = await schematicRunner.runSchematicAsync('update', {
- packages: ['@angular-devkit-tests/update-base'],
- }, tree).toPromise();
+ const newTree = await schematicRunner
+ .runSchematicAsync(
+ 'update',
+ {
+ packages: ['@angular-devkit-tests/update-base'],
+ },
+ tree,
+ )
+ .toPromise();
const { dependencies } = JSON.parse(newTree.readContent('/package.json'));
expect(dependencies['@angular-devkit-tests/update-base']).toBe('1.1.0');
});
- it('updates Angular as compatible with Angular N-1', done => {
+ it('updates Angular as compatible with Angular N-1', (done) => {
// Add the basic migration package.
const content = virtualFs.fileBufferToString(host.sync.read(normalize('/package.json')));
const packageJson = JSON.parse(content);
@@ -105,33 +123,41 @@ describe('@schematics/update', () => {
virtualFs.stringToFileBuffer(JSON.stringify(packageJson)),
);
- schematicRunner.runSchematicAsync('update', {
- packages: ['@angular/core@^6.0.0'],
- }, appTree).pipe(
- map(tree => {
- const packageJson = JSON.parse(tree.readContent('/package.json'));
- expect(packageJson['dependencies']['@angular/core'][0]).toBe('6');
+ schematicRunner
+ .runSchematicAsync(
+ 'update',
+ {
+ packages: ['@angular/core@^6.0.0'],
+ },
+ appTree,
+ )
+ .pipe(
+ map((tree) => {
+ const packageJson = JSON.parse(tree.readContent('/package.json'));
+ expect(packageJson['dependencies']['@angular/core'][0]).toBe('6');
- // Check install task.
- expect(schematicRunner.tasks).toEqual([
- {
- name: 'node-package',
- options: jasmine.objectContaining({
- command: 'install',
- }),
- },
- {
- name: 'run-schematic',
- options: jasmine.objectContaining({
- name: 'migrate',
- }),
- },
- ]);
- }),
- ).toPromise().then(done, done.fail);
+ // Check install task.
+ expect(schematicRunner.tasks).toEqual([
+ {
+ name: 'node-package',
+ options: jasmine.objectContaining({
+ command: 'install',
+ }),
+ },
+ {
+ name: 'run-schematic',
+ options: jasmine.objectContaining({
+ name: 'migrate',
+ }),
+ },
+ ]);
+ }),
+ )
+ .toPromise()
+ .then(done, done.fail);
}, 45000);
- it('updates Angular as compatible with Angular N-1 (2)', done => {
+ it('updates Angular as compatible with Angular N-1 (2)', (done) => {
// Add the basic migration package.
const content = virtualFs.fileBufferToString(host.sync.read(normalize('/package.json')));
const packageJson = JSON.parse(content);
@@ -151,33 +177,41 @@ describe('@schematics/update', () => {
virtualFs.stringToFileBuffer(JSON.stringify(packageJson)),
);
- schematicRunner.runSchematicAsync('update', {
- packages: ['@angular/core@^6.0.0'],
- }, appTree).pipe(
- map(tree => {
- const packageJson = JSON.parse(tree.readContent('/package.json'));
- expect(packageJson['dependencies']['@angular/core'][0]).toBe('6');
- expect(packageJson['dependencies']['rxjs'][0]).toBe('6');
- expect(packageJson['dependencies']['typescript'][0]).toBe('2');
- expect(packageJson['dependencies']['typescript'][2]).not.toBe('4');
+ schematicRunner
+ .runSchematicAsync(
+ 'update',
+ {
+ packages: ['@angular/core@^6.0.0'],
+ },
+ appTree,
+ )
+ .pipe(
+ map((tree) => {
+ const packageJson = JSON.parse(tree.readContent('/package.json'));
+ expect(packageJson['dependencies']['@angular/core'][0]).toBe('6');
+ expect(packageJson['dependencies']['rxjs'][0]).toBe('6');
+ expect(packageJson['dependencies']['typescript'][0]).toBe('2');
+ expect(packageJson['dependencies']['typescript'][2]).not.toBe('4');
- // Check install task.
- expect(schematicRunner.tasks).toEqual([
- {
- name: 'node-package',
- options: jasmine.objectContaining({
- command: 'install',
- }),
- },
- {
- name: 'run-schematic',
- options: jasmine.objectContaining({
- name: 'migrate',
- }),
- },
- ]);
- }),
- ).toPromise().then(done, done.fail);
+ // Check install task.
+ expect(schematicRunner.tasks).toEqual([
+ {
+ name: 'node-package',
+ options: jasmine.objectContaining({
+ command: 'install',
+ }),
+ },
+ {
+ name: 'run-schematic',
+ options: jasmine.objectContaining({
+ name: 'migrate',
+ }),
+ },
+ ]);
+ }),
+ )
+ .toPromise()
+ .then(done, done.fail);
}, 45000);
it('uses packageGroup for versioning', async () => {
@@ -192,29 +226,36 @@ describe('@schematics/update', () => {
virtualFs.stringToFileBuffer(JSON.stringify(packageJson)),
);
- await schematicRunner.runSchematicAsync('update', {
- packages: ['@angular-devkit-tests/update-package-group-1'],
- }, appTree).pipe(
- map(tree => {
- const packageJson = JSON.parse(tree.readContent('/package.json'));
- const deps = packageJson['dependencies'];
- expect(deps['@angular-devkit-tests/update-package-group-1']).toBe('1.2.0');
- expect(deps['@angular-devkit-tests/update-package-group-2']).toBe('2.0.0');
+ await schematicRunner
+ .runSchematicAsync(
+ 'update',
+ {
+ packages: ['@angular-devkit-tests/update-package-group-1'],
+ },
+ appTree,
+ )
+ .pipe(
+ map((tree) => {
+ const packageJson = JSON.parse(tree.readContent('/package.json'));
+ const deps = packageJson['dependencies'];
+ expect(deps['@angular-devkit-tests/update-package-group-1']).toBe('1.2.0');
+ expect(deps['@angular-devkit-tests/update-package-group-2']).toBe('2.0.0');
- // Check install task.
- expect(schematicRunner.tasks).toEqual([
- {
- name: 'node-package',
- options: jasmine.objectContaining({
- command: 'install',
- }),
- },
- ]);
- }),
- ).toPromise();
+ // Check install task.
+ expect(schematicRunner.tasks).toEqual([
+ {
+ name: 'node-package',
+ options: jasmine.objectContaining({
+ command: 'install',
+ }),
+ },
+ ]);
+ }),
+ )
+ .toPromise();
}, 45000);
- it('can migrate only', done => {
+ it('can migrate only', (done) => {
// Add the basic migration package.
const content = virtualFs.fileBufferToString(host.sync.read(normalize('/package.json')));
const packageJson = JSON.parse(content);
@@ -224,30 +265,39 @@ describe('@schematics/update', () => {
virtualFs.stringToFileBuffer(JSON.stringify(packageJson)),
);
- schematicRunner.runSchematicAsync('update', {
- packages: ['@angular-devkit-tests/update-migrations'],
- migrateOnly: true,
- }, appTree).pipe(
- map(tree => {
- const packageJson = JSON.parse(tree.readContent('/package.json'));
- expect(packageJson['dependencies']['@angular-devkit-tests/update-base']).toBe('1.0.0');
- expect(packageJson['dependencies']['@angular-devkit-tests/update-migrations'])
- .toBe('1.0.0');
+ schematicRunner
+ .runSchematicAsync(
+ 'update',
+ {
+ packages: ['@angular-devkit-tests/update-migrations'],
+ migrateOnly: true,
+ },
+ appTree,
+ )
+ .pipe(
+ map((tree) => {
+ const packageJson = JSON.parse(tree.readContent('/package.json'));
+ expect(packageJson['dependencies']['@angular-devkit-tests/update-base']).toBe('1.0.0');
+ expect(packageJson['dependencies']['@angular-devkit-tests/update-migrations']).toBe(
+ '1.0.0',
+ );
- // Check install task.
- expect(schematicRunner.tasks).toEqual([
- {
- name: 'run-schematic',
- options: jasmine.objectContaining({
- name: 'migrate',
- }),
- },
- ]);
- }),
- ).toPromise().then(done, done.fail);
+ // Check install task.
+ expect(schematicRunner.tasks).toEqual([
+ {
+ name: 'run-schematic',
+ options: jasmine.objectContaining({
+ name: 'migrate',
+ }),
+ },
+ ]);
+ }),
+ )
+ .toPromise()
+ .then(done, done.fail);
}, 45000);
- it('can migrate from only', done => {
+ it('can migrate from only', (done) => {
// Add the basic migration package.
const content = virtualFs.fileBufferToString(host.sync.read(normalize('/package.json')));
const packageJson = JSON.parse(content);
@@ -257,34 +307,43 @@ describe('@schematics/update', () => {
virtualFs.stringToFileBuffer(JSON.stringify(packageJson)),
);
- schematicRunner.runSchematicAsync('update', {
- packages: ['@angular-devkit-tests/update-migrations'],
- migrateOnly: true,
- from: '0.1.2',
- }, appTree).pipe(
- map(tree => {
- const packageJson = JSON.parse(tree.readContent('/package.json'));
- expect(packageJson['dependencies']['@angular-devkit-tests/update-migrations'])
- .toBe('1.6.0');
+ schematicRunner
+ .runSchematicAsync(
+ 'update',
+ {
+ packages: ['@angular-devkit-tests/update-migrations'],
+ migrateOnly: true,
+ from: '0.1.2',
+ },
+ appTree,
+ )
+ .pipe(
+ map((tree) => {
+ const packageJson = JSON.parse(tree.readContent('/package.json'));
+ expect(packageJson['dependencies']['@angular-devkit-tests/update-migrations']).toBe(
+ '1.6.0',
+ );
- // Check install task.
- expect(schematicRunner.tasks).toEqual([
- {
- name: 'run-schematic',
- options: jasmine.objectContaining({
- name: 'migrate',
+ // Check install task.
+ expect(schematicRunner.tasks).toEqual([
+ {
+ name: 'run-schematic',
options: jasmine.objectContaining({
- from: '0.1.2',
- to: '1.6.0',
+ name: 'migrate',
+ options: jasmine.objectContaining({
+ from: '0.1.2',
+ to: '1.6.0',
+ }),
}),
- }),
- },
- ]);
- }),
- ).toPromise().then(done, done.fail);
+ },
+ ]);
+ }),
+ )
+ .toPromise()
+ .then(done, done.fail);
}, 45000);
- it('can install and migrate with --from (short version number)', done => {
+ it('can install and migrate with --from (short version number)', (done) => {
// Add the basic migration package.
const content = virtualFs.fileBufferToString(host.sync.read(normalize('/package.json')));
const packageJson = JSON.parse(content);
@@ -294,34 +353,43 @@ describe('@schematics/update', () => {
virtualFs.stringToFileBuffer(JSON.stringify(packageJson)),
);
- schematicRunner.runSchematicAsync('update', {
- packages: ['@angular-devkit-tests/update-migrations'],
- migrateOnly: true,
- from: '0',
- }, appTree).pipe(
- map(tree => {
- const packageJson = JSON.parse(tree.readContent('/package.json'));
- expect(packageJson['dependencies']['@angular-devkit-tests/update-migrations'])
- .toBe('1.6.0');
+ schematicRunner
+ .runSchematicAsync(
+ 'update',
+ {
+ packages: ['@angular-devkit-tests/update-migrations'],
+ migrateOnly: true,
+ from: '0',
+ },
+ appTree,
+ )
+ .pipe(
+ map((tree) => {
+ const packageJson = JSON.parse(tree.readContent('/package.json'));
+ expect(packageJson['dependencies']['@angular-devkit-tests/update-migrations']).toBe(
+ '1.6.0',
+ );
- // Check install task.
- expect(schematicRunner.tasks).toEqual([
- {
- name: 'run-schematic',
- options: jasmine.objectContaining({
- name: 'migrate',
+ // Check install task.
+ expect(schematicRunner.tasks).toEqual([
+ {
+ name: 'run-schematic',
options: jasmine.objectContaining({
- from: '0.0.0',
- to: '1.6.0',
+ name: 'migrate',
+ options: jasmine.objectContaining({
+ from: '0.0.0',
+ to: '1.6.0',
+ }),
}),
- }),
- },
- ]);
- }),
- ).toPromise().then(done, done.fail);
+ },
+ ]);
+ }),
+ )
+ .toPromise()
+ .then(done, done.fail);
}, 45000);
- it('validates peer dependencies', done => {
+ it('validates peer dependencies', (done) => {
const content = virtualFs.fileBufferToString(host.sync.read(normalize('/package.json')));
const packageJson = JSON.parse(content);
const dependencies = packageJson['dependencies'];
@@ -336,21 +404,31 @@ describe('@schematics/update', () => {
);
const messages: string[] = [];
- schematicRunner.logger.subscribe(x => messages.push(x.message));
+ schematicRunner.logger.subscribe((x) => messages.push(x.message));
const hasPeerdepMsg = (dep: string) =>
- messages.some(str => str.includes(`missing peer dependency of "${dep}"`));
+ messages.some((str) => str.includes(`missing peer dependency of "${dep}"`));
- schematicRunner.runSchematicAsync('update', {
- packages: ['@angular-devkit/build-angular'],
- next: true,
- }, appTree).pipe(
- map(() => {
- expect(hasPeerdepMsg('@angular/compiler-cli'))
- .toBeTruthy(`Should show @angular/compiler-cli message.`);
- expect(hasPeerdepMsg('typescript')).toBeTruthy(`Should show typescript message.`);
- expect(hasPeerdepMsg('@angular/localize'))
- .toBeFalsy(`Should not show @angular/localize message.`);
- }),
- ).toPromise().then(done, done.fail);
+ schematicRunner
+ .runSchematicAsync(
+ 'update',
+ {
+ packages: ['@angular-devkit/build-angular'],
+ next: true,
+ },
+ appTree,
+ )
+ .pipe(
+ map(() => {
+ expect(hasPeerdepMsg('@angular/compiler-cli')).toBeTruthy(
+ `Should show @angular/compiler-cli message.`,
+ );
+ expect(hasPeerdepMsg('typescript')).toBeTruthy(`Should show typescript message.`);
+ expect(hasPeerdepMsg('@angular/localize')).toBeFalsy(
+ `Should not show @angular/localize message.`,
+ );
+ }),
+ )
+ .toPromise()
+ .then(done, done.fail);
}, 45000);
});
diff --git a/packages/angular/cli/src/commands/update/schematic/npm.ts b/packages/angular/cli/src/commands/update/schematic/npm.ts
index 429a6ffd1745..f92f923458bd 100644
--- a/packages/angular/cli/src/commands/update/schematic/npm.ts
+++ b/packages/angular/cli/src/commands/update/schematic/npm.ts
@@ -45,9 +45,7 @@ function readOptions(
path.join(homedir(), dotFilename),
];
- const projectConfigLocations: string[] = [
- path.join(cwd, dotFilename),
- ];
+ const projectConfigLocations: string[] = [path.join(cwd, dotFilename)];
const root = path.parse(cwd).root;
for (let curDir = path.dirname(cwd); curDir && curDir !== root; curDir = path.dirname(curDir)) {
projectConfigLocations.unshift(path.join(curDir, dotFilename));
@@ -92,7 +90,7 @@ function readOptions(
const cafile = path.resolve(path.dirname(location), value);
try {
options['ca'] = readFileSync(cafile, 'utf8').replace(/\r?\n/g, '\n');
- } catch { }
+ } catch {}
}
break;
default:
@@ -141,23 +139,20 @@ export function getNpmPackageJson(
if (!npmrc) {
try {
npmrc = readOptions(logger, false, options && options.verbose);
- } catch { }
+ } catch {}
if (options && options.usingYarn) {
try {
npmrc = { ...npmrc, ...readOptions(logger, true, options && options.verbose) };
- } catch { }
+ } catch {}
}
}
- const resultPromise: Promise = pacote.packument(
- packageName,
- {
- fullMetadata: true,
- ...npmrc,
- ...(options && options.registryUrl ? { registry: options.registryUrl } : {}),
- },
- );
+ const resultPromise: Promise = pacote.packument(packageName, {
+ fullMetadata: true,
+ ...npmrc,
+ ...(options && options.registryUrl ? { registry: options.registryUrl } : {}),
+ });
// TODO: find some way to test this
const response = resultPromise.catch((err) => {
diff --git a/packages/angular/cli/src/commands/update/schematic/package-json.ts b/packages/angular/cli/src/commands/update/schematic/package-json.ts
index 3c77bdf98edd..7784e076f95d 100644
--- a/packages/angular/cli/src/commands/update/schematic/package-json.ts
+++ b/packages/angular/cli/src/commands/update/schematic/package-json.ts
@@ -23,7 +23,8 @@ export type JsonSchemaForNpmPackageJsonFiles = CoreProperties &
| {
bundledDependencies?: BundledDependency;
[k: string]: any;
- }) & {
+ }
+ ) & {
[k: string]: any;
};
/**
diff --git a/packages/angular/cli/src/commands/update/schematic/schema.json b/packages/angular/cli/src/commands/update/schematic/schema.json
index 8637bbbd7465..9811d1a3fe9a 100644
--- a/packages/angular/cli/src/commands/update/schematic/schema.json
+++ b/packages/angular/cli/src/commands/update/schematic/schema.json
@@ -57,14 +57,8 @@
"description": "The preferred package manager configuration files to use for registry settings.",
"type": "string",
"default": "npm",
- "enum": [
- "npm",
- "yarn",
- "cnpm",
- "pnpm"
- ]
+ "enum": ["npm", "yarn", "cnpm", "pnpm"]
}
},
- "required": [
- ]
+ "required": []
}
diff --git a/packages/angular/cli/utilities/install-package.ts b/packages/angular/cli/utilities/install-package.ts
index 4f1bdfd18158..a3d53729fad4 100644
--- a/packages/angular/cli/utilities/install-package.ts
+++ b/packages/angular/cli/utilities/install-package.ts
@@ -45,12 +45,16 @@ export function installPackage(
installArgs.push(packageManagerArgs.saveDev);
}
- const { status, stderr, stdout, error } = spawnSync(packageManager, [...installArgs, ...extraArgs], {
- stdio: 'pipe',
- shell: true,
- encoding: 'utf8',
- cwd,
- });
+ const { status, stderr, stdout, error } = spawnSync(
+ packageManager,
+ [...installArgs, ...extraArgs],
+ {
+ stdio: 'pipe',
+ shell: true,
+ encoding: 'utf8',
+ cwd,
+ },
+ );
if (status !== 0) {
let errorMessage = ((error && error.message) || stderr || stdout || '').trim();
@@ -75,7 +79,7 @@ export function installTempPackage(
process.on('exit', () => {
try {
rimraf.sync(tempPath);
- } catch { }
+ } catch {}
});
// NPM will warn when a `package.json` is not found in the install directory
@@ -87,12 +91,15 @@ export function installTempPackage(
// While we can use `npm init -y` we will end up needing to update the 'package.json' anyways
// because of missing fields.
- writeFileSync(join(tempPath, 'package.json'), JSON.stringify({
- name: 'temp-cli-install',
- description: 'temp-cli-install',
- repository: 'temp-cli-install',
- license: 'MIT',
- }));
+ writeFileSync(
+ join(tempPath, 'package.json'),
+ JSON.stringify({
+ name: 'temp-cli-install',
+ description: 'temp-cli-install',
+ repository: 'temp-cli-install',
+ license: 'MIT',
+ }),
+ );
// setup prefix/global modules path
const packageManagerArgs = getPackageManagerArguments(packageManager);
diff --git a/packages/angular/cli/utilities/json-file.ts b/packages/angular/cli/utilities/json-file.ts
index f27781c15525..466ee53b64af 100644
--- a/packages/angular/cli/utilities/json-file.ts
+++ b/packages/angular/cli/utilities/json-file.ts
@@ -8,8 +8,15 @@
import { JsonValue } from '@angular-devkit/core';
import { readFileSync, writeFileSync } from 'fs';
import {
- Node, ParseError, applyEdits, findNodeAtLocation,
- getNodeValue, modify, parse, parseTree, printParseErrorCode,
+ Node,
+ ParseError,
+ applyEdits,
+ findNodeAtLocation,
+ getNodeValue,
+ modify,
+ parse,
+ parseTree,
+ printParseErrorCode,
} from 'jsonc-parser';
export type InsertionIndex = (properties: string[]) => number;
@@ -19,9 +26,7 @@ export type JSONPath = (string | number)[];
export class JSONFile {
content: string;
- constructor(
- private readonly path: string,
- ) {
+ constructor(private readonly path: string) {
const buffer = readFileSync(this.path);
if (buffer) {
this.content = buffer.toString();
@@ -60,7 +65,11 @@ export class JSONFile {
return node === undefined ? undefined : getNodeValue(node);
}
- modify(jsonPath: JSONPath, value: JsonValue | undefined, insertInOrder?: InsertionIndex | false): boolean {
+ modify(
+ jsonPath: JSONPath,
+ value: JsonValue | undefined,
+ insertInOrder?: InsertionIndex | false,
+ ): boolean {
if (value === undefined && this.get(jsonPath) === undefined) {
// Cannot remove a value which doesn't exist.
return false;
@@ -69,23 +78,19 @@ export class JSONFile {
let getInsertionIndex: InsertionIndex | undefined;
if (insertInOrder === undefined) {
const property = jsonPath.slice(-1)[0];
- getInsertionIndex = properties => [...properties, property].sort().findIndex(p => p === property);
+ getInsertionIndex = (properties) =>
+ [...properties, property].sort().findIndex((p) => p === property);
} else if (insertInOrder !== false) {
getInsertionIndex = insertInOrder;
}
- const edits = modify(
- this.content,
- jsonPath,
- value,
- {
- getInsertionIndex,
- formattingOptions: {
- insertSpaces: true,
- tabSize: 2,
- },
+ const edits = modify(this.content, jsonPath, value, {
+ getInsertionIndex,
+ formattingOptions: {
+ insertSpaces: true,
+ tabSize: 2,
},
- );
+ });
if (edits.length === 0) {
return false;
@@ -115,7 +120,11 @@ export function readAndParseJson(path: string): any {
function formatError(path: string, errors: ParseError[]): never {
const { error, offset } = errors[0];
- throw new Error(`Failed to parse "${path}" as JSON AST Object. ${printParseErrorCode(error)} at location: ${offset}.`);
+ throw new Error(
+ `Failed to parse "${path}" as JSON AST Object. ${printParseErrorCode(
+ error,
+ )} at location: ${offset}.`,
+ );
}
// tslint:disable-next-line: no-any
diff --git a/packages/angular/cli/utilities/json-schema.ts b/packages/angular/cli/utilities/json-schema.ts
index 739debc1d01a..0206ed561f7c 100644
--- a/packages/angular/cli/utilities/json-schema.ts
+++ b/packages/angular/cli/utilities/json-schema.ts
@@ -20,7 +20,6 @@ import {
Value,
} from '../models/interface';
-
export class CommandJsonPathException extends BaseException {
constructor(public readonly path: string, public readonly name: string) {
super(`File ${path} was not found while constructing the subcommand ${name}.`);
@@ -37,7 +36,7 @@ function _getEnumFromValue(
}
if (Object.values(enumeration).includes(value)) {
- return value as unknown as T;
+ return (value as unknown) as T;
}
return defaultValue;
@@ -53,14 +52,14 @@ export async function parseJsonSchemaToSubCommandDescription(
const aliases: string[] = [];
if (json.isJsonArray(schema.$aliases)) {
- schema.$aliases.forEach(value => {
+ schema.$aliases.forEach((value) => {
if (typeof value == 'string') {
aliases.push(value);
}
});
}
if (json.isJsonArray(schema.aliases)) {
- schema.aliases.forEach(value => {
+ schema.aliases.forEach((value) => {
if (typeof value == 'string') {
aliases.push(value);
}
@@ -107,8 +106,7 @@ export async function parseJsonSchemaToCommandDescription(
registry: json.schema.SchemaRegistry,
schema: json.JsonObject,
): Promise {
- const subcommand =
- await parseJsonSchemaToSubCommandDescription(name, jsonPath, registry, schema);
+ const subcommand = await parseJsonSchemaToSubCommandDescription(name, jsonPath, registry, schema);
// Before doing any work, let's validate the implementation.
if (typeof schema.$impl != 'string') {
@@ -173,27 +171,31 @@ export async function parseJsonSchemaToOptions(
}
// We only support number, string or boolean (or array of those), so remove everything else.
- const types = [...typeSet].filter(x => {
- switch (x) {
- case 'boolean':
- case 'number':
- case 'string':
- return true;
-
- case 'array':
- // Only include arrays if they're boolean, string or number.
- if (json.isJsonObject(current.items)
- && typeof current.items.type == 'string'
- && ['boolean', 'number', 'string'].includes(current.items.type)) {
+ const types = [...typeSet]
+ .filter((x) => {
+ switch (x) {
+ case 'boolean':
+ case 'number':
+ case 'string':
return true;
- }
- return false;
+ case 'array':
+ // Only include arrays if they're boolean, string or number.
+ if (
+ json.isJsonObject(current.items) &&
+ typeof current.items.type == 'string' &&
+ ['boolean', 'number', 'string'].includes(current.items.type)
+ ) {
+ return true;
+ }
- default:
- return false;
- }
- }).map(x => _getEnumFromValue(x, OptionType, OptionType.String));
+ return false;
+
+ default:
+ return false;
+ }
+ })
+ .map((x) => _getEnumFromValue(x, OptionType, OptionType.String));
if (types.length == 0) {
// This means it's not usable on the command line. e.g. an Object.
@@ -201,7 +203,7 @@ export async function parseJsonSchemaToOptions(
}
// Only keep enum values we support (booleans, numbers and strings).
- const enumValues = (json.isJsonArray(current.enum) && current.enum || []).filter(x => {
+ const enumValues = ((json.isJsonArray(current.enum) && current.enum) || []).filter((x) => {
switch (typeof x) {
case 'boolean':
case 'number':
@@ -236,15 +238,19 @@ export async function parseJsonSchemaToOptions(
const type = types[0];
const $default = current.$default;
- const $defaultIndex = (json.isJsonObject($default) && $default['$source'] == 'argv')
- ? $default['index'] : undefined;
- const positional: number | undefined = typeof $defaultIndex == 'number'
- ? $defaultIndex : undefined;
+ const $defaultIndex =
+ json.isJsonObject($default) && $default['$source'] == 'argv' ? $default['index'] : undefined;
+ const positional: number | undefined =
+ typeof $defaultIndex == 'number' ? $defaultIndex : undefined;
const required = json.isJsonArray(current.required)
- ? current.required.indexOf(name) != -1 : false;
- const aliases = json.isJsonArray(current.aliases) ? [...current.aliases].map(x => '' + x)
- : current.alias ? ['' + current.alias] : [];
+ ? current.required.indexOf(name) != -1
+ : false;
+ const aliases = json.isJsonArray(current.aliases)
+ ? [...current.aliases].map((x) => '' + x)
+ : current.alias
+ ? ['' + current.alias]
+ : [];
const format = typeof current.format == 'string' ? current.format : undefined;
const visible = current.visible === undefined || current.visible === true;
const hidden = !!current.hidden || !visible;
@@ -254,22 +260,22 @@ export async function parseJsonSchemaToOptions(
// Deprecated is set only if it's true or a string.
const xDeprecated = current['x-deprecated'];
- const deprecated = (xDeprecated === true || typeof xDeprecated === 'string')
- ? xDeprecated : undefined;
+ const deprecated =
+ xDeprecated === true || typeof xDeprecated === 'string' ? xDeprecated : undefined;
const option: Option = {
name,
description: '' + (current.description === undefined ? '' : current.description),
- ...types.length == 1 ? { type } : { type, types },
- ...defaultValue !== undefined ? { default: defaultValue } : {},
- ...enumValues && enumValues.length > 0 ? { enum: enumValues } : {},
+ ...(types.length == 1 ? { type } : { type, types }),
+ ...(defaultValue !== undefined ? { default: defaultValue } : {}),
+ ...(enumValues && enumValues.length > 0 ? { enum: enumValues } : {}),
required,
aliases,
- ...format !== undefined ? { format } : {},
+ ...(format !== undefined ? { format } : {}),
hidden,
- ...userAnalytics ? { userAnalytics } : {},
- ...deprecated !== undefined ? { deprecated } : {},
- ...positional !== undefined ? { positional } : {},
+ ...(userAnalytics ? { userAnalytics } : {}),
+ ...(deprecated !== undefined ? { deprecated } : {}),
+ ...(positional !== undefined ? { positional } : {}),
};
options.push(option);
diff --git a/packages/angular/cli/utilities/json-schema_spec.ts b/packages/angular/cli/utilities/json-schema_spec.ts
index 65ad06a72bb4..f300cc4bc077 100644
--- a/packages/angular/cli/utilities/json-schema_spec.ts
+++ b/packages/angular/cli/utilities/json-schema_spec.ts
@@ -24,9 +24,7 @@ describe('parseJsonSchemaToCommandDescription', () => {
'$impl': './version-impl#VersionCommand',
'type': 'object',
- 'allOf': [
- { '$ref': './definitions.json#/definitions/base' },
- ],
+ 'allOf': [{ '$ref': './definitions.json#/definitions/base' }],
};
beforeEach(() => {
@@ -34,7 +32,9 @@ describe('parseJsonSchemaToCommandDescription', () => {
registry.registerUriHandler((uri: string) => {
if (uri.startsWith('ng-cli://')) {
const content = readFileSync(
- join(__dirname, '..', uri.substr('ng-cli://'.length)), 'utf-8');
+ join(__dirname, '..', uri.substr('ng-cli://'.length)),
+ 'utf-8',
+ );
return Promise.resolve(JSON.parse(content));
} else {
diff --git a/packages/angular/cli/utilities/package-manager.ts b/packages/angular/cli/utilities/package-manager.ts
index c56b7dc1c517..c049d1c3836e 100644
--- a/packages/angular/cli/utilities/package-manager.ts
+++ b/packages/angular/cli/utilities/package-manager.ts
@@ -32,7 +32,7 @@ export function supportsNpm(): boolean {
}
export async function getPackageManager(root: string): Promise {
- let packageManager = await getConfiguredPackageManager() as PackageManager | null;
+ let packageManager = (await getConfiguredPackageManager()) as PackageManager | null;
if (packageManager) {
return packageManager;
}
@@ -66,7 +66,7 @@ export async function ensureCompatibleNpm(root: string): Promise {
}
try {
- const versionText = execSync('npm --version', {encoding: 'utf8', stdio: 'pipe'}).trim();
+ const versionText = execSync('npm --version', { encoding: 'utf8', stdio: 'pipe' }).trim();
const version = valid(versionText);
if (!version) {
return;
diff --git a/packages/angular/cli/utilities/package-metadata.ts b/packages/angular/cli/utilities/package-metadata.ts
index 84c5142a8b1e..e39aa590b1f6 100644
--- a/packages/angular/cli/utilities/package-metadata.ts
+++ b/packages/angular/cli/utilities/package-metadata.ts
@@ -66,12 +66,12 @@ function ensureNpmrc(logger: logging.LoggerApi, usingYarn: boolean, verbose: boo
if (!npmrc) {
try {
npmrc = readOptions(logger, false, verbose);
- } catch { }
+ } catch {}
if (usingYarn) {
try {
npmrc = { ...npmrc, ...readOptions(logger, true, verbose) };
- } catch { }
+ } catch {}
}
}
}
@@ -145,7 +145,7 @@ function readOptions(
const cafile = path.resolve(path.dirname(location), value);
try {
options['ca'] = readFileSync(cafile, 'utf8').replace(/\r?\n/g, '\n');
- } catch { }
+ } catch {}
}
break;
default:
diff --git a/packages/angular/cli/utilities/package-tree.ts b/packages/angular/cli/utilities/package-tree.ts
index 06413799648f..9b5bca0b30eb 100644
--- a/packages/angular/cli/utilities/package-tree.ts
+++ b/packages/angular/cli/utilities/package-tree.ts
@@ -66,7 +66,7 @@ export async function getProjectDependencies(dir: string): Promise