mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
Compare commits
287 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a4c9e8df6d | |||
| 8722eddd1d | |||
| d6528b157f | |||
| 2d8ad6c7fe | |||
| 13c5585fb9 | |||
| 7a084c8134 | |||
| c086653655 | |||
| 3dd7bb3f8f | |||
| 79a973aec8 | |||
| d05e9a96e5 | |||
| 6ad7b40a6f | |||
| 5d3b97e1f8 | |||
| c79bb148fc | |||
| 8ce0b33b60 | |||
| 180a15e81e | |||
| 9022787f8c | |||
| 7f137fc27b | |||
| 6b82eb13b8 | |||
| 516c8366a7 | |||
| 74451fdca7 | |||
| 66dd534f06 | |||
| 0ac2e54b0c | |||
| 639277b96f | |||
| 8fac2995fc | |||
| 14b96287e9 | |||
| 52c949c91b | |||
| 4c4700bf2e | |||
| 91422ccd7b | |||
| 958dcf81b2 | |||
| 88e16553e8 | |||
| ddc2e70a39 | |||
| 469d9b6ebe | |||
| d2470cc568 | |||
| ce74beacf2 | |||
| 12edfad39b | |||
| 4a1ff28547 | |||
| 0abfa7681c | |||
| b5d5f76c9d | |||
| a0f3c81bb3 | |||
| 3fd8948b4a | |||
| b92c1a6ada | |||
| 8ac3513b62 | |||
| 75c953f55b | |||
| bd9bf1d210 | |||
| 9b5c493b77 | |||
| f7d4d13968 | |||
| 621ab9fc9d | |||
| 6b82b643c8 | |||
| bcef929f19 | |||
| b60d15c704 | |||
| cac6ef76c4 | |||
| fc97c768f7 | |||
| 77ae8e1c20 | |||
| a1c3dbf4fe | |||
| 8ecfd71fd7 | |||
| c2ba7c4149 | |||
| 4139fbe4b5 | |||
| 0d0ae6dbec | |||
| c8b0ebb0fb | |||
| 074075d551 | |||
| d6ee9f29e6 | |||
| ef5cba3df7 | |||
| 16c71fc56f | |||
| 9fe1a156e1 | |||
| f0b94f5b48 | |||
| 31d6f32f76 | |||
| 34ba41f1aa | |||
| 5b7c131658 | |||
| 6abe57fedd | |||
| 1f31dae40d | |||
| 862aafbec9 | |||
| b20e470704 | |||
| 6862438711 | |||
| 9f5558cb2a | |||
| 43e4ba42b2 | |||
| 19da41308f | |||
| 9b5cc21ff7 | |||
| 5408a1e130 | |||
| b52daff813 | |||
| ef12d56cf1 | |||
| d17c7ddbb8 | |||
| 8c32114df3 | |||
| b00d237c0e | |||
| e7ff714189 | |||
| d023270472 | |||
| dde0b7f4b3 | |||
| 765090adf6 | |||
| 66040711ee | |||
| 9df8ceafd8 | |||
| 90fa5fee7a | |||
| 03f840535b | |||
| dee2ba900e | |||
| 0cc2b89efa | |||
| 7206e3f4f9 | |||
| f708c87c7d | |||
| 9cff09ea1f | |||
| f30179d973 | |||
| b52b40ee2c | |||
| ed570453da | |||
| 36983a469a | |||
| 9a0a7bac21 | |||
| 67aca23bd4 | |||
| f35f01984a | |||
| d627b8f10b | |||
| b497aa0cf7 | |||
| 19b4cc969d | |||
| 420fb46ad6 | |||
| 127e794885 | |||
| de49652fd7 | |||
| 6280a98ff1 | |||
| bf6b44be35 | |||
| c2c520341f | |||
| e813f3c7e9 | |||
| 536939e138 | |||
| 083a9c4dc4 | |||
| d982fa7da2 | |||
| 763c5f8991 | |||
| 0111f6c75e | |||
| c90193475f | |||
| 51baa0b448 | |||
| 19db22e911 | |||
| fa358feef0 | |||
| 1dd58b5e2a | |||
| 0a68506d77 | |||
| b8c15eb257 | |||
| 416d535d1e | |||
| ba9f30c9a6 | |||
| 5dee53b352 | |||
| 35653ce337 | |||
| 12938577ef | |||
| 560188bf12 | |||
| d7c358139e | |||
| 568269f124 | |||
| 136358f1a0 | |||
| 724e88e042 | |||
| 1798ce99b6 | |||
| 0bc77f4cab | |||
| 542d4c7805 | |||
| ff172d2818 | |||
| ddce357d1d | |||
| ce66cfc765 | |||
| ab90d8dcc2 | |||
| af21c5f008 | |||
| 2360708cc0 | |||
| 05fd839eb1 | |||
| 4204936b49 | |||
| 60a9910f05 | |||
| 97fe33866e | |||
| c578aeec74 | |||
| 21a04ef5be | |||
| e03eb282cb | |||
| d7912ca7d6 | |||
| 8cccc830d2 | |||
| 21f1d5979d | |||
| 61bfb7afba | |||
| bf340479ca | |||
| 3654d7ab1a | |||
| b5ecae307e | |||
| c7683e1cbd | |||
| 933f1945ed | |||
| 8ea4e1e6eb | |||
| 3dec816276 | |||
| 060d36f67a | |||
| 82399133cb | |||
| c92b242f22 | |||
| 9d1f489542 | |||
| 7059655a0b | |||
| f2e5234e07 | |||
| 2949ae340c | |||
| 3172b4cc99 | |||
| 42db488ed7 | |||
| 45ed2b7584 | |||
| b11a939e21 | |||
| df339d8abf | |||
| 701405fa71 | |||
| 4f1a813596 | |||
| 2c52284e44 | |||
| 183b5f3fde | |||
| ad93c28889 | |||
| f02ba99820 | |||
| 45eb491a25 | |||
| 054cb99421 | |||
| 05f0cd7727 | |||
| 2e96cede3e | |||
| 39be06037d | |||
| 2bc65351b4 | |||
| 8869fce1a4 | |||
| 74ff3b55c1 | |||
| 35f20afcac | |||
| a524a50361 | |||
| 37dbe55945 | |||
| cb479bfa46 | |||
| 5a04963305 | |||
| f92add1157 | |||
| 338de1b4cf | |||
| 79025a69ba | |||
| add2bb8e89 | |||
| 29ac86deb8 | |||
| 2d444db6b4 | |||
| b8e27fafa1 | |||
| 97e90f8470 | |||
| c14c5fcb86 | |||
| af5b3c181a | |||
| 3e2b443b20 | |||
| 29ad2aa44b | |||
| 063fc8cde3 | |||
| 4b2c3617d0 | |||
| e56e6d6166 | |||
| 5879e4616f | |||
| 3c690bc1e9 | |||
| 018550ed50 | |||
| 39a1364e43 | |||
| 9b97b840af | |||
| 5e71f2abc0 | |||
| 3ae133c69e | |||
| 9cd2626e63 | |||
| f1a15dadfa | |||
| 333c23d0d9 | |||
| 19018ca61e | |||
| bcef46d83e | |||
| 77c9508e51 | |||
| 3f7ecec59b | |||
| 45fedb50c4 | |||
| 25fde5db4c | |||
| 42ab829684 | |||
| 4e82bcd08c | |||
| d7ad280941 | |||
| 9cd8e50848 | |||
| b056f1b823 | |||
| 1c0d0f0579 | |||
| ffbf6b67ac | |||
| c3c82b69fb | |||
| f70b84f755 | |||
| 51e3722e77 | |||
| 1d3cf22abb | |||
| 23c4c9601e | |||
| 9f6fa5b746 | |||
| 7dd6450a26 | |||
| 13fad9febe | |||
| 5d13e58aed | |||
| 4a173eb3f8 | |||
| 8e9efbd1f2 | |||
| f76bf8a27d | |||
| 6984dde030 | |||
| 9afb6e31a4 | |||
| fbf6f1f9bf | |||
| 13eb6ca1bf | |||
| 6ec6c87ce1 | |||
| bfe6985d1e | |||
| e9317aee71 | |||
| fbf42ed9d8 | |||
| 216af1c234 | |||
| a267484cde | |||
| 57d1bc09be | |||
| ac7f0460f9 | |||
| 4d27448f21 | |||
| eae93b235f | |||
| 883194a3f8 | |||
| 663c1f905e | |||
| eb511d9c3f | |||
| 141bb16632 | |||
| 74a2e2e2ec | |||
| 018b917602 | |||
| 06bfcb2be3 | |||
| 323ef1ebf7 | |||
| fe2855167a | |||
| ff2dc4a719 | |||
| 86f0213303 | |||
| d48e0ccc01 | |||
| f94055dee6 | |||
| 7604585cd3 | |||
| af36adf540 | |||
| 58a8bd3df2 | |||
| c793efd9b7 | |||
| f6543c25aa | |||
| 3f9faad356 | |||
| 40bf2a6a81 | |||
| dcea70fab7 | |||
| 1e4e9ee9a7 | |||
| d80018b7ca | |||
| 8786c609f8 | |||
| d93ca6cc81 | |||
| 4dbcf9766b | |||
| e586cb8124 | |||
| de008f1149 | |||
| 0c61ea426a | |||
| 967e9345b3 |
@@ -38,6 +38,8 @@ test --incompatible_strict_action_env
|
||||
# and https://github.com/bazelbuild/bazel/commit/03246077f948f2790a83520e7dccc2625650e6df
|
||||
build --nobuild_runfile_links
|
||||
|
||||
build --enable_runfiles
|
||||
|
||||
###############################
|
||||
# Release support #
|
||||
# Turn on these settings with #
|
||||
@@ -51,8 +53,8 @@ build:release --workspace_status_command="yarn -s ng-dev release build-env-stamp
|
||||
build:release --stamp
|
||||
|
||||
# Snapshots should also be stamped with version control information.
|
||||
build:snapshot --workspace_status_command="yarn -s ng-dev release build-env-stamp --mode=snapshot"
|
||||
build:snapshot --stamp
|
||||
build:snapshot-build --workspace_status_command="yarn -s ng-dev release build-env-stamp --mode=snapshot"
|
||||
build:snapshot-build --stamp
|
||||
|
||||
###############################
|
||||
# Output #
|
||||
|
||||
@@ -31,8 +31,8 @@ var_3: &cache_key v6-angular-node-14-{{ checksum "month.txt" }}-{{ checksum ".ba
|
||||
var_4: &cache_key_fallback v6-angular-node-14-{{ checksum "month.txt" }}-{{ checksum ".bazelversion" }}
|
||||
|
||||
# Windows needs its own cache key because binaries in node_modules are different.
|
||||
var_3_win: &cache_key_win v7-angular-win-node-14-{{ checksum "month.txt" }}-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}
|
||||
var_4_win: &cache_key_win_fallback v7-angular-win-node-14-{{ checksum "month.txt" }}-{{ checksum ".bazelversion" }}
|
||||
var_3_win: &cache_key_win v8-angular-win-node-14-{{ checksum "month.txt" }}-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}
|
||||
var_4_win: &cache_key_win_fallback v8-angular-win-node-14-{{ checksum "month.txt" }}-{{ checksum ".bazelversion" }}
|
||||
|
||||
# Cache key for the `components-repo-unit-tests` job. **Note** when updating the SHA in the
|
||||
# cache keys also update the SHA for the "COMPONENTS_REPO_COMMIT" environment variable.
|
||||
@@ -64,8 +64,6 @@ var_10: &only_on_main_branch
|
||||
branches:
|
||||
only:
|
||||
- main
|
||||
# TODO(BRANCH_RENAME_CLEANUP): remove
|
||||
- master
|
||||
|
||||
# Filter to run a job on all releasable branches.
|
||||
var_11: &only_release_branches
|
||||
@@ -73,8 +71,6 @@ var_11: &only_release_branches
|
||||
branches:
|
||||
only:
|
||||
- main
|
||||
# TODO(BRANCH_RENAME_CLEANUP): remove
|
||||
- master
|
||||
- /\d+\.\d+\.x/
|
||||
|
||||
# CircleCI orbs
|
||||
@@ -308,7 +304,7 @@ jobs:
|
||||
path: dist/bin/packages/core/test/bundling/todo/bundle.min.js.br
|
||||
destination: core/todo/bundle.br
|
||||
|
||||
# NOTE: This is currently limited to master builds only. See the `monitoring` configuration.
|
||||
# NOTE: This is currently limited to main builds only. See the `monitoring` configuration.
|
||||
saucelabs:
|
||||
executor:
|
||||
name: default-executor
|
||||
@@ -446,7 +442,7 @@ jobs:
|
||||
steps:
|
||||
- custom_attach_workspace
|
||||
- init_environment
|
||||
- run: node scripts/build/build-packages-dist.js
|
||||
- run: yarn build
|
||||
|
||||
# Save the npm packages from //packages/... for other workflow jobs to read
|
||||
- persist_to_workspace:
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ setSecretVar CI_SECRET_PAYLOAD_FIREBASE_TOKEN "$ANGULAR_PAYLOAD_TOKEN";
|
||||
# Define SauceLabs environment variables for CircleCI.
|
||||
####################################################################################################
|
||||
setPublicVar SAUCE_USERNAME "angular-framework";
|
||||
setSecretVar SAUCE_ACCESS_KEY "0c731274ed5f-cbc9-16f4-021a-9835e39f";
|
||||
setSecretVar SAUCE_ACCESS_KEY "f4bf7c639c5a-c6bb-d6a4-a4b5-800aa111";
|
||||
# TODO(josephperrott): Remove environment variables once all saucelabs tests are via bazel method.
|
||||
setPublicVar SAUCE_LOG_FILE /tmp/angular/sauce-connect.log
|
||||
setPublicVar SAUCE_READY_FILE /tmp/angular/sauce-connect-ready-file.lock
|
||||
|
||||
@@ -101,14 +101,6 @@ function getRefFromBranchList(gitOutput) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// TODO(BRANCH_RENAME_CLEANUP): remove
|
||||
if (a === 'master') {
|
||||
return -1;
|
||||
}
|
||||
if (b === 'master') {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const aIsSemver = semverRegex.test(a);
|
||||
const bIsSemver = semverRegex.test(b);
|
||||
if (aIsSemver && bIsSemver) {
|
||||
|
||||
@@ -10,5 +10,5 @@ contact_links:
|
||||
url: https://github.com/angular/components/issues/new/choose
|
||||
about: Issues and feature requests for Angular Material
|
||||
- name: Support Request
|
||||
url: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
|
||||
url: https://github.com/angular/angular/blob/main/CONTRIBUTING.md#question
|
||||
about: Questions and requests for support
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
## PR Checklist
|
||||
Please check if your PR fulfills the following requirements:
|
||||
|
||||
- [ ] The commit message follows our guidelines: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
|
||||
- [ ] The commit message follows our guidelines: https://github.com/angular/angular/blob/main/CONTRIBUTING.md#commit
|
||||
- [ ] Tests for the changes have been added (for bug fixes / features)
|
||||
- [ ] Docs have been added / updated (for bug fixes / features)
|
||||
|
||||
|
||||
@@ -42,13 +42,26 @@ merge:
|
||||
exclude:
|
||||
- 'packages/*'
|
||||
- 'packages/bazel/*'
|
||||
- 'packages/bazel/src/*'
|
||||
- 'packages/bazel/src/api-extractor/**'
|
||||
- 'packages/bazel/src/ng_package/**'
|
||||
- 'packages/bazel/src/builders/**'
|
||||
- 'packages/bazel/src/ng_module/**'
|
||||
- 'packages/bazel/src/ng_package/**'
|
||||
- 'packages/bazel/src/protractor/**'
|
||||
- 'packages/bazel/src/schematics/**'
|
||||
- 'packages/bazel/src/types_bundle/**'
|
||||
- 'packages/compiler-cli/src/ngcc/**'
|
||||
- 'packages/compiler-cli/linker/**'
|
||||
- 'packages/compiler-cli/ngcc/**'
|
||||
- 'packages/compiler-cli/src/ngtsc/sourcemaps/**'
|
||||
# 'private' mostly contains entrypoints for 3P Angular.
|
||||
# Note that 'private/migrations' _is_ used.
|
||||
- 'packages/compiler-cli/private/bazel.ts'
|
||||
- 'packages/compiler-cli/private/localize.ts'
|
||||
- 'packages/compiler-cli/private/tooling.ts'
|
||||
- 'packages/compiler-cli/private/babel.d.ts'
|
||||
# google3 defines its own binary entrypoints.
|
||||
- 'packages/compiler-cli/src/bin/**'
|
||||
- 'packages/docs/**'
|
||||
- 'packages/elements/schematics/**'
|
||||
- 'packages/examples/**'
|
||||
@@ -56,7 +69,8 @@ merge:
|
||||
- 'packages/localize/**'
|
||||
- 'packages/private/**'
|
||||
- 'packages/service-worker/**'
|
||||
- 'packages/common/locales/**'
|
||||
- 'packages/common/locales/generate-locales-tool/**'
|
||||
- 'packages/common/locales/index.bzl'
|
||||
- 'packages/http/**'
|
||||
- '**/.gitignore'
|
||||
- '**/.gitkeep'
|
||||
@@ -97,7 +111,7 @@ merge:
|
||||
|
||||
# whether the PR shouldn't have a conflict with the base branch
|
||||
noConflict: true
|
||||
# list of labels that a PR needs to have, checked with a regexp (e.g. "target:" will work for the label "target: master")
|
||||
# list of labels that a PR needs to have, checked with a regexp.
|
||||
requiredLabels:
|
||||
- 'target: *'
|
||||
|
||||
@@ -119,7 +133,7 @@ merge:
|
||||
# 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
|
||||
# {{PLACEHOLDER}} will be replaced by the list of failing checks
|
||||
mergeRemovedComment: "I see that you just added the `{{MERGE_LABEL}}` label, but the following checks are still failing:\n{{PLACEHOLDER}}\n\n**If you want your PR to be merged, it has to pass all the CI checks.**\n\nIf you can't get the PR to a green state due to flakes or broken master, please try rebasing to master and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help."
|
||||
mergeRemovedComment: "I see that you just added the `{{MERGE_LABEL}}` label, but the following checks are still failing:\n{{PLACEHOLDER}}\n\n**If you want your PR to be merged, it has to pass all the CI checks.**\n\nIf you can't get the PR to a green state due to flakes or broken `main`, please try rebasing to `main` and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help."
|
||||
|
||||
# options for the triage plugin
|
||||
triage:
|
||||
|
||||
@@ -13,6 +13,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2
|
||||
- uses: angular/dev-infra/github-actions/commit-message-based-labels@a7d07a6f66c05791fdde2dd372da4ba55c1d524b
|
||||
- uses: angular/dev-infra/github-actions/commit-message-based-labels@91ba217766e28a53c469d5ca43a76e37af64e3f1
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
post_approval_changes:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2
|
||||
- uses: angular/dev-infra/github-actions/post-approval-changes@91ba217766e28a53c469d5ca43a76e37af64e3f1
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -14,6 +14,6 @@ jobs:
|
||||
if: github.repository == 'angular/angular'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: angular/dev-infra/github-actions/feature-request@a7d07a6f66c05791fdde2dd372da4ba55c1d524b
|
||||
- uses: angular/dev-infra/github-actions/feature-request@91ba217766e28a53c469d5ca43a76e37af64e3f1
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -14,6 +14,6 @@ jobs:
|
||||
if: github.repository == 'angular/angular'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: angular/dev-infra/github-actions/lock-closed@a7d07a6f66c05791fdde2dd372da4ba55c1d524b
|
||||
- uses: angular/dev-infra/github-actions/lock-closed@91ba217766e28a53c469d5ca43a76e37af64e3f1
|
||||
with:
|
||||
lock-bot-key: ${{ secrets.LOCK_BOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -4,11 +4,7 @@ on:
|
||||
schedule:
|
||||
- cron: '0 0 * * 0'
|
||||
push:
|
||||
branches: [
|
||||
main,
|
||||
# TODO(BRANCH_RENAME_CLEANUP): remove
|
||||
master,
|
||||
]
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
# Declare default permissions as read only.
|
||||
@@ -27,12 +23,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: 'Checkout code'
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # tag=v3.0.0
|
||||
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: 'Run analysis'
|
||||
uses: ossf/scorecard-action@c1aec4ac820532bab364f02a81873c555a0ba3a1 # renovate: tag=v1.0.4
|
||||
uses: ossf/scorecard-action@3e15ea8318eee9b333819ec77a36aca8d39df13e # tag=v1.1.1
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
@@ -41,7 +37,7 @@ jobs:
|
||||
|
||||
# Upload the results as artifacts.
|
||||
- name: 'Upload artifact'
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # tag=v3.0.0
|
||||
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # tag=v3.1.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
@@ -49,6 +45,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: 'Upload to code-scanning'
|
||||
uses: github/codeql-action/upload-sarif@1ed1437484560351c5be56cf73a48a279d116b78 # tag=v2.1.8
|
||||
uses: github/codeql-action/upload-sarif@d00e8c09a38ef8c1ca1091fc55ef490776d2de73 # tag=v2.1.13
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
+3
-3
@@ -74,7 +74,7 @@ Fixes #<issue number>
|
||||
# =============================
|
||||
#
|
||||
# The full specification of the Angular Commit Message Format can be found at
|
||||
# https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
|
||||
# https://github.com/angular/angular/blob/main/CONTRIBUTING.md#commit
|
||||
#
|
||||
# The following is an excerpt of the specification with the most commonly needed info.
|
||||
#
|
||||
@@ -108,10 +108,10 @@ Fixes #<issue number>
|
||||
# │ platform-browser-dynamic|platform-server|router|service-worker|
|
||||
# │ upgrade|zone.js|packaging|changelog|docs-infra|migrations|ngcc|ve|
|
||||
# │ devtools
|
||||
# │ https://github.com/angular/angular/blob/master/CONTRIBUTING.md#scope
|
||||
# │ https://github.com/angular/angular/blob/main/CONTRIBUTING.md#scope
|
||||
# │
|
||||
# └─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test
|
||||
# https://github.com/angular/angular/blob/master/CONTRIBUTING.md#type
|
||||
# https://github.com/angular/angular/blob/main/CONTRIBUTING.md#type
|
||||
#
|
||||
#
|
||||
# Commit Message Body
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import {caretaker} from './caretaker.mjs';
|
||||
import {commitMessage} from './commit-message.mjs';
|
||||
import {format} from './format.mjs';
|
||||
import {github} from './github.mjs';
|
||||
import {pullRequest} from './pull-request.mjs';
|
||||
import {release} from './release.mjs';
|
||||
|
||||
export {
|
||||
commitMessage,
|
||||
format,
|
||||
github,
|
||||
pullRequest,
|
||||
caretaker,
|
||||
release,
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
import {caretaker} from './caretaker';
|
||||
import {commitMessage} from './commit-message';
|
||||
import {format} from './format';
|
||||
import {github} from './github';
|
||||
import {pullRequest} from './pullRequest';
|
||||
import {release} from './release';
|
||||
|
||||
module.exports = {
|
||||
commitMessage,
|
||||
format,
|
||||
github,
|
||||
pullRequest,
|
||||
caretaker,
|
||||
release,
|
||||
};
|
||||
@@ -1,5 +1,4 @@
|
||||
import {ReleaseConfig} from '@angular/dev-infra-private/ng-dev';
|
||||
import {join} from 'path';
|
||||
|
||||
/** Configuration for the `ng-dev release` command. */
|
||||
export const release: ReleaseConfig = {
|
||||
@@ -24,13 +23,13 @@ export const release: ReleaseConfig = {
|
||||
{name: '@angular/upgrade'},
|
||||
],
|
||||
buildPackages: async () => {
|
||||
// The buildTargetPackages function is loaded at runtime as the loading the script causes an
|
||||
// invocation of bazel.
|
||||
const {buildTargetPackages} = require(join(__dirname, '../scripts/build/package-builder'));
|
||||
return buildTargetPackages('dist/release-output', false, 'Release', /* isRelease */ true);
|
||||
// The buildTargetPackages function is loaded at runtime as the loading the script
|
||||
// causes an invocation of Bazel.
|
||||
const {performNpmReleaseBuild} = await import('../scripts/build/package-builder.mjs');
|
||||
return performNpmReleaseBuild();
|
||||
},
|
||||
releaseNotes: {
|
||||
hiddenScopes: ['aio', 'dev-infra', 'docs-infra', 'zone.js', 'devtools'],
|
||||
hiddenScopes: ['aio', 'bazel', 'dev-infra', 'docs-infra', 'zone.js', 'devtools'],
|
||||
},
|
||||
releasePrLabels: ['comp: build & ci', 'action: merge', 'PullApprove: disable'],
|
||||
};
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"target": "es2015",
|
||||
"module": "commonjs",
|
||||
"target": "es2020",
|
||||
"module": "Node16",
|
||||
"noEmit": true,
|
||||
"skipLibCheck": true,
|
||||
"types": []
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
+16
-4
@@ -236,6 +236,12 @@ groups:
|
||||
'aio/content/images/guide/attribute-directives/**',
|
||||
'aio/content/guide/bootstrapping.md',
|
||||
'aio/content/examples/bootstrapping/**',
|
||||
'aio/content/guide/change-detection.md',
|
||||
'aio/content/guide/change-detection-zone-pollution.md',
|
||||
'aio/content/guide/change-detection-slow-computations.md',
|
||||
'aio/content/guide/change-detection-skipping-subtrees.md',
|
||||
'aio/content/images/guide/change-detection/**',
|
||||
'aio/content/guide/class-binding.md',
|
||||
'aio/content/guide/cheatsheet.md',
|
||||
'aio/content/guide/component-interaction.md',
|
||||
'aio/content/examples/component-interaction/**',
|
||||
@@ -287,6 +293,7 @@ groups:
|
||||
'aio/content/guide/ngmodule-faq.md',
|
||||
'aio/content/guide/ngmodule-vs-jsmodule.md',
|
||||
'aio/content/guide/module-types.md',
|
||||
'aio/content/guide/template-overview.md',
|
||||
'aio/content/guide/template-syntax.md',
|
||||
'aio/content/guide/built-in-template-functions.md',
|
||||
'aio/content/examples/built-in-template-functions/**',
|
||||
@@ -297,6 +304,7 @@ groups:
|
||||
'aio/content/examples/interpolation/**',
|
||||
'aio/content/examples/template-syntax/**',
|
||||
'aio/content/images/guide/template-syntax/**',
|
||||
'aio/content/guide/binding-overview.md',
|
||||
'aio/content/guide/binding-syntax.md',
|
||||
'aio/content/examples/binding-syntax/**',
|
||||
'aio/content/guide/property-binding.md',
|
||||
@@ -314,20 +322,22 @@ groups:
|
||||
'aio/content/guide/inputs-outputs.md',
|
||||
'aio/content/examples/inputs-outputs/**',
|
||||
'aio/content/images/guide/inputs-outputs/**',
|
||||
'aio/content/guide/understanding-template-expr-overview.md',
|
||||
'aio/content/guide/template-expression-operators.md',
|
||||
'aio/content/examples/template-expression-operators/**',
|
||||
'aio/content/guide/pipes.md',
|
||||
'aio/content/guide/pipes-custom-data-trans.md',
|
||||
'aio/content/guide/pipes-overview.md',
|
||||
'aio/content/guide/pipes-transform-data.md',
|
||||
'aio/content/guide/pipe-template.md',
|
||||
'aio/content/examples/pipes/**',
|
||||
'aio/content/images/guide/pipes/**',
|
||||
'aio/content/guide/providers.md',
|
||||
'aio/content/examples/providers/**',
|
||||
'aio/content/images/guide/providers/**',
|
||||
'aio/content/guide/singleton-services.md',
|
||||
'aio/content/guide/set-document-title.md',
|
||||
'aio/content/examples/set-document-title/**',
|
||||
'aio/content/images/guide/set-document-title/**',
|
||||
'aio/content/guide/sharing-ngmodules.md',
|
||||
'aio/content/guide/standalone-components.md',
|
||||
'aio/content/guide/structural-directives.md',
|
||||
'aio/content/examples/structural-directives/**',
|
||||
'aio/content/guide/svg-in-templates.md',
|
||||
@@ -436,6 +446,7 @@ groups:
|
||||
'aio/content/examples/forms-overview/**',
|
||||
'aio/content/images/guide/forms-overview/**',
|
||||
'aio/content/guide/form-validation.md',
|
||||
'aio/content/guide/typed-forms.md',
|
||||
'aio/content/examples/form-validation/**',
|
||||
'aio/content/images/guide/form-validation/**',
|
||||
'aio/content/guide/dynamic-form.md',
|
||||
@@ -975,6 +986,7 @@ groups:
|
||||
'aio/content/examples/setup/**',
|
||||
'aio/content/guide/build.md',
|
||||
'aio/content/images/guide/build/**',
|
||||
'aio/content/images/guide/cli/**',
|
||||
'aio/content/guide/cli-builder.md',
|
||||
'aio/content/examples/cli-builder/**',
|
||||
'aio/content/guide/deployment.md',
|
||||
@@ -985,7 +997,6 @@ groups:
|
||||
'aio/content/guide/web-worker.md',
|
||||
'aio/content/guide/workspace-config.md',
|
||||
'aio/content/guide/migration-solution-style-tsconfig.md',
|
||||
'aio/content/guide/migration-update-module-and-target-compiler-options.md',
|
||||
'aio/content/guide/migration-update-libraries-tslib.md',
|
||||
])
|
||||
reviewers:
|
||||
@@ -1113,6 +1124,7 @@ groups:
|
||||
'packages/examples/*',
|
||||
'scripts/**',
|
||||
'third_party/**',
|
||||
'tools/bazel-repo-patches/**',
|
||||
'tools/build/**',
|
||||
'tools/circular_dependency_test/**',
|
||||
'tools/contributing-stats/**',
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary")
|
||||
load("//tools:defaults.bzl", "nodejs_binary")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
|
||||
+337
-514
@@ -1,50 +1,378 @@
|
||||
<a name="13.3.6"></a>
|
||||
# 13.3.6 (2022-05-04)
|
||||
<a name="14.0.3"></a>
|
||||
# 14.0.3 (2022-06-22)
|
||||
### animations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [3dd7bb3f8f](https://github.com/angular/angular/commit/3dd7bb3f8fa009e245bfc91aa06a485d0cb27586) | fix | reset the start and done fns on player reset ([#46364](https://github.com/angular/angular/pull/46364)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [c086653655](https://github.com/angular/angular/commit/c0866536558fa5abb91e1ba51fa84ea0321e6864) | fix | deduplicate imports of standalone components in JIT compiler ([#46439](https://github.com/angular/angular/pull/46439)) |
|
||||
| [5d3b97e1f8](https://github.com/angular/angular/commit/5d3b97e1f8d5d004621df1004e00f128064d73cd) | fix | handle NgModules with standalone pipes in TestBed correctly ([#46407](https://github.com/angular/angular/pull/46407)) |
|
||||
### platform-server
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [6ad7b40a6f](https://github.com/angular/angular/commit/6ad7b40a6fe1b447173a44e7750f2b9abcb6fc0a) | fix | invalid style attribute being generated for null values ([#46433](https://github.com/angular/angular/pull/46433)) |
|
||||
## Special Thanks
|
||||
Andrew Kushnir, Andrew Scott, George Kalpakas, Paul Gschwendtner, Pawel Kozlowski, Ryan Day and dario-piotrowicz
|
||||
4javier, Aakash, Alan Agius, Andrew Kushnir, Aristeidis Bampakos, Dany Paredes, Derek Cormier, JoostK, Kristiyan Kostadinov, Paul Gschwendtner, Ramesh Thiruchelvam, behrooz bozorg chami, dario-piotrowicz, markostanimirovic, renovate[bot] and web-dave
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="14.0.0-next.15"></a>
|
||||
# 14.0.0-next.15 (2022-04-27)
|
||||
<a name="14.0.2"></a>
|
||||
# 14.0.2 (2022-06-15)
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [ef5cba3df7](https://github.com/angular/angular/commit/ef5cba3df783691433fe918f8f3c05878784c0f8) | fix | allow null in ngComponentOutlet ([#46280](https://github.com/angular/angular/pull/46280)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [8ecfd71fd7](https://github.com/angular/angular/commit/8ecfd71fd7a44628500668fbb59fdc08de8b8140) | fix | don't emit empty providers array ([#46301](https://github.com/angular/angular/pull/46301)) |
|
||||
| [b92c1a6ada](https://github.com/angular/angular/commit/b92c1a6adada5923b1fd69e24560ae5bfd67dd5a) | fix | use inline type-check blocks for components outside `rootDir` ([#46096](https://github.com/angular/angular/pull/46096)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [3fd8948b4a](https://github.com/angular/angular/commit/3fd8948b4a04dc504be3d4dd751a5554673423bb) | fix | Resolve forwardRef declarations for jit ([#46334](https://github.com/angular/angular/pull/46334)) |
|
||||
## Special Thanks
|
||||
Alex Rickabaugh, Andrew Scott, Badawi7, Daniel Schmitz, Derek Cormier, JoostK, Kevin Davila, Kristiyan Kostadinov, Paul Draper, Paul Gschwendtner, Tom Eustace, Totati, Younes Jaaidi, alefra, dario-piotrowicz, markostanimirovic, mgechev, piyush132000, sten-bone and vivekkoya
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="14.0.1"></a>
|
||||
# 14.0.1 (2022-06-08)
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [dde0b7f4b3](https://github.com/angular/angular/commit/dde0b7f4b3bc658b67a97644c8655252803be663) | fix | allow FormBuilder.group(...) to accept optional fields. ([#46253](https://github.com/angular/angular/pull/46253)) |
|
||||
## Special Thanks
|
||||
Adrien Crivelli, Alan Agius, Alex Rickabaugh, Andrew Kushnir, Andrew Scott, Dylan Hunn, Fabrizio Fallico, George Kalpakas, Jelle Bruisten, JoostK, Kristiyan Kostadinov, Krzysztof Platis, Paul Gschwendtner, Phalgun Vaddepalli, San Leen, dario-piotrowicz, mgechev and wellWINeo
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="14.0.0"></a>
|
||||
# 14.0.0 (2022-06-02)
|
||||
|
||||
[Blog post "Angular v14 is now available"](http://goo.gle/angular-v14).
|
||||
|
||||
## Breaking Changes
|
||||
### animations
|
||||
- The `AnimationDriver.getParentElement` method has become required, so any
|
||||
implementors of this interface are now required to provide an implementation
|
||||
for this method. This breakage is unlikely to affect application developers,
|
||||
as `AnimationDriver` is not expected to be implemented in user code.
|
||||
### common
|
||||
- Adds new required class member that any implementors of the LocationStrategy will need to satisfy.
|
||||
Location does not depend on PlatformLocation anymore.
|
||||
### compiler
|
||||
- Keyframes names are now prefixed with the component's "scope name".
|
||||
For example, the following keyframes rule in a component definition,
|
||||
whose "scope name" is host-my-cmp:
|
||||
|
||||
@keyframes foo { ... }
|
||||
|
||||
will become:
|
||||
|
||||
@keyframes host-my-cmp_foo { ... }
|
||||
|
||||
Any TypeScript/JavaScript code which relied on the names of keyframes rules
|
||||
will no longer match.
|
||||
|
||||
The recommended solutions in this case are to either:
|
||||
- change the component's view encapsulation to the `None` or `ShadowDom`
|
||||
- define keyframes rules in global stylesheets (e.g styles.css)
|
||||
- define keyframes rules programmatically in code.
|
||||
|
||||
### core
|
||||
- Support for Node.js v12 has been removed as it will become EOL on 2022-04-30. Please use Node.js v14.15 or later.
|
||||
- TypeScript versions older than 4.6 are no longer supported.
|
||||
- Forms [email] input coercion
|
||||
|
||||
Forms [email] input value will be considered as true if it is defined with any value rather
|
||||
than false and 'false'.
|
||||
- Since Ivy, TestBed doesn't use AOT summaries. The `aotSummaries` fields in TestBed APIs were present, but unused. The fields were deprecated in previous major version and in v14 those fields are removed. The `aotSummaries` fields were completely unused, so you can just drop them from the TestBed APIs usage.
|
||||
### forms
|
||||
- Forms classes accept a generic.
|
||||
|
||||
Forms model classes now accept a generic type parameter. Untyped versions of these classes are available to opt-out of the new, stricter behavior.
|
||||
- objects with a length key set to zero will no longer validate as empty.
|
||||
|
||||
This is technically a breaking change, since objects with a key `length` and value `0` will no longer validate as empty. This is a very minor change, and any reliance on this behavior is probably a bug anyway.
|
||||
### http
|
||||
- Queries including + will now actually query for + instead of space.
|
||||
Most workarounds involving custom codecs will be unaffected.
|
||||
Possible server-side workarounds will need to be undone.
|
||||
- JSONP will throw an error when headers are set on a reques
|
||||
|
||||
JSONP does not support headers being set on requests. Before when
|
||||
a request was sent to a JSONP backend that had headers set the headers
|
||||
were ignored. The JSONP backend will now throw an error if it
|
||||
receives a request that has any headers set. Any uses of JSONP
|
||||
on requests with headers set will need to remove the headers
|
||||
to avoid the error.
|
||||
### platform-browser
|
||||
- This change may cause a breaking change in unit tests that are implicitly depending on a specific
|
||||
number and sequence of change detections in order for their assertions to pass.
|
||||
- This may break invalid calls to `TransferState` methods.
|
||||
|
||||
This tightens parameter types of `TransferState` usage, and is a minor breaking change which may reveal existing problematic calls.
|
||||
### router
|
||||
- The type of `Route.pathMatch` is now more strict. Places that use
|
||||
`pathMatch` will likely need to be updated to have an explicit
|
||||
`Route`/`Routes` type so that TypeScript does not infer the type as
|
||||
`string`.
|
||||
- When returning a `Promise` from the
|
||||
`LoadChildrenCallback`, the possible type is now restricted to
|
||||
`Type<any>|NgModuleFactory<any>` rather than `any`.
|
||||
- `initialNavigation: 'enabled'` was deprecated in v11 and is replaced by
|
||||
`initialNavigation: 'enabledBlocking'`.
|
||||
- The type of `component` on `ActivatedRoute` and `ActivatedRouteSnapshot`
|
||||
includes `string`. In reality, this is not the case. The component
|
||||
cannot be anything other than a component class.
|
||||
- * The type of `initialUrl` is set to `string|UrlTree` but in reality,
|
||||
the `Router` only sets it to a value that will always be `UrlTree`
|
||||
* `initialUrl` is documented as "The target URL passed into the
|
||||
`Router#navigateByUrl()` call before navigation" but the value
|
||||
actually gets set to something completely different. It's set to the
|
||||
current internal `UrlTree` of the Router at the time navigation
|
||||
occurs.
|
||||
|
||||
With this change, there is no exact replacement for the old value of
|
||||
`initialUrl` because it was never intended to be exposed.
|
||||
`Router.url` is likely the best replacement for this.
|
||||
In more specific use-cases, tracking the `finalUrl` between successful
|
||||
navigations can also be used as a replacement.
|
||||
- Lazy loaded configs are now also validated once loaded like the
|
||||
initial set of routes are. Lazy loaded modules which have invalid Route
|
||||
configs will now error. Note that this is only done in dev mode so
|
||||
there is no production impact of this change.
|
||||
- When a guard returns a `UrlTree`, the router would previously schedule
|
||||
the redirect navigation within a `setTimeout`. This timeout is now removed,
|
||||
which can result in test failures due to incorrectly written tests.
|
||||
Tests which perform navigations should ensure that all timeouts are
|
||||
flushed before making assertions. Tests should ensure they are capable
|
||||
of handling all redirects from the original navigation.
|
||||
### bazel
|
||||
- Previously, resolvers were waiting to be completed
|
||||
before proceeding with the navigation and the Router would take the last
|
||||
value emitted from the resolver.
|
||||
The router now takes only the first emitted value by the resolvers
|
||||
and then proceeds with navigation. This is now consistent with `Observables`
|
||||
returned by other guards: only the first value is used.
|
||||
### zone.js
|
||||
- in TaskTrackingZoneSpec track a periodic task until it is cancelled
|
||||
|
||||
The breaking change is scoped only to the plugin
|
||||
`zone.js/plugins/task-tracking`. If you used `TaskTrackingZoneSpec` and
|
||||
checked the pending macroTasks e.g. using `(this.ngZone as any)._inner
|
||||
._parent._properties.TaskTrackingZone.getTasksFor('macroTask')`, then
|
||||
its behavior slightly changed for periodic macrotasks. For example,
|
||||
previously the `setInterval` macrotask was no longer tracked after its
|
||||
callback was executed for the first time. Now it's tracked until
|
||||
the task is explicitly cancelled, e.g with `clearInterval(id)`.
|
||||
|
||||
## Deprecations
|
||||
### common
|
||||
- The `ngModuleFactory` input of the `NgComponentOutlet` directive is deprecated in favor of a newly added `ngModule` input. The `ngModule` input accepts references to the NgModule class directly, without the need to resolve module factory first.
|
||||
### forms
|
||||
- The `initialValueIsDefault` option has been deprecated and replaced with the otherwise-identical `nonNullable` option, for the sake of naming consistency.
|
||||
- It is now deprecated to provide *both* `AbstractControlOption`s and an async validators argument to a FormControl. Previously, the async validators would just be silently dropped, resulting in a probably buggy forms. Now, the constructor call is deprecated, and Angular will print a warning in devmode.
|
||||
### router
|
||||
- The `resolver` argument of the `RouterOutletContract.activateWith` function and the `resolver` field of the `OutletContext` class are deprecated. Passing component factory resolvers are no longer needed. The `ComponentFactoryResolver`-related symbols were deprecated in `@angular/core` package since v13.
|
||||
### animations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [68597bb0ca](https://github.com/angular/angular/commit/68597bb0ca958445655653a0a3cb206c01c7e0b3) | feat | speed up dev-turnaround by bundling types only when packaging ([#45405](https://github.com/angular/angular/pull/45405)) |
|
||||
| [970a3b5c70](https://github.com/angular/angular/commit/970a3b5c70fee29aa40945836ebeb464d75438e4) | fix | add this_is_bazel marker ([#45728](https://github.com/angular/angular/pull/45728)) |
|
||||
| [a6fa37bc6e](https://github.com/angular/angular/commit/a6fa37bc6e705fee48f555d4b8022915094e8b16) | feat | make validateStyleProperty check dev-mode only ([#45570](https://github.com/angular/angular/pull/45570)) |
|
||||
| [79d334b138](https://github.com/angular/angular/commit/79d334b1385685d0fd1451534df2ed3cbaefa0b6) | feat | provide warnings for non-animatable CSS properties ([#45212](https://github.com/angular/angular/pull/45212)) |
|
||||
| [f8dc660605](https://github.com/angular/angular/commit/f8dc66060591e1ce42265a7862c3df16e40b05e1) | fix | allow animations with unsupported CSS properties ([#44729](https://github.com/angular/angular/pull/44729)) |
|
||||
| [2a75754ee8](https://github.com/angular/angular/commit/2a75754ee823032e651bc596887a2186dc6846ae) | fix | apply default params when resolved value is null or undefined ([#45339](https://github.com/angular/angular/pull/45339)) |
|
||||
| [e46b379204](https://github.com/angular/angular/commit/e46b37920438d84bff895498c0a102dd1ffba178) | fix | implement missing transition delay ([#44799](https://github.com/angular/angular/pull/44799)) |
|
||||
| [5c7c56bc85](https://github.com/angular/angular/commit/5c7c56bc859b195bf6710f6c1479d9e18dde35b1) | perf | improve algorithm to balance animation namespaces ([#45057](https://github.com/angular/angular/pull/45057)) |
|
||||
| [4c778cdb28](https://github.com/angular/angular/commit/4c778cdb28de128c6ddecd2fd6cb6257d675500b) | perf | made errors in the animations package tree shakeable ([#45004](https://github.com/angular/angular/pull/45004)) |
|
||||
| [7a81481fb2](https://github.com/angular/angular/commit/7a81481fb29e94b550db7ad68270eccf26bb2743) | perf | Remove generic objects in favor of Maps ([#44482](https://github.com/angular/angular/pull/44482)) |
|
||||
| [6642e3c8fd](https://github.com/angular/angular/commit/6642e3c8fd7d3b5ed22710667b2c41a46f14eda8) | perf | remove no longer needed CssKeyframes classes ([#44903](https://github.com/angular/angular/pull/44903)) |
|
||||
| [59559fdbac](https://github.com/angular/angular/commit/59559fdbacc00bee380b1e88c79d08b6e856ebbe) | refactor | make `AnimationDriver.getParentElement` required ([#45114](https://github.com/angular/angular/pull/45114)) |
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [31d7c3bd71](https://github.com/angular/angular/commit/31d7c3bd71fdab3fef1b4615ecb8124fe6c165bd) | feat | add getState method to LocationStrategy interface ([#45648](https://github.com/angular/angular/pull/45648)) |
|
||||
| [c89cf63059](https://github.com/angular/angular/commit/c89cf63059370bba43717483e3d9627499dfe815) | feat | support NgModule as an input to the NgComponentOutlet ([#44815](https://github.com/angular/angular/pull/44815)) |
|
||||
| [38c03a2035](https://github.com/angular/angular/commit/38c03a20358db3f8621c023b98e627cd385731c0) | feat | support years greater than 9999 ([#43622](https://github.com/angular/angular/pull/43622)) |
|
||||
| [bedb257afc](https://github.com/angular/angular/commit/bedb257afc1ca12eb221536ea44ade960e62cda0) | fix | cleanup URL change listeners when the root view is removed ([#44901](https://github.com/angular/angular/pull/44901)) |
|
||||
| [10691c626b](https://github.com/angular/angular/commit/10691c626bf381bedfa278e9d50ab922b4b656cd) | fix | properly cast http param values to strings ([#42643](https://github.com/angular/angular/pull/42643)) |
|
||||
| [05d50b849b](https://github.com/angular/angular/commit/05d50b849bb891c37c3eefab81a45099057dfd78) | perf | make `NgLocalization` token tree-shakable ([#45118](https://github.com/angular/angular/pull/45118)) |
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [bb8d7091c6](https://github.com/angular/angular/commit/bb8d7091c64a785758ae347b1a9bcdeeed95897c) | fix | exclude empty styles from emitted metadata ([#45459](https://github.com/angular/angular/pull/45459)) |
|
||||
| [4d6a1d6722](https://github.com/angular/angular/commit/4d6a1d672210219328b33f4f96210870563066ee) | fix | scope css keyframes in emulated view encapsulation ([#42608](https://github.com/angular/angular/pull/42608)) |
|
||||
| [f03e313f24](https://github.com/angular/angular/commit/f03e313f24465cbe9ce99aa5f9f482a6c6b5485f) | fix | scope css keyframes in emulated view encapsulation ([#42608](https://github.com/angular/angular/pull/42608)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [9cf14ff03d](https://github.com/angular/angular/commit/9cf14ff03dc7a848413b323dfb943fcd26f1217e) | feat | exclude abstract classes from `strictInjectionParameters` requirement ([#44615](https://github.com/angular/angular/pull/44615)) |
|
||||
| [0072eb48ba](https://github.com/angular/angular/commit/0072eb48ba1c6f549703988b7fd7ba3e09058048) | feat | initial implementation of standalone components ([#44812](https://github.com/angular/angular/pull/44812)) |
|
||||
| [2142ffd295](https://github.com/angular/angular/commit/2142ffd295de491eb8582c2eb1712b5b48044f24) | feat | propagate `standalone` flag to runtime ([#44973](https://github.com/angular/angular/pull/44973)) |
|
||||
| [6f653e05f9](https://github.com/angular/angular/commit/6f653e05f985141ae4d2d90af78b2bc001595661) | feat | standalone types imported into NgModule scopes ([#44973](https://github.com/angular/angular/pull/44973)) |
|
||||
| [752ddbc165](https://github.com/angular/angular/commit/752ddbc165359c2ff987c24f715d0a36fd604ec0) | feat | Support template binding to protected component members ([#45823](https://github.com/angular/angular/pull/45823)) |
|
||||
| [3d13343975](https://github.com/angular/angular/commit/3d133439754cbf5d5a20bb3c714c8673c848e465) | fix | better error messages for NgModule structural issues ([#44973](https://github.com/angular/angular/pull/44973)) |
|
||||
| [046dad1a8d](https://github.com/angular/angular/commit/046dad1a8d878ea537a6e2ef5f5ef24a85a2cf02) | fix | fix issue with incremental tracking of APIs for pipes ([#45672](https://github.com/angular/angular/pull/45672)) |
|
||||
| [27b4af7240](https://github.com/angular/angular/commit/27b4af7240ea964d1e4d51b83118f10321163627) | fix | full side-effectful registration of NgModules with ids ([#45024](https://github.com/angular/angular/pull/45024)) |
|
||||
| [32c625d027](https://github.com/angular/angular/commit/32c625d0279d9fd55178ced47c45969da533eedc) | fix | handle forwardRef in imports of standalone component ([#45869](https://github.com/angular/angular/pull/45869)) |
|
||||
| [06050ac2b4](https://github.com/angular/angular/commit/06050ac2b4937836096fb331ec71bacb5a1fc231) | fix | handle inline type-check blocks in nullish coalescing extended check ([#45454](https://github.com/angular/angular/pull/45454)) |
|
||||
| [a524a50361](https://github.com/angular/angular/commit/a524a50361bb408cf8baf8ff209378a1db967545) | fix | handle standalone components with cycles ([#46029](https://github.com/angular/angular/pull/46029)) |
|
||||
| [724e88e042](https://github.com/angular/angular/commit/724e88e042b1a89691d48879673b5e1b161c3d9a) | fix | preserve `forwardRef` for component scopes ([#46139](https://github.com/angular/angular/pull/46139)) |
|
||||
| [9cfea3d522](https://github.com/angular/angular/commit/9cfea3d522c0e4a34bb3a5d0fa9d04f64de39b49) | fix | report invalid imports in standalone components during resolve phase ([#45827](https://github.com/angular/angular/pull/45827)) |
|
||||
| [c0778b4dfc](https://github.com/angular/angular/commit/c0778b4dfc1c107543b3db6f1958814a0812c7df) | fix | Support resolve animation name from the DTS ([#45107](https://github.com/angular/angular/pull/45107)) |
|
||||
| [f2e5234e07](https://github.com/angular/angular/commit/f2e5234e078b6d4771d07e8b28b8098f1faeb176) | fix | update unknown tag error for aot standalone components ([#45919](https://github.com/angular/angular/pull/45919)) |
|
||||
| [35f20afcac](https://github.com/angular/angular/commit/35f20afcac4877963e4a3e5d85b67ed8cb000af9) | fix | use existing imports for standalone dependencies ([#46029](https://github.com/angular/angular/pull/46029)) |
|
||||
| [8155428ba6](https://github.com/angular/angular/commit/8155428ba65c38c0c15f2666727202a7b360c1bd) | perf | ignore the module.id anti-pattern for NgModule ids ([#45024](https://github.com/angular/angular/pull/45024)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [174ce7dd13](https://github.com/angular/angular/commit/174ce7dd13f6d8f941d3aa0b843559614cb68b0c) | feat | add `ApplicationRef.destroy` method ([#45624](https://github.com/angular/angular/pull/45624)) |
|
||||
| [5771b18a98](https://github.com/angular/angular/commit/5771b18a989c3c75d713ffb75cd7c047c63e4090) | feat | add the `bootstrapApplication` function ([#45674](https://github.com/angular/angular/pull/45674)) |
|
||||
| [69018c9f42](https://github.com/angular/angular/commit/69018c9f42d14c1c7aa8271b406d6d247de1c564) | feat | allow for injector to be specified when creating an embedded view ([#45156](https://github.com/angular/angular/pull/45156)) |
|
||||
| [94c949a60a](https://github.com/angular/angular/commit/94c949a60ad0de1f5385ec97f2c1933cb1d55f22) | feat | allow for injector to be specified when creating an embedded view ([#45156](https://github.com/angular/angular/pull/45156)) |
|
||||
| [e702cafcf2](https://github.com/angular/angular/commit/e702cafcf2fef53968ef52ce17cb343f3a12bb53) | feat | allow to throw on unknown elements in tests ([#45479](https://github.com/angular/angular/pull/45479)) |
|
||||
| [6662a97c61](https://github.com/angular/angular/commit/6662a97c61f133a14f2d117f71e4d2b8f4a83c32) | feat | allow to throw on unknown elements in tests ([#45479](https://github.com/angular/angular/pull/45479)) |
|
||||
| [a6675925b0](https://github.com/angular/angular/commit/a6675925b0b6f313d4932a753bd4aa4cb473b5f3) | feat | allow to throw on unknown properties in tests ([#45853](https://github.com/angular/angular/pull/45853)) |
|
||||
| [6eaaefd22e](https://github.com/angular/angular/commit/6eaaefd22ebb95ee896a62237832ff2f2defdee0) | feat | drop support for Node.js 12 ([#45286](https://github.com/angular/angular/pull/45286)) |
|
||||
| [c9d566ce4b](https://github.com/angular/angular/commit/c9d566ce4b6e9097d9eceb7ac3964a0b25c404ad) | feat | drop support for TypeScript 4.4 and 4.5 ([#45394](https://github.com/angular/angular/pull/45394)) |
|
||||
| [b568a5e708](https://github.com/angular/angular/commit/b568a5e708579f5035f40c7218fbba39ad6b3065) | feat | implement `importProvidersFrom` function ([#45626](https://github.com/angular/angular/pull/45626)) |
|
||||
| [d5a6cd1111](https://github.com/angular/angular/commit/d5a6cd11110c78762a8e6115a718f5851508dbf2) | feat | implement EnvironmentInjector with adapter to NgModuleRef ([#45626](https://github.com/angular/angular/pull/45626)) |
|
||||
| [5a10fc4f82](https://github.com/angular/angular/commit/5a10fc4f8287d448c88ce2f6c97c48307af34af1) | feat | implement standalone directives, components, and pipes ([#45687](https://github.com/angular/angular/pull/45687)) |
|
||||
| [e461f716d4](https://github.com/angular/angular/commit/e461f716d4b736829d53de26ba6dddb58f476746) | feat | move ANIMATION_MODULE_TYPE injection token into core ([#44970](https://github.com/angular/angular/pull/44970)) |
|
||||
| [94bba76a4a](https://github.com/angular/angular/commit/94bba76a4a9594a5eb90e581f407f1b70697e715) | feat | support TypeScript 4.6 ([#45190](https://github.com/angular/angular/pull/45190)) |
|
||||
| [29039fcdbc](https://github.com/angular/angular/commit/29039fcdbcb8cab040d88dabe2dcb1abae34cb4e) | feat | support TypeScript 4.7 ([#45749](https://github.com/angular/angular/pull/45749)) |
|
||||
| [225e4f2dbe](https://github.com/angular/angular/commit/225e4f2dbeac5982982fb94eac65ea931c44247a) | feat | triggerEventHandler accept optional eventObj ([#45279](https://github.com/angular/angular/pull/45279)) |
|
||||
| [401dec46eb](https://github.com/angular/angular/commit/401dec46eb71e33ae3ef185b8f92ed2b3b7661fd) | feat | update TestBed to recognize Standalone Components ([#45809](https://github.com/angular/angular/pull/45809)) |
|
||||
| [35653ce337](https://github.com/angular/angular/commit/35653ce337b59336ebb06f07dfed027e5037ed06) | fix | add more details to the MISSING_INJECTION_CONTEXT error ([#46166](https://github.com/angular/angular/pull/46166)) |
|
||||
| [d36fa111eb](https://github.com/angular/angular/commit/d36fa111eb677d504a9952d8b4ca53560cadd04d) | fix | avoid Closure Compiler error in restoreView ([#45445](https://github.com/angular/angular/pull/45445)) |
|
||||
| [0bc77f4cab](https://github.com/angular/angular/commit/0bc77f4cabb3fe76accb120f7aba57ebfee9262b) | fix | better error message when unknown property is present ([#46147](https://github.com/angular/angular/pull/46147)) |
|
||||
| [f3eb7d9ecb](https://github.com/angular/angular/commit/f3eb7d9ecb9a82e7396cca658e3250e47c853153) | fix | Ensure the `StandaloneService` is retained after closure minification ([#45783](https://github.com/angular/angular/pull/45783)) |
|
||||
| [701405fa71](https://github.com/angular/angular/commit/701405fa710177ed1c963f61686ebb910e5ec74e) | fix | handle AOT-compiled standalone components in TestBed correctly ([#46052](https://github.com/angular/angular/pull/46052)) |
|
||||
| [ddce357d1d](https://github.com/angular/angular/commit/ddce357d1db9694bc69c114deb96e26d2651fb8b) | fix | improve TestBed declarations standalone error message ([#45999](https://github.com/angular/angular/pull/45999)) |
|
||||
| [ba9f30c9a6](https://github.com/angular/angular/commit/ba9f30c9a6af19b34d13962303ec96997c7c3d56) | fix | include component name into unknown element/property error message ([#46160](https://github.com/angular/angular/pull/46160)) |
|
||||
| [9fa6f5a552](https://github.com/angular/angular/commit/9fa6f5a552b7780ce32aa5a60273d4008a7b6afb) | fix | incorrectly inserting elements inside `<template>` element ([#43429](https://github.com/angular/angular/pull/43429)) |
|
||||
| [d5719c2e0f](https://github.com/angular/angular/commit/d5719c2e0fb237be71d658444bbfe2410e05086a) | fix | input coercion ([#42803](https://github.com/angular/angular/pull/42803)) |
|
||||
| [be161bef79](https://github.com/angular/angular/commit/be161bef798ac5309df8390e3c2bba2cf84cb530) | fix | memory leak in event listeners inside embedded views ([#43075](https://github.com/angular/angular/pull/43075)) |
|
||||
| [fa755b2a54](https://github.com/angular/angular/commit/fa755b2a541274336541e8870852e73718ad62d4) | fix | prevent `BrowserModule` providers from being loaded twice ([#45826](https://github.com/angular/angular/pull/45826)) |
|
||||
| [3172b4cc99](https://github.com/angular/angular/commit/3172b4cc9972a7d347b3078484c9adcb15cf270c) | fix | produce proper error message for unknown props on `<ng-template>`s ([#46068](https://github.com/angular/angular/pull/46068)) |
|
||||
| [4f1a813596](https://github.com/angular/angular/commit/4f1a813596a40f7885d369eb8917aedcce9dd795) | fix | restore NgModule state correctly after TestBed overrides ([#46049](https://github.com/angular/angular/pull/46049)) |
|
||||
| [3f7ecec59b](https://github.com/angular/angular/commit/3f7ecec59b894d2a92f4b5643d2a23891938bde8) | fix | set correct context for inject() for component ctors ([#45991](https://github.com/angular/angular/pull/45991)) |
|
||||
| [4e413d9240](https://github.com/angular/angular/commit/4e413d9240259fca1b1e548c5c405e646f8e68c8) | fix | support nested arrays of providers in `EnvironmentInjector` ([#45789](https://github.com/angular/angular/pull/45789)) |
|
||||
| [fde4942cdf](https://github.com/angular/angular/commit/fde4942cdf5133119b13ed26ee2f6976b787d84c) | fix | throw if standalone components are present in `@NgModule.bootstrap` ([#45825](https://github.com/angular/angular/pull/45825)) |
|
||||
| [560188bf12](https://github.com/angular/angular/commit/560188bf126f259328477773cabb367587a257d5) | fix | update unknown property error to account for standalone components in AOT ([#46159](https://github.com/angular/angular/pull/46159)) |
|
||||
| [df339d8abf](https://github.com/angular/angular/commit/df339d8abf979c715c35db813c5a80252a92eba7) | fix | update unknown tag error for jit standalone components ([#45920](https://github.com/angular/angular/pull/45920)) |
|
||||
| [aafac7228f](https://github.com/angular/angular/commit/aafac7228f3d18bb720e85d2b889df446122f4c7) | fix | verify standalone component imports in JiT ([#45777](https://github.com/angular/angular/pull/45777)) |
|
||||
| [e9317aee71](https://github.com/angular/angular/commit/e9317aee71f64f4aadea0529601e589b37f6b46f) | perf | allow `checkNoChanges` mode to be tree-shaken in production ([#45913](https://github.com/angular/angular/pull/45913)) |
|
||||
| [071c8af8ba](https://github.com/angular/angular/commit/071c8af8ba89163270f17657c0c7f1c944f186f7) | perf | avoid storing LView in `__ngContext__` ([#45051](https://github.com/angular/angular/pull/45051)) |
|
||||
| [a96c4827c4](https://github.com/angular/angular/commit/a96c4827c4f62e1d665d8544a3e66c51d2644c88) | perf | make `Compiler`, `ApplicationRef` and `ApplicationInitStatus` tree-shakable ([#45102](https://github.com/angular/angular/pull/45102)) |
|
||||
| [45d98e7ca5](https://github.com/angular/angular/commit/45d98e7ca5accf918e2602cbc17805e11e18896b) | perf | make `IterableDiffers` and `KeyValueDiffers` tree-shakable ([#45094](https://github.com/angular/angular/pull/45094)) |
|
||||
| [1e60fe0a3e](https://github.com/angular/angular/commit/1e60fe0a3eeb6bd46997f7eeb4825351cfbe3c44) | perf | make `LOCALE_ID` and other tokens from `ApplicationModule` tree-shakable ([#45102](https://github.com/angular/angular/pull/45102)) |
|
||||
| [88f1168506](https://github.com/angular/angular/commit/88f1168506befd0665125da1fca2a719cb27dbb5) | perf | only track LViews that are referenced in `__ngContext__` ([#45172](https://github.com/angular/angular/pull/45172)) |
|
||||
| [9add714b13](https://github.com/angular/angular/commit/9add714b13740db621eb2b200d72be74cc7eb630) | refactor | remove deprecated `aotSummaries` fields in TestBed config ([#45487](https://github.com/angular/angular/pull/45487)) |
|
||||
### devtools tabs
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [6c284ef32e](https://github.com/angular/angular/commit/6c284ef32e53a8dabbc368b9cf69f1b6f1a377b7) | fix | stop scroll occuring at tabs level |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [2dbdebc646](https://github.com/angular/angular/commit/2dbdebc6467074c7005c09ef5c229029f8d3607c) | feat | Add `FormBuilder.nonNullable`. ([#45852](https://github.com/angular/angular/pull/45852)) |
|
||||
| [e0a2248b32](https://github.com/angular/angular/commit/e0a2248b3233b5d384f33859ef6207613cad909d) | feat | Add a FormRecord type. ([#45607](https://github.com/angular/angular/pull/45607)) |
|
||||
| [7ee121f595](https://github.com/angular/angular/commit/7ee121f595a47338b31098ae51a6f91d80c8fdce) | feat | Add untyped versions of the model classes for use in migration. ([#45205](https://github.com/angular/angular/pull/45205)) |
|
||||
| [89d299105a](https://github.com/angular/angular/commit/89d299105a4ae11985fb809f42cd0e34511207c9) | feat | Implement strict types for the Angular Forms package. ([#43834](https://github.com/angular/angular/pull/43834)) |
|
||||
| [f490c2de4e](https://github.com/angular/angular/commit/f490c2de4e1ada26e62e35c0d70cb90e55297658) | feat | support negative indices in FormArray methods. ([#44848](https://github.com/angular/angular/pull/44848)) |
|
||||
| [39be06037d](https://github.com/angular/angular/commit/39be06037daf65ae9298b5bdb4cd50785c16332f) | fix | Add a `nonNullable` option to `FormControl` for consistency. |
|
||||
| [4332897baa](https://github.com/angular/angular/commit/4332897baa2226ef246ee054fdd5254e3c129109) | fix | Add UntypedFormBuilder ([#45268](https://github.com/angular/angular/pull/45268)) |
|
||||
| [5d13e58aed](https://github.com/angular/angular/commit/5d13e58aed8b7641f0b2d4f0c9015cb90ff4edb5) | fix | Allow NonNullableFormBuilder to be injected. ([#45904](https://github.com/angular/angular/pull/45904)) |
|
||||
| [8dd3f82f94](https://github.com/angular/angular/commit/8dd3f82f946bae86dc6c678d8694ab73d915bbfa) | fix | Correct empty validator to handle objects with a property `length: 0`. ([#33729](https://github.com/angular/angular/pull/33729)) |
|
||||
| [ff3f5a8d12](https://github.com/angular/angular/commit/ff3f5a8d12e3243620e311b690a050e26493e539) | fix | Fix a typing bug in FormBuilder. ([#45684](https://github.com/angular/angular/pull/45684)) |
|
||||
| [fe0e42a996](https://github.com/angular/angular/commit/fe0e42a996d5b70f4c0923cb6570c9a8032b1298) | fix | Make UntypedFormBuilder assignable to FormBuilder, and vice versa. ([#45421](https://github.com/angular/angular/pull/45421)) |
|
||||
| [b36dec6b5b](https://github.com/angular/angular/commit/b36dec6b5b05de0d40581726c59db9f962a97124) | fix | not picking up disabled state if group is swapped out and disabled ([#43499](https://github.com/angular/angular/pull/43499)) |
|
||||
| [9f6fa5b746](https://github.com/angular/angular/commit/9f6fa5b746cbdd4a71f67728ff6b663ad26c6a29) | fix | Prevent FormBuilder from distributing unions to control types. ([#45942](https://github.com/angular/angular/pull/45942)) |
|
||||
| [aa7b857be8](https://github.com/angular/angular/commit/aa7b857be89a62e6dcfe62c418acf0823525d265) | fix | Property renaming safe code ([#45271](https://github.com/angular/angular/pull/45271)) |
|
||||
| [cae1e44608](https://github.com/angular/angular/commit/cae1e44608227ac80682401190c6d28ef39b3269) | fix | Update the typed forms migration to use `FormArray<T>` instead of `FormArray<T[]>`. ([#44933](https://github.com/angular/angular/pull/44933)) |
|
||||
| [d336ba96d9](https://github.com/angular/angular/commit/d336ba96d922363235688f54d8af108ef7ab01f0) | fix | Update the typed forms migration. ([#45281](https://github.com/angular/angular/pull/45281)) |
|
||||
| [018550ed50](https://github.com/angular/angular/commit/018550ed5025de9737794b683eb7c0697d83d430) | fix | Value and RawValue should be part of the public API. ([#45978](https://github.com/angular/angular/pull/45978)) |
|
||||
| [2e96cede3e](https://github.com/angular/angular/commit/2e96cede3e2d9ac399c10d3bfe25259b92a5276e) | fix | Warn on FormControls that are constructed with both options and asyncValidators. |
|
||||
### http
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [76a9a24cdc](https://github.com/angular/angular/commit/76a9a24cdcb87e36868e2e29d1831af2dec3a818) | fix | encode + signs in query params as %2B (angular[#11058](https://github.com/angular/angular/pull/11058)) ([#45111](https://github.com/angular/angular/pull/45111)) |
|
||||
| [d43c0e973f](https://github.com/angular/angular/commit/d43c0e973f4389c74eb19a7f6b667bd2e1d380fe) | fix | Throw error when headers are supplied in JSONP request ([#45210](https://github.com/angular/angular/pull/45210)) |
|
||||
### language-service
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [9d4af65e34](https://github.com/angular/angular/commit/9d4af65e343e41b48cb9afd12c2b61d8ca61a9ac) | feat | Provide plugin to delegate rename requests to Angular ([#44696](https://github.com/angular/angular/pull/44696)) |
|
||||
| [3ae133c69e](https://github.com/angular/angular/commit/3ae133c69e1c78d5ddf772cacf222f909faccd70) | fix | Fix detection of Angular for v14+ projects ([#45998](https://github.com/angular/angular/pull/45998)) |
|
||||
### localize
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [a50e2da64a](https://github.com/angular/angular/commit/a50e2da64a4297d1bc994a267203c2097da2efaf) | fix | ensure transitively loaded compiler code is tree-shakable ([#45405](https://github.com/angular/angular/pull/45405)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [d56a537196](https://github.com/angular/angular/commit/d56a537196d2ab0f3f48821889020d2f5bc621ba) | feat | Add migration to add explicit `Route`/`Routes` type ([#45084](https://github.com/angular/angular/pull/45084)) |
|
||||
### ngcc
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [74a2e2e2ec](https://github.com/angular/angular/commit/74a2e2e2ecb81a31c7fbec42d7770937b09e33a4) | fix | cope with packages following APF v14+ ([#45833](https://github.com/angular/angular/pull/45833)) |
|
||||
### platform-browser
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [a01bcb8e7e](https://github.com/angular/angular/commit/a01bcb8e7eaf63ac9466a78dd4d15228241da900) | fix | do not run change detection when loading Hammer ([#44921](https://github.com/angular/angular/pull/44921)) |
|
||||
| [b32647dc68](https://github.com/angular/angular/commit/b32647dc68b055da0c49c86d6e7e2a7d2ec5954a) | fix | Make transfer state key typesafe. ([#23020](https://github.com/angular/angular/pull/23020)) |
|
||||
| [c7bf75dd5e](https://github.com/angular/angular/commit/c7bf75dd5e7f3f80a3c2afb8586ae46f7258f349) | fix | remove obsolete shim for Map comparison in Jasmine ([#45521](https://github.com/angular/angular/pull/45521)) |
|
||||
| [23c4c9601e](https://github.com/angular/angular/commit/23c4c9601e1bdd8bd2e37d9e0468440a44971b95) | perf | avoid including Testability by default in `bootstrapApplication` ([#45885](https://github.com/angular/angular/pull/45885)) |
|
||||
### platform-server
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [dff5586d52](https://github.com/angular/angular/commit/dff5586d5243f914b9054b5ab7ac71d57edfa973) | feat | implement `renderApplication` function ([#45785](https://github.com/angular/angular/pull/45785)) |
|
||||
| [22c71be94c](https://github.com/angular/angular/commit/22c71be94c3a695ca0cd0316065d807abb46355f) | fix | update `renderApplication` to move `appId` to options ([#45844](https://github.com/angular/angular/pull/45844)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f4fd1a8262](https://github.com/angular/angular/commit/f4fd1a82620b5b3899c5e8c89fa06b084ee5792e) | feat | Add `EnvironmentInjector` to `RouterOutlet.activateWith` ([#45597](https://github.com/angular/angular/pull/45597)) |
|
||||
| [910de8bc33](https://github.com/angular/angular/commit/910de8bc3379b1452c0bc23a866b5108d6d94e55) | feat | Add `Route.title` with a configurable `TitleStrategy` ([#43307](https://github.com/angular/angular/pull/43307)) |
|
||||
| [4e0957a4e1](https://github.com/angular/angular/commit/4e0957a4e10d1ae188faa843043a2314c9873c52) | feat | Add ability to specify providers on a Route ([#45673](https://github.com/angular/angular/pull/45673)) |
|
||||
| [dea8c86cd5](https://github.com/angular/angular/commit/dea8c86cd57f8e1720634928805f9ea0ba8f0baa) | feat | add ariaCurrentWhenActive input to RouterLinkActive directive ([#45167](https://github.com/angular/angular/pull/45167)) |
|
||||
| [41e2a68e30](https://github.com/angular/angular/commit/41e2a68e30c12e5ad3e26047c3a4032e9aa1a6e1) | feat | add type properties to all router events ([#44189](https://github.com/angular/angular/pull/44189)) |
|
||||
| [4962a4a332](https://github.com/angular/angular/commit/4962a4a3324d5972f364d768b38b21a33fdb7d7c) | feat | Allow `loadChildren` to return a `Route` array ([#45700](https://github.com/angular/angular/pull/45700)) |
|
||||
| [791bd31424](https://github.com/angular/angular/commit/791bd3142432ed7caf14a68a6e434b27004e634b) | feat | set stricter type for Route.title ([#44939](https://github.com/angular/angular/pull/44939)) |
|
||||
| [50004c143b](https://github.com/angular/angular/commit/50004c143ba9b1e041c7b30caf98f6582d3d26d4) | feat | Support lazy loading standalone components with `loadComponent` ([#45705](https://github.com/angular/angular/pull/45705)) |
|
||||
| [7fd416d060](https://github.com/angular/angular/commit/7fd416d060bd873bc88dffed41946c51aa649ec1) | fix | Fix type of Route.pathMatch to be more accurate ([#45176](https://github.com/angular/angular/pull/45176)) |
|
||||
| [1c11a57155](https://github.com/angular/angular/commit/1c11a5715576632a4fb7170202395cf95dfbce09) | fix | merge interited resolved data and static data ([#45276](https://github.com/angular/angular/pull/45276)) |
|
||||
| [f8f3ab377b](https://github.com/angular/angular/commit/f8f3ab377b8842c2bae0f215a0e90aaa3a1e070a) | fix | Remove `any` from `LoadChildrenCallback` type ([#45524](https://github.com/angular/angular/pull/45524)) |
|
||||
| [d4fc12fa19](https://github.com/angular/angular/commit/d4fc12fa19dbe5e89189bb52c37e5d37a00a663c) | fix | Remove deprecated initialNavigation option ([#45729](https://github.com/angular/angular/pull/45729)) |
|
||||
| [989e840cce](https://github.com/angular/angular/commit/989e840cce7ebe94311ae898786e09b1b41ce7f6) | fix | Remove unused string type for ActivatedRoute.component ([#45625](https://github.com/angular/angular/pull/45625)) |
|
||||
| [64f837d2c0](https://github.com/angular/angular/commit/64f837d2c0fbcf722d32b35a87e87220bfe61f65) | fix | Update `Navigation#initialUrl` to match documentation and reality ([#43863](https://github.com/angular/angular/pull/43863)) |
|
||||
| [96fd29c6d2](https://github.com/angular/angular/commit/96fd29c6d2d2abc5afee4d21a3e964a79aa39844) | fix | validate lazy loaded configs ([#45526](https://github.com/angular/angular/pull/45526)) |
|
||||
| [f13295f3a3](https://github.com/angular/angular/commit/f13295f3a3a1d622d15cf8339360d53feba824b5) | perf | cancel the navigation instantly if at least one resolver doesn't emit any value ([#45621](https://github.com/angular/angular/pull/45621)) |
|
||||
| [1d2f5c1101](https://github.com/angular/angular/commit/1d2f5c1101ccd182f5b528de52583a1b98dd6789) | refactor | deprecate no longer needed resolver fields ([#45597](https://github.com/angular/angular/pull/45597)) |
|
||||
| [7b367d9d90](https://github.com/angular/angular/commit/7b367d9d908e15222645a45e2ba133b9d9da76b7) | refactor | Remove unnecessary setTimeout in UrlTree redirects ([#45735](https://github.com/angular/angular/pull/45735)) |
|
||||
| [c9679760b2](https://github.com/angular/angular/commit/c9679760b2bf5c607c957c20482b9cea7a21702b) | refactor | take only the first emitted value of every resolver to make it consistent with guards ([#44573](https://github.com/angular/angular/pull/44573)) |
|
||||
### service-worker
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [ec0a0e0669](https://github.com/angular/angular/commit/ec0a0e0669ef5d2f524fbf9a540eb2b306b2e24a) | feat | add `cacheOpaqueResponses` option for data-groups ([#44723](https://github.com/angular/angular/pull/44723)) |
|
||||
| [bd04fbc05b](https://github.com/angular/angular/commit/bd04fbc05b0397de966a493a863e1054203c86d9) | feat | emit a notification when the service worker is already up to date after check ([#45216](https://github.com/angular/angular/pull/45216)) |
|
||||
## Special Thanks
|
||||
Alex Rickabaugh, Andrew Kushnir, Andrew Scott, George Kalpakas, Joey Perrott, Michal Materowski, Paul Gschwendtner, Pawel Kozlowski, Sumit Arora and dario-piotrowicz
|
||||
Adrian Kunz, Alan Agius, AleksanderBodurri, Alex Rickabaugh, AlirezaEbrahimkhani, Amir Rustamzadeh, Andrew Kushnir, Andrew Scott, Chabbey François, Charles Lyding, Cédric Exbrayat, Daan De Smedt, David Schmidt, Derek Cormier, Dmitrij Kuba, Doug Parker, Dylan Hunn, Emma Twersky, George Kalpakas, George Looshch, Jan Kuehle, Jessica Janiuk, JiaLiPassion, JimMorrison723, Joe Martin (Crowdstaffing), Joey Perrott, JoostK, Kristiyan Kostadinov, Krzysztof Platis, Leosvel Pérez Espinosa, Maddie Klein, Mark Whitfeld, Martin Sikora, Michael-Doner, Michal Materowski, Minko Gechev, Paul Gschwendtner, Pawel Kozlowski, Payam Shahidi, Pusztai Tibor, Ricardo Mattiazzi Baumgartner, Roy Dorombozi, Ruslan Lekhman, Samuel Littley, Sergej Grilborzer, Sumit Arora, Tobias Speicher, Virginia Dooley, Zack Elliott, alirezaghey, ananyahs96, arturovt, cexbrayat, dario-piotrowicz, ivanwonder, kamikopi, markostanimirovic, markwhitfeld, mgechev, renovate[bot], twerske and zverbeta
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="13.3.10"></a>
|
||||
# 13.3.10 (2022-05-25)
|
||||
## Special Thanks
|
||||
A. J. Javier, Aristeidis Bampakos, J Rob Gant, Jerome Kruse, Joey Perrott, Nathan Nontell, Paul Gschwendtner, Roopesh Chinnakampalli, Thomas Mair, Tom Raithel, dario-piotrowicz and mgechev
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="13.3.6"></a>
|
||||
# 13.3.6 (2022-05-04)
|
||||
## Special Thanks
|
||||
Andrew Kushnir, Andrew Scott, George Kalpakas, Paul Gschwendtner, Pawel Kozlowski, Ryan Day and dario-piotrowicz
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
@@ -59,68 +387,6 @@ Andrew Kushnir, George Kalpakas, Joey Perrott and dario-piotrowicz
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="14.0.0-next.14"></a>
|
||||
# 14.0.0-next.14 (2022-04-20)
|
||||
## Breaking Changes
|
||||
### http
|
||||
- Queries including + will now actually query for + instead of space.
|
||||
Most workarounds involving custom codecs will be unaffected.
|
||||
Possible server-side workarounds will need to be undone.
|
||||
### router
|
||||
- The type of `component` on `ActivatedRoute` and `ActivatedRouteSnapshot`
|
||||
includes `string`. In reality, this is not the case. The component
|
||||
cannot be anything other than a component class.
|
||||
|
||||
- Lazy loaded configs are now also validated once loaded like the
|
||||
initial set of routes are. Lazy loaded modules which have invalid Route
|
||||
configs will now error. Note that this is only done in dev mode so
|
||||
there is no production impact of this change.
|
||||
## Deprecations
|
||||
### router
|
||||
- The `resolver` argument of the `RouterOutletContract.activateWith` function and the `resolver` field of the `OutletContext` class are deprecated. Passing component factory resolvers are no longer needed. The `ComponentFactoryResolver`-related symbols were deprecated in `@angular/core` package since v13.
|
||||
### bazel
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f8a1ea0c11](https://github.com/angular/angular/commit/f8a1ea0c117aa97f45b7696d2b0c9b5679e09b9f) | fix | do not error if files part of `srcs` are outside of package ([#45622](https://github.com/angular/angular/pull/45622)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [046dad1a8d](https://github.com/angular/angular/commit/046dad1a8d878ea537a6e2ef5f5ef24a85a2cf02) | fix | fix issue with incremental tracking of APIs for pipes ([#45672](https://github.com/angular/angular/pull/45672)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [174ce7dd13](https://github.com/angular/angular/commit/174ce7dd13f6d8f941d3aa0b843559614cb68b0c) | feat | add `ApplicationRef.destroy` method ([#45624](https://github.com/angular/angular/pull/45624)) |
|
||||
| [b568a5e708](https://github.com/angular/angular/commit/b568a5e708579f5035f40c7218fbba39ad6b3065) | feat | implement `importProvidersFrom` function ([#45626](https://github.com/angular/angular/pull/45626)) |
|
||||
| [d5a6cd1111](https://github.com/angular/angular/commit/d5a6cd11110c78762a8e6115a718f5851508dbf2) | feat | implement EnvironmentInjector with adapter to NgModuleRef ([#45626](https://github.com/angular/angular/pull/45626)) |
|
||||
| [57f8ab2ed8](https://github.com/angular/angular/commit/57f8ab2ed81f9fa12ff84fabcd9771ab877809c5) | fix | better error message when directive extends a component ([#45658](https://github.com/angular/angular/pull/45658)) |
|
||||
| [c6e0e3f6d3](https://github.com/angular/angular/commit/c6e0e3f6d31a66dc3034da4dfddbffed4bec37d2) | fix | improve multiple components match error ([#45645](https://github.com/angular/angular/pull/45645)) |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [e0a2248b32](https://github.com/angular/angular/commit/e0a2248b3233b5d384f33859ef6207613cad909d) | feat | Add a FormRecord type. ([#45607](https://github.com/angular/angular/pull/45607)) |
|
||||
| [ff3f5a8d12](https://github.com/angular/angular/commit/ff3f5a8d12e3243620e311b690a050e26493e539) | fix | Fix a typing bug in FormBuilder. ([#45684](https://github.com/angular/angular/pull/45684)) |
|
||||
### http
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [76a9a24cdc](https://github.com/angular/angular/commit/76a9a24cdcb87e36868e2e29d1831af2dec3a818) | fix | encode + signs in query params as %2B (angular[#11058](https://github.com/angular/angular/pull/11058)) ([#45111](https://github.com/angular/angular/pull/45111)) |
|
||||
### language-service
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f57e46c538](https://github.com/angular/angular/commit/f57e46c53881c46e712a64e23bffb1893dfe54fc) | fix | two-way binding completion should not remove the trailing quote ([#45582](https://github.com/angular/angular/pull/45582)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f4fd1a8262](https://github.com/angular/angular/commit/f4fd1a82620b5b3899c5e8c89fa06b084ee5792e) | feat | Add `EnvironmentInjector` to `RouterOutlet.activateWith` ([#45597](https://github.com/angular/angular/pull/45597)) |
|
||||
| [4e0957a4e1](https://github.com/angular/angular/commit/4e0957a4e10d1ae188faa843043a2314c9873c52) | feat | Add ability to specify providers on a Route ([#45673](https://github.com/angular/angular/pull/45673)) |
|
||||
| [989e840cce](https://github.com/angular/angular/commit/989e840cce7ebe94311ae898786e09b1b41ce7f6) | fix | Remove unused string type for ActivatedRoute.component ([#45625](https://github.com/angular/angular/pull/45625)) |
|
||||
| [96fd29c6d2](https://github.com/angular/angular/commit/96fd29c6d2d2abc5afee4d21a3e964a79aa39844) | fix | validate lazy loaded configs ([#45526](https://github.com/angular/angular/pull/45526)) |
|
||||
| [f13295f3a3](https://github.com/angular/angular/commit/f13295f3a3a1d622d15cf8339360d53feba824b5) | perf | cancel the navigation instantly if at least one resolver doesn't emit any value ([#45621](https://github.com/angular/angular/pull/45621)) |
|
||||
| [1d2f5c1101](https://github.com/angular/angular/commit/1d2f5c1101ccd182f5b528de52583a1b98dd6789) | refactor | deprecate no longer needed resolver fields ([#45597](https://github.com/angular/angular/pull/45597)) |
|
||||
## Special Thanks
|
||||
Adrian Kunz, Alex Rickabaugh, Andrew Kushnir, Andrew Scott, Dmitrij Kuba, Doug Parker, Dylan Hunn, George Kalpakas, Ilya Marchik, Jeremy Elbourn, Kristiyan Kostadinov, Louis Gombert, Mangalraj, Marko Kaznovac, Paul Gschwendtner, Saurabh Kamble, dario-piotrowicz and ivanwonder
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="13.3.4"></a>
|
||||
# 13.3.4 (2022-04-20)
|
||||
### core
|
||||
@@ -137,24 +403,6 @@ Andrew Kushnir, Andrew Scott, George Kalpakas, Ilya Marchik, Jeremy Elbourn, Kri
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="14.0.0-next.13"></a>
|
||||
# 14.0.0-next.13 (2022-04-13)
|
||||
## Breaking Changes
|
||||
### core
|
||||
- Since Ivy, TestBed doesn't use AOT summaries. The `aotSummaries` fields in TestBed APIs were present, but unused. The fields were deprecated in previous major version and in v14 those fields are removed. The `aotSummaries` fields were completely unused, so you can just drop them from the TestBed APIs usage.
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [598b759d33](https://github.com/angular/angular/commit/598b759d33221cc2bbfad4895ca0d2499a0547f8) | fix | avoid errors with extremely long instruction chains ([#45574](https://github.com/angular/angular/pull/45574)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [9add714b13](https://github.com/angular/angular/commit/9add714b13740db621eb2b200d72be74cc7eb630) | refactor | remove deprecated `aotSummaries` fields in TestBed config ([#45487](https://github.com/angular/angular/pull/45487)) |
|
||||
## Special Thanks
|
||||
4javier, Andrew Kushnir, Andrew Scott, Dylan Hunn, Jason Hendee, Jessica Janiuk, Kristiyan Kostadinov, Michael-Doner, Michal Materowski and Virginia Dooley
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="13.3.3"></a>
|
||||
# 13.3.3 (2022-04-13)
|
||||
### compiler
|
||||
@@ -166,63 +414,6 @@ Andrew Kushnir, Andrew Scott, George Kalpakas, Ilya Marchik, Jeremy Elbourn, Kri
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="14.0.0-next.12"></a>
|
||||
# 14.0.0-next.12 (2022-04-12)
|
||||
## Breaking Changes
|
||||
### forms
|
||||
- Forms classes accept a generic.
|
||||
|
||||
Forms model classes now accept a generic type parameter. Untyped versions of these classes are available to opt-out of the new, stricter behavior.
|
||||
### router
|
||||
- When returning a `Promise` from the
|
||||
`LoadChildrenCallback`, the possible type is now restricted to
|
||||
`Type<any>|NgModuleFactory<any>` rather than `any`.
|
||||
### animations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [a6fa37bc6e](https://github.com/angular/angular/commit/a6fa37bc6e705fee48f555d4b8022915094e8b16) | feat | make validateStyleProperty check dev-mode only ([#45570](https://github.com/angular/angular/pull/45570)) |
|
||||
### bazel
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [636909fba7](https://github.com/angular/angular/commit/636909fba73e25b75489c6e050bda1b880e62885) | feat | allow for generated `package.json` files in `ng_package` ([#45470](https://github.com/angular/angular/pull/45470)) |
|
||||
| [28e835b4bb](https://github.com/angular/angular/commit/28e835b4bbd9271cbc7abe2a0e42ff273b1e7e84) | feat | report error when dependency does not provide JS sources in `ng_package` ([#45470](https://github.com/angular/angular/pull/45470)) |
|
||||
| [4b2e98d55d](https://github.com/angular/angular/commit/4b2e98d55dde4f6040a021a6ebd35d29fb5f8fdf) | fix | remove unnecessary file extractions from `ng_package` ([#45470](https://github.com/angular/angular/pull/45470)) |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [89d299105a](https://github.com/angular/angular/commit/89d299105a4ae11985fb809f42cd0e34511207c9) | feat | Implement strict types for the Angular Forms package. ([#43834](https://github.com/angular/angular/pull/43834)) |
|
||||
### platform-browser
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [c7bf75dd5e](https://github.com/angular/angular/commit/c7bf75dd5e7f3f80a3c2afb8586ae46f7258f349) | fix | remove obsolete shim for Map comparison in Jasmine ([#45521](https://github.com/angular/angular/pull/45521)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f8f3ab377b](https://github.com/angular/angular/commit/f8f3ab377b8842c2bae0f215a0e90aaa3a1e070a) | fix | Remove `any` from `LoadChildrenCallback` type ([#45524](https://github.com/angular/angular/pull/45524)) |
|
||||
## Special Thanks
|
||||
Andrew Scott, Cédric Exbrayat, Dylan Hunn, George Kalpakas, Hossein Mousavi, Jessica Janiuk, Joe Martin (Crowdstaffing), Joey Perrott, Kristiyan Kostadinov, Leosvel Pérez Espinosa, Michael-Doner, Michal Materowski, Paul Gschwendtner, Samuel Littley, Sumit Arora and dario-piotrowicz
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="14.0.0-next.11"></a>
|
||||
# 14.0.0-next.11 (2022-04-06)
|
||||
### animations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [29d3891782](https://github.com/angular/angular/commit/29d38917825b9334a049799cdac60f0d39baf65a) | fix | handle structured AnimateTimings ([#31107](https://github.com/angular/angular/pull/31107)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [d56a537196](https://github.com/angular/angular/commit/d56a537196d2ab0f3f48821889020d2f5bc621ba) | feat | Add migration to add explicit `Route`/`Routes` type ([#45084](https://github.com/angular/angular/pull/45084)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [1c11a57155](https://github.com/angular/angular/commit/1c11a5715576632a4fb7170202395cf95dfbce09) | fix | merge interited resolved data and static data ([#45276](https://github.com/angular/angular/pull/45276)) |
|
||||
## Special Thanks
|
||||
Alan Agius, Andrew Kushnir, Andrew Scott, Chabbey François, Christoph Guttandin, Cédric Exbrayat, Dylan Hunn, George Kalpakas, Martin Sikora, mgechev and piyush132000
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="13.3.2"></a>
|
||||
# 13.3.2 (2022-04-06)
|
||||
### animations
|
||||
@@ -253,114 +444,6 @@ AlirezaEbrahimkhani, Andrew Kushnir, Andrew Scott, Ben Brook, Dylan Hunn, George
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="14.0.0-next.10"></a>
|
||||
# 14.0.0-next.10 (2022-03-30)
|
||||
## Breaking Changes
|
||||
### http
|
||||
- JSONP will throw an error when headers are set on a request
|
||||
|
||||
JSONP does not support headers being set on requests. Before when
|
||||
a request was sent to a JSONP backend that had headers set the headers
|
||||
were ignored. The JSONP backend will now throw an error if it
|
||||
receives a request that has any headers set. Any uses of JSONP
|
||||
on requests with headers set will need to remove the headers
|
||||
to avoid the error.
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [2142ffd295](https://github.com/angular/angular/commit/2142ffd295de491eb8582c2eb1712b5b48044f24) | feat | propagate `standalone` flag to runtime ([#44973](https://github.com/angular/angular/pull/44973)) |
|
||||
| [6f653e05f9](https://github.com/angular/angular/commit/6f653e05f985141ae4d2d90af78b2bc001595661) | feat | standalone types imported into NgModule scopes ([#44973](https://github.com/angular/angular/pull/44973)) |
|
||||
| [3d13343975](https://github.com/angular/angular/commit/3d133439754cbf5d5a20bb3c714c8673c848e465) | fix | better error messages for NgModule structural issues ([#44973](https://github.com/angular/angular/pull/44973)) |
|
||||
| [06050ac2b4](https://github.com/angular/angular/commit/06050ac2b4937836096fb331ec71bacb5a1fc231) | fix | handle inline type-check blocks in nullish coalescing extended check ([#45454](https://github.com/angular/angular/pull/45454)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [d36fa111eb](https://github.com/angular/angular/commit/d36fa111eb677d504a9952d8b4ca53560cadd04d) | fix | avoid Closure Compiler error in restoreView ([#45445](https://github.com/angular/angular/pull/45445)) |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [b36dec6b5b](https://github.com/angular/angular/commit/b36dec6b5b05de0d40581726c59db9f962a97124) | fix | not picking up disabled state if group is swapped out and disabled ([#43499](https://github.com/angular/angular/pull/43499)) |
|
||||
### http
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [d43c0e973f](https://github.com/angular/angular/commit/d43c0e973f4389c74eb19a7f6b667bd2e1d380fe) | fix | Throw error when headers are supplied in JSONP request ([#45210](https://github.com/angular/angular/pull/45210)) |
|
||||
## Special Thanks
|
||||
Alex Rickabaugh, AlirezaEbrahimkhani, Andrew Kushnir, Andrew Scott, Dylan Hunn, JiaLiPassion, JoostK, Kristiyan Kostadinov, Maddie Klein, Michael-Doner, Paul Gschwendtner, Willian Corrêa, arturovt, dario-piotrowicz and zverbeta
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="14.0.0-next.9"></a>
|
||||
# 14.0.0-next.9 (2022-03-25)
|
||||
## Special Thanks
|
||||
Paul Gschwendtner
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="14.0.0-next.8"></a>
|
||||
# 14.0.0-next.8 (2022-03-25)
|
||||
## Breaking Changes
|
||||
### core
|
||||
- TypeScript versions older than 4.6 are no longer supported.
|
||||
### zone.js
|
||||
- in TaskTrackingZoneSpec track a periodic task until it is cancelled
|
||||
|
||||
The breaking change is scoped only to the plugin
|
||||
`zone.js/plugins/task-tracking`. If you used `TaskTrackingZoneSpec` and
|
||||
checked the pending macroTasks e.g. using `(this.ngZone as any)._inner
|
||||
._parent._properties.TaskTrackingZone.getTasksFor('macroTask')`, then
|
||||
its behavior slightly changed for periodic macrotasks. For example,
|
||||
previously the `setInterval` macrotask was no longer tracked after its
|
||||
callback was executed for the first time. Now it's tracked until
|
||||
the task is explicitly cancelled, e.g with `clearInterval(id)`.
|
||||
|
||||
fixes 45350
|
||||
### animations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [79d334b138](https://github.com/angular/angular/commit/79d334b1385685d0fd1451534df2ed3cbaefa0b6) | feat | provide warnings for non-animatable CSS properties ([#45212](https://github.com/angular/angular/pull/45212)) |
|
||||
| [2a75754ee8](https://github.com/angular/angular/commit/2a75754ee823032e651bc596887a2186dc6846ae) | fix | apply default params when resolved value is null or undefined ([#45339](https://github.com/angular/angular/pull/45339)) |
|
||||
### bazel
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [dc72f3007a](https://github.com/angular/angular/commit/dc72f3007ac74389ec02ea021a27f35770aa5a5d) | fix | ng module compilation workers are subject to linker race-conditions ([#45393](https://github.com/angular/angular/pull/45393)) |
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [fffa023803](https://github.com/angular/angular/commit/fffa023803e5b04a58f0bd0b8667ee8b686aa530) | fix | scope css rules within `@layer` blocks ([#45396](https://github.com/angular/angular/pull/45396)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [27b4af7240](https://github.com/angular/angular/commit/27b4af7240ea964d1e4d51b83118f10321163627) | fix | full side-effectful registration of NgModules with ids ([#45024](https://github.com/angular/angular/pull/45024)) |
|
||||
| [8155428ba6](https://github.com/angular/angular/commit/8155428ba65c38c0c15f2666727202a7b360c1bd) | perf | ignore the module.id anti-pattern for NgModule ids ([#45024](https://github.com/angular/angular/pull/45024)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [c9d566ce4b](https://github.com/angular/angular/commit/c9d566ce4b6e9097d9eceb7ac3964a0b25c404ad) | feat | drop support for TypeScript 4.4 and 4.5 ([#45394](https://github.com/angular/angular/pull/45394)) |
|
||||
| [be161bef79](https://github.com/angular/angular/commit/be161bef798ac5309df8390e3c2bba2cf84cb530) | fix | memory leak in event listeners inside embedded views ([#43075](https://github.com/angular/angular/pull/43075)) |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [fe0e42a996](https://github.com/angular/angular/commit/fe0e42a996d5b70f4c0923cb6570c9a8032b1298) | fix | Make UntypedFormBuilder assignable to FormBuilder, and vice versa. ([#45421](https://github.com/angular/angular/pull/45421)) |
|
||||
## Special Thanks
|
||||
Alan Agius, Alex Rickabaugh, AlirezaEbrahimkhani, Ben Brook, Dylan Hunn, George Kalpakas, Joey Perrott, JoostK, Kristiyan Kostadinov, Krzysztof Platis, Mike, Paul Gschwendtner, Tobias Speicher, alirezaghey, arturovt, dario-piotrowicz, khai and mgechev
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="14.0.0-next.7"></a>
|
||||
# 14.0.0-next.7 (2022-03-16)
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [225e4f2dbe](https://github.com/angular/angular/commit/225e4f2dbeac5982982fb94eac65ea931c44247a) | feat | triggerEventHandler accept optional eventObj ([#45279](https://github.com/angular/angular/pull/45279)) |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [9db9091349](https://github.com/angular/angular/commit/9db9091349e0e9761855d3c55729004674eec3c5) | fix | improve error message for invalid value accessors ([#45192](https://github.com/angular/angular/pull/45192)) |
|
||||
## Special Thanks
|
||||
Alan Agius, Alistair Kane, Amer Yousuf, Andrew Kushnir, Andrew Scott, Derek Cormier, Jessica Janiuk, JiaLiPassion, Lee Cooper, Paul Gschwendtner, alirezaghey and why520crazy
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="13.3.0"></a>
|
||||
# 13.3.0-rc.0 (2022-03-16)
|
||||
### core
|
||||
@@ -394,41 +477,6 @@ Alistair Kane, Andrew Scott and Kristiyan Kostadinov
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="14.0.0-next.6"></a>
|
||||
# 14.0.0-next.6 (2022-03-09)
|
||||
## Breaking Changes
|
||||
### core
|
||||
- Support for Node.js v12 has been removed as it will become EOL on 2022-04-30. Please use Node.js v14.15 or later.
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [2b7553db6f](https://github.com/angular/angular/commit/2b7553db6f59e64b73fc2e5601db278f815a67a2) | fix | compute correct offsets when interpolations have HTML entities ([#44811](https://github.com/angular/angular/pull/44811)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [6eaaefd22e](https://github.com/angular/angular/commit/6eaaefd22ebb95ee896a62237832ff2f2defdee0) | feat | drop support for Node.js 12 ([#45286](https://github.com/angular/angular/pull/45286)) |
|
||||
| [94bba76a4a](https://github.com/angular/angular/commit/94bba76a4a9594a5eb90e581f407f1b70697e715) | feat | support TypeScript 4.6 ([#45190](https://github.com/angular/angular/pull/45190)) |
|
||||
| [9fa6f5a552](https://github.com/angular/angular/commit/9fa6f5a552b7780ce32aa5a60273d4008a7b6afb) | fix | incorrectly inserting elements inside `<template>` element ([#43429](https://github.com/angular/angular/pull/43429)) |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [4332897baa](https://github.com/angular/angular/commit/4332897baa2226ef246ee054fdd5254e3c129109) | fix | Add UntypedFormBuilder ([#45268](https://github.com/angular/angular/pull/45268)) |
|
||||
| [aa7b857be8](https://github.com/angular/angular/commit/aa7b857be89a62e6dcfe62c418acf0823525d265) | fix | Property renaming safe code ([#45271](https://github.com/angular/angular/pull/45271)) |
|
||||
| [d336ba96d9](https://github.com/angular/angular/commit/d336ba96d922363235688f54d8af108ef7ab01f0) | fix | Update the typed forms migration. ([#45281](https://github.com/angular/angular/pull/45281)) |
|
||||
### language-service
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [be220fa683](https://github.com/angular/angular/commit/be220fa683e636e5ec3e49f56859015ec66a71fb) | fix | Prioritize Angular-specific completions over DOM completions ([#45293](https://github.com/angular/angular/pull/45293)) |
|
||||
### service-worker
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [bd04fbc05b](https://github.com/angular/angular/commit/bd04fbc05b0397de966a493a863e1054203c86d9) | feat | emit a notification when the service worker is already up to date after check ([#45216](https://github.com/angular/angular/pull/45216)) |
|
||||
| [3ecf93020c](https://github.com/angular/angular/commit/3ecf93020ce06b9b8621f0c83126cb3d584d4181) | fix | file system hash in batch of 500 elements ([#45262](https://github.com/angular/angular/pull/45262)) |
|
||||
## Special Thanks
|
||||
Alan Agius, Andrew Kushnir, Andrew Scott, Anner Visser, Aristeidis Bampakos, Dylan Hunn, George Kalpakas, JiaLiPassion, Joey Perrott, JoostK, Kristiyan Kostadinov, Luca, Mladen Jakovljević, Paul Gschwendtner, Srikanth Kolli, ananyahs96 and nanda18
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="13.2.6"></a>
|
||||
# 13.2.6 (2022-03-09)
|
||||
### compiler
|
||||
@@ -448,50 +496,6 @@ Andrew Scott, Anner Visser, Aristeidis Bampakos, JiaLiPassion, Joey Perrott, Kri
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="14.0.0-next.5"></a>
|
||||
# 14.0.0-next.5 (2022-03-02)
|
||||
## Breaking Changes
|
||||
### router
|
||||
- The type of `Route.pathMatch` is now more strict. Places that use
|
||||
`pathMatch` will likely need to be updated to have an explicit
|
||||
`Route`/`Routes` type so that TypeScript does not infer the type as
|
||||
`string`.
|
||||
|
||||
- Previously, resolvers were waiting to be completed
|
||||
before proceeding with the navigation and the Router would take the last
|
||||
value emitted from the resolver.
|
||||
The router now takes only the first emitted value by the resolvers
|
||||
and then proceeds with navigation. This is now consistent with `Observables`
|
||||
returned by other guards: only the first value is used.
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [7671a1e40d](https://github.com/angular/angular/commit/7671a1e40d0f2abe1cb7e9d84d5ac47a5adb546a) | fix | canceled JSONP requests won't throw console error with missing callback function ([#36807](https://github.com/angular/angular/pull/36807)) |
|
||||
| [05d50b849b](https://github.com/angular/angular/commit/05d50b849bb891c37c3eefab81a45099057dfd78) | perf | make `NgLocalization` token tree-shakable ([#45118](https://github.com/angular/angular/pull/45118)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [69018c9f42](https://github.com/angular/angular/commit/69018c9f42d14c1c7aa8271b406d6d247de1c564) | feat | allow for injector to be specified when creating an embedded view ([#45156](https://github.com/angular/angular/pull/45156)) |
|
||||
| [c5df474c7c](https://github.com/angular/angular/commit/c5df474c7c744305c9412090b5e19bb6d4f7128d) | fix | remove individual commands for updating gold files ([#45198](https://github.com/angular/angular/pull/45198)) |
|
||||
| [88f1168506](https://github.com/angular/angular/commit/88f1168506befd0665125da1fca2a719cb27dbb5) | perf | only track LViews that are referenced in __ngContext__ ([#45172](https://github.com/angular/angular/pull/45172)) |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [7ee121f595](https://github.com/angular/angular/commit/7ee121f595a47338b31098ae51a6f91d80c8fdce) | feat | Add untyped versions of the model classes for use in migration. ([#45205](https://github.com/angular/angular/pull/45205)) |
|
||||
### localize
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [ca5603b09b](https://github.com/angular/angular/commit/ca5603b09b06481529dce78ff995d674383e274f) | fix | avoid imports into `compiler-cli` package ([#45180](https://github.com/angular/angular/pull/45180)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [7fd416d060](https://github.com/angular/angular/commit/7fd416d060bd873bc88dffed41946c51aa649ec1) | fix | Fix type of Route.pathMatch to be more accurate ([#45176](https://github.com/angular/angular/pull/45176)) |
|
||||
| [c9679760b2](https://github.com/angular/angular/commit/c9679760b2bf5c607c957c20482b9cea7a21702b) | refactor | take only the first emitted value of every resolver to make it consistent with guards ([#44573](https://github.com/angular/angular/pull/44573)) |
|
||||
## Special Thanks
|
||||
Andrew Kushnir, Andrew Scott, Charles Lyding, Dmitrij Kuba, Dylan Hunn, Guillaume Bonnet, Jessica Janiuk, JiaLiPassion, JoostK, Kristiyan Kostadinov, Martin Sikora, Paul Gschwendtner, Theodore Brown and dario-piotrowicz
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="13.2.5"></a>
|
||||
# 13.2.5 (2022-03-02)
|
||||
### animations
|
||||
@@ -522,34 +526,6 @@ Andrew Kushnir, Andrew Scott, Charles Lyding, Guillaume Bonnet, Jessica Janiuk,
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="14.0.0-next.4"></a>
|
||||
# 14.0.0-next.4 (2022-02-23)
|
||||
## Breaking Changes
|
||||
### animations
|
||||
- The `AnimationDriver.getParentElement` method has become required, so any
|
||||
implementors of this interface are now required to provide an implementation
|
||||
for this method. This breakage is unlikely to affect application developers,
|
||||
as `AnimationDriver` is not expected to be implemented in user code.
|
||||
### animations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f8dc660605](https://github.com/angular/angular/commit/f8dc66060591e1ce42265a7862c3df16e40b05e1) | fix | allow animations with unsupported CSS properties ([#44729](https://github.com/angular/angular/pull/44729)) |
|
||||
| [59559fdbac](https://github.com/angular/angular/commit/59559fdbacc00bee380b1e88c79d08b6e856ebbe) | refactor | make `AnimationDriver.getParentElement` required ([#45114](https://github.com/angular/angular/pull/45114)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [c0778b4dfc](https://github.com/angular/angular/commit/c0778b4dfc1c107543b3db6f1958814a0812c7df) | fix | Support resolve animation name from the DTS ([#45107](https://github.com/angular/angular/pull/45107)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [071c8af8ba](https://github.com/angular/angular/commit/071c8af8ba89163270f17657c0c7f1c944f186f7) | perf | avoid storing LView in __ngContext__ ([#45051](https://github.com/angular/angular/pull/45051)) |
|
||||
| [a96c4827c4](https://github.com/angular/angular/commit/a96c4827c4f62e1d665d8544a3e66c51d2644c88) | perf | make `Compiler`, `ApplicationRef` and `ApplicationInitStatus` tree-shakable ([#45102](https://github.com/angular/angular/pull/45102)) |
|
||||
| [1e60fe0a3e](https://github.com/angular/angular/commit/1e60fe0a3eeb6bd46997f7eeb4825351cfbe3c44) | perf | make `LOCALE_ID` and other tokens from `ApplicationModule` tree-shakable ([#45102](https://github.com/angular/angular/pull/45102)) |
|
||||
## Special Thanks
|
||||
Alan Cohen, AlirezaEbrahimkhani, Andrew Kushnir, Andrew Scott, Daniele Maltese, David Wolf, JiaLiPassion, JoostK, Kristiyan Kostadinov, Paul Gschwendtner, arturovt, dario-piotrowicz, ivanwonder and manuelkroiss
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="13.2.4"></a>
|
||||
# 13.2.4 (2022-02-23)
|
||||
### animations
|
||||
@@ -565,32 +541,6 @@ Alan Cohen, AlirezaEbrahimkhani, Andrew Kushnir, Daniele Maltese, David Wolf, Jo
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="14.0.0-next.3"></a>
|
||||
# 14.0.0-next.3 (2022-02-17)
|
||||
### animations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [5c7c56bc85](https://github.com/angular/angular/commit/5c7c56bc859b195bf6710f6c1479d9e18dde35b1) | perf | improve algorithm to balance animation namespaces ([#45057](https://github.com/angular/angular/pull/45057)) |
|
||||
| [4c778cdb28](https://github.com/angular/angular/commit/4c778cdb28de128c6ddecd2fd6cb6257d675500b) | perf | made errors in the animations package tree shakeable ([#45004](https://github.com/angular/angular/pull/45004)) |
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [bedb257afc](https://github.com/angular/angular/commit/bedb257afc1ca12eb221536ea44ade960e62cda0) | fix | cleanup URL change listeners when the root view is removed ([#44901](https://github.com/angular/angular/pull/44901)) |
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [1b91e1049e](https://github.com/angular/angular/commit/1b91e1049eedfb96febd9f6cc45fb7c0e1f154a7) | perf | chain element start/end instructions ([#44994](https://github.com/angular/angular/pull/44994)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [e461f716d4](https://github.com/angular/angular/commit/e461f716d4b736829d53de26ba6dddb58f476746) | feat | move ANIMATION_MODULE_TYPE injection token into core ([#44970](https://github.com/angular/angular/pull/44970)) |
|
||||
| [822439fddd](https://github.com/angular/angular/commit/822439fdddfca316ac826569042efab460e67b50) | fix | `ViewContainerRef.createComponent` should consult module injector when custom one is provided ([#44966](https://github.com/angular/angular/pull/44966)) |
|
||||
| [45d98e7ca5](https://github.com/angular/angular/commit/45d98e7ca5accf918e2602cbc17805e11e18896b) | perf | make `IterableDiffers` and `KeyValueDiffers` tree-shakable ([#45094](https://github.com/angular/angular/pull/45094)) |
|
||||
## Special Thanks
|
||||
Alan Cohen, AlirezaEbrahimkhani, Amer Yousuf, Andrew Kushnir, Aristeidis Bampakos, Dario Piotrowicz, Dylan Hunn, Esteban Gehring, George Kalpakas, Jessica Janiuk, JiaLiPassion, Joey Perrott, JoostK, Kristiyan Kostadinov, Mina Hosseini Moghadam, Patrick Cameron, Srdjan Milic, Yousaf Nawaz, arturovt, dario-piotrowicz, markostanimirovic, mgechev and zuckjet
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="13.2.3"></a>
|
||||
# 13.2.3 (2022-02-16)
|
||||
### animations
|
||||
@@ -633,118 +583,6 @@ Alan Agius, Alan Cohen, Andrew Kushnir, Andrew Scott, Daniel Díaz, Dario Piotro
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="14.0.0-next.2"></a>
|
||||
# 14.0.0-next.2 (2022-02-07)
|
||||
## Breaking Changes
|
||||
|
||||
### forms
|
||||
- Forms [email] input coercion: forms [email] input value will be considered as true if it is defined with any value rather than false and 'false'.
|
||||
- Objects with a length key set to zero will no longer validate as empty. This is technically a breaking change, since objects with a key `length` and value `0` will no longer validate as empty. This is a very minor change, and any reliance on this behavior is probably a bug anyway.
|
||||
### platform-browser
|
||||
- This change may cause a breaking change in unit tests that are implicitly depending on a specific number and sequence of change detections in order for their assertions to pass.
|
||||
- This tightens parameter types of `TransferState` usage, and is a minor breaking change which may reveal existing problematic calls. This may break invalid calls to `TransferState` methods.
|
||||
### router
|
||||
- The type of `initialUrl` is set to `string|UrlTree` but in reality,
|
||||
the `Router` only sets it to a value that will always be `UrlTree`.
|
||||
`initialUrl` is documented as "The target URL passed into the
|
||||
`Router#navigateByUrl()` call before navigation" but the value
|
||||
actually gets set to something completely different. It's set to the
|
||||
current internal `UrlTree` of the Router at the time navigation
|
||||
occurs. With this change, there is no exact replacement for the old value of
|
||||
`initialUrl` because it was enver intended to be exposed.
|
||||
`Router.url` is likely the best replacement for this.
|
||||
In more specific use-cases, tracking the `finalUrl` between successful
|
||||
navigations can also be used as a replacement.
|
||||
### animations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [e46b379204](https://github.com/angular/angular/commit/e46b37920438d84bff895498c0a102dd1ffba178) | fix | implement missing transition delay ([#44799](https://github.com/angular/angular/pull/44799)) |
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [38c03a2035](https://github.com/angular/angular/commit/38c03a20358db3f8621c023b98e627cd385731c0) | feat | support years greater than 9999 ([#43622](https://github.com/angular/angular/pull/43622)) |
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [db6cf7e7c1](https://github.com/angular/angular/commit/db6cf7e7c168f9a25550d7fa53840c08b50b889c) | fix | allow banana-in-a-box bindings to end with non-null assertion ([#37809](https://github.com/angular/angular/pull/37809)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [0072eb48ba](https://github.com/angular/angular/commit/0072eb48ba1c6f549703988b7fd7ba3e09058048) | feat | initial implementation of standalone components ([#44812](https://github.com/angular/angular/pull/44812)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [d5719c2e0f](https://github.com/angular/angular/commit/d5719c2e0fb237be71d658444bbfe2410e05086a) | fix | input coercion ([#42803](https://github.com/angular/angular/pull/42803)) |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [8dd3f82f94](https://github.com/angular/angular/commit/8dd3f82f946bae86dc6c678d8694ab73d915bbfa) | fix | Correct empty validator to handle objects with a property `length: 0`. ([#33729](https://github.com/angular/angular/pull/33729)) |
|
||||
| [ebf2fc5224](https://github.com/angular/angular/commit/ebf2fc5224c9debfd839087c9d1d21fb49577d37) | fix | incorrectly keeping track of ngModel with ngFor inside a form ([#40459](https://github.com/angular/angular/pull/40459)) |
|
||||
### http
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [28393031b1](https://github.com/angular/angular/commit/28393031b10f4dbefab7587c19641e49cb820785) | perf | remove IE special status handling ([#44354](https://github.com/angular/angular/pull/44354)) |
|
||||
### platform-browser
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [a01bcb8e7e](https://github.com/angular/angular/commit/a01bcb8e7eaf63ac9466a78dd4d15228241da900) | fix | do not run change detection when loading Hammer ([#44921](https://github.com/angular/angular/pull/44921)) |
|
||||
| [b32647dc68](https://github.com/angular/angular/commit/b32647dc68b055da0c49c86d6e7e2a7d2ec5954a) | fix | Make transfer state key typesafe. ([#23020](https://github.com/angular/angular/pull/23020)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [791bd31424](https://github.com/angular/angular/commit/791bd3142432ed7caf14a68a6e434b27004e634b) | feat | set stricter type for Route.title ([#44939](https://github.com/angular/angular/pull/44939)) |
|
||||
| [64f837d2c0](https://github.com/angular/angular/commit/64f837d2c0fbcf722d32b35a87e87220bfe61f65) | fix | Update `Navigation#initialUrl` to match documentation and reality ([#43863](https://github.com/angular/angular/pull/43863)) |
|
||||
### upgrade
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [202a1a5631](https://github.com/angular/angular/commit/202a1a56314af4ddb99c476f974536a10e390319) | fix | Do not trigger duplicate navigation events from Angular Router ([#43441](https://github.com/angular/angular/pull/43441)) |
|
||||
## Special Thanks
|
||||
Alan Agius, Alex Rickabaugh, Andrew Kushnir, Andrew Scott, Daniel Díaz, Dario Piotrowicz, Doug Parker, Jayson Acosta, Joey Perrott, JoostK, Kristiyan Kostadinov, Olivier Capuozzo, Payam Shahidi, Pusztai Tibor, Ramzan, Ruslan Lekhman, Sergej Grilborzer, Shai Reznik, TANMAY SRIVASTAVA, arturovt, dario-piotrowicz, iRealNirmal, jhonyeduardo, markostanimirovic, mgechev and zuckjet
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="14.0.0-next.1"></a>
|
||||
# 14.0.0-next.1 (2022-02-02)
|
||||
## Deprecations
|
||||
### common
|
||||
- The `ngModuleFactory` input of the `NgComponentOutlet` directive is deprecated in favor of a newly added `ngModule` input. The `ngModule` input accepts references to the NgModule class directly, without the need to resolve module factory first.
|
||||
### animations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [7a81481fb2](https://github.com/angular/angular/commit/7a81481fb29e94b550db7ad68270eccf26bb2743) | perf | Remove generic objects in favor of Maps ([#44482](https://github.com/angular/angular/pull/44482)) |
|
||||
| [6642e3c8fd](https://github.com/angular/angular/commit/6642e3c8fd7d3b5ed22710667b2c41a46f14eda8) | perf | remove no longer needed CssKeyframes classes ([#44903](https://github.com/angular/angular/pull/44903)) |
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [c89cf63059](https://github.com/angular/angular/commit/c89cf63059370bba43717483e3d9627499dfe815) | feat | support NgModule as an input to the NgComponentOutlet ([#44815](https://github.com/angular/angular/pull/44815)) |
|
||||
| [a2cbffc06f](https://github.com/angular/angular/commit/a2cbffc06f25ea1cb8f1c8aef658f7c213621a07) | fix | include query parameters for open HTTP requests in `verify` ([#44917](https://github.com/angular/angular/pull/44917)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [73c97aea9e](https://github.com/angular/angular/commit/73c97aea9e4a1cb94199272384d5e912d3b0ccd0) | fix | accept nullish coalescing operator for any and unknown types ([#44862](https://github.com/angular/angular/pull/44862)) |
|
||||
| [366e424a73](https://github.com/angular/angular/commit/366e424a7382cdbd72f5d1c3460fe2992fb72941) | fix | enable nullish coalescing check only with `strictNullChecks` ([#44862](https://github.com/angular/angular/pull/44862)) |
|
||||
| [d82c957a26](https://github.com/angular/angular/commit/d82c957a260f4e4a341e7036355a764a5e98d3ca) | fix | ensure casing of logical paths is preserved ([#44798](https://github.com/angular/angular/pull/44798)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [5686f68fde](https://github.com/angular/angular/commit/5686f68fde514a7daf760aacc1fe52a7cb80b3af) | fix | Add back support for namespace URIs in createElement of dom renderer ([#44914](https://github.com/angular/angular/pull/44914)) |
|
||||
| [39c614c438](https://github.com/angular/angular/commit/39c614c4389fb48c8fc5a51329e9169a0139c4aa) | fix | flush delayed scoping queue while setting up TestBed ([#44814](https://github.com/angular/angular/pull/44814)) |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f490c2de4e](https://github.com/angular/angular/commit/f490c2de4e1ada26e62e35c0d70cb90e55297658) | feat | support negative indices in FormArray methods. ([#44848](https://github.com/angular/angular/pull/44848)) |
|
||||
| [889de8276d](https://github.com/angular/angular/commit/889de8276d77eed3b65f8c2032f2f5c3c4ac9139) | fix | ensure OnPush ancestors are marked dirty when the promise resolves ([#44886](https://github.com/angular/angular/pull/44886)) |
|
||||
| [deb9531a31](https://github.com/angular/angular/commit/deb9531a31274fbedcbf468a33d80481328c55ce) | fix | Update the typed forms migration schematic to find all files. ([#44881](https://github.com/angular/angular/pull/44881)) |
|
||||
| [cae1e44608](https://github.com/angular/angular/commit/cae1e44608227ac80682401190c6d28ef39b3269) | fix | Update the typed forms migration to use FormArray<T> instead of FormArray<T[]>. ([#44933](https://github.com/angular/angular/pull/44933)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [910de8bc33](https://github.com/angular/angular/commit/910de8bc3379b1452c0bc23a866b5108d6d94e55) | feat | Add `Route.title` with a configurable `TitleStrategy` ([#43307](https://github.com/angular/angular/pull/43307)) |
|
||||
## Special Thanks
|
||||
Alan, Alan Agius, AleksanderBodurri, Amir Rustamzadeh, Andrew Kushnir, Andrew Scott, Aristeidis Bampakos, Arjen, Daan De Smedt, Daniel Díaz, David Shevitz, Doug Parker, Dylan Hunn, Emma Twersky, Esteban Gehring, George Kalpakas, Jessica Janiuk, JimMorrison723, JoostK, Juri Strumpflohner, Lee Robinson, Maarten Tibau, Mark Whitfeld, Minko Gechev, Paul Gschwendtner, Ricardo Mattiazzi Baumgartner, Sumit Arora, Theodore Brown, arturovt, dario-piotrowicz, fru2, kamikopi, markostanimirovic, markwhitfeld, mgechev, renovate[bot] and twerske
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="13.2.1"></a>
|
||||
# 13.2.1 (2022-02-02)
|
||||
### animations
|
||||
@@ -776,21 +614,6 @@ Alan, Andrew Kushnir, Andrew Scott, Aristeidis Bampakos, Arjen, Daniel Díaz, Da
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="14.0.0-next.0"></a>
|
||||
# 14.0.0-next.0 (2022-01-26)
|
||||
### language-service
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [9d4af65e34](https://github.com/angular/angular/commit/9d4af65e343e41b48cb9afd12c2b61d8ca61a9ac) | feat | Provide plugin to delegate rename requests to Angular ([#44696](https://github.com/angular/angular/pull/44696)) |
|
||||
### service-worker
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [ec0a0e0669](https://github.com/angular/angular/commit/ec0a0e0669ef5d2f524fbf9a540eb2b306b2e24a) | feat | add `cacheOpaqueResponses` option for data-groups ([#44723](https://github.com/angular/angular/pull/44723)) |
|
||||
## Special Thanks
|
||||
Andrew Kushnir, Dylan Hunn, George Kalpakas, JiaLiPassion, Joey Perrott and ivanwonder
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="13.2.0"></a>
|
||||
# 13.2.0 (2022-01-26)
|
||||
## Deprecations
|
||||
|
||||
+7
-7
@@ -94,7 +94,7 @@ Before you submit your Pull Request (PR) consider the following guidelines:
|
||||
5. In your forked repository, make your changes in a new git branch:
|
||||
|
||||
```shell
|
||||
git checkout -b my-fix-branch master
|
||||
git checkout -b my-fix-branch main
|
||||
```
|
||||
|
||||
6. Create your patch, **including appropriate test cases**.
|
||||
@@ -117,7 +117,7 @@ Before you submit your Pull Request (PR) consider the following guidelines:
|
||||
git push origin my-fix-branch
|
||||
```
|
||||
|
||||
11. In GitHub, send a pull request to `angular:master`.
|
||||
11. In GitHub, send a pull request to `angular:main`.
|
||||
|
||||
### Reviewing a Pull Request
|
||||
|
||||
@@ -181,10 +181,10 @@ After your pull request is merged, you can safely delete your branch and pull th
|
||||
git push origin --delete my-fix-branch
|
||||
```
|
||||
|
||||
* Check out the master branch:
|
||||
* Check out the main branch:
|
||||
|
||||
```shell
|
||||
git checkout master -f
|
||||
git checkout main -f
|
||||
```
|
||||
|
||||
* Delete the local branch:
|
||||
@@ -193,10 +193,10 @@ After your pull request is merged, you can safely delete your branch and pull th
|
||||
git branch -D my-fix-branch
|
||||
```
|
||||
|
||||
* Update your master with the latest upstream version:
|
||||
* Update your local `main` with the latest upstream version:
|
||||
|
||||
```shell
|
||||
git pull --ff upstream master
|
||||
git pull --ff upstream main
|
||||
```
|
||||
|
||||
|
||||
@@ -397,7 +397,7 @@ The following documents can help you sort out issues with GitHub accounts and mu
|
||||
[coc]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md
|
||||
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
|
||||
[corporate-cla]: https://cla.developers.google.com/about/google-corporate
|
||||
[dev-doc]: https://github.com/angular/angular/blob/master/docs/DEVELOPER.md
|
||||
[dev-doc]: https://github.com/angular/angular/blob/main/docs/DEVELOPER.md
|
||||
[github]: https://github.com/angular/angular
|
||||
[discord]: https://discord.gg/angular
|
||||
[individual-cla]: https://cla.developers.google.com/about/google-individual
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://circleci.com/gh/angular/workflows/angular/tree/master">
|
||||
<img src="https://img.shields.io/circleci/build/github/angular/angular/master.svg?logo=circleci&logoColor=fff&label=CircleCI" alt="CI status" />
|
||||
<a href="https://circleci.com/gh/angular/workflows/angular/tree/main">
|
||||
<img src="https://img.shields.io/circleci/build/github/angular/angular/main.svg?logo=circleci&logoColor=fff&label=CircleCI" alt="CI status" />
|
||||
</a>
|
||||
<a href="https://www.npmjs.com/@angular/core">
|
||||
<img src="https://img.shields.io/npm/v/@angular/core.svg?logo=npm&logoColor=fff&label=NPM+package&color=limegreen" alt="Angular on npm" />
|
||||
|
||||
@@ -8,10 +8,24 @@ workspace(
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
# Add a patch fix for rules_webtesting v0.3.5 required for enabling runfiles on Windows.
|
||||
# TODO: Remove the http_archive for this transitive dependency when a release is cut
|
||||
# for https://github.com/bazelbuild/rules_webtesting/commit/581b1557e382f93419da6a03b91a45c2ac9a9ec8
|
||||
# and the version is updated in rules_nodejs.
|
||||
http_archive(
|
||||
name = "io_bazel_rules_webtesting",
|
||||
patch_args = ["-p1"],
|
||||
patches = [
|
||||
"//:tools/bazel-repo-patches/rules_webtesting__windows_runfiles_fix.patch",
|
||||
],
|
||||
sha256 = "e9abb7658b6a129740c0b3ef6f5a2370864e102a5ba5ffca2cea565829ed825a",
|
||||
urls = ["https://github.com/bazelbuild/rules_webtesting/releases/download/0.3.5/rules_webtesting.tar.gz"],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "build_bazel_rules_nodejs",
|
||||
sha256 = "2b2004784358655f334925e7eadc7ba80f701144363df949b3293e1ae7a2fb7b",
|
||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/5.4.0/rules_nodejs-5.4.0.tar.gz"],
|
||||
sha256 = "0fad45a9bda7dc1990c47b002fd64f55041ea751fafc00cd34efb96107675778",
|
||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/5.5.0/rules_nodejs-5.5.0.tar.gz"],
|
||||
)
|
||||
|
||||
load("@build_bazel_rules_nodejs//:repositories.bzl", "build_bazel_rules_nodejs_dependencies")
|
||||
@@ -144,14 +158,16 @@ cldr_xml_data_repository(
|
||||
# sass rules
|
||||
http_archive(
|
||||
name = "io_bazel_rules_sass",
|
||||
sha256 = "b83d695bc8deb5ab5fb3a8e6919999eebf738a4a5aa57a43a63ee70109f80224",
|
||||
strip_prefix = "rules_sass-1.50.0",
|
||||
sha256 = "c0b0cd75596e80b32dc9804a394a3d022af8ff660024e9c61a2268e659f38d49",
|
||||
strip_prefix = "rules_sass-1.52.3",
|
||||
urls = [
|
||||
"https://github.com/bazelbuild/rules_sass/archive/1.50.0.zip",
|
||||
"https://github.com/bazelbuild/rules_sass/archive/1.52.3.zip",
|
||||
],
|
||||
)
|
||||
|
||||
# Setup the rules_sass toolchain
|
||||
load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories")
|
||||
|
||||
sass_repositories()
|
||||
sass_repositories(
|
||||
yarn_script = "//:.yarn/releases/yarn-1.22.17.cjs",
|
||||
)
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
"@typescript-eslint/naming-convention": "off",
|
||||
"no-console": ["error", {"allow": ["log", "warn", "error"]}],
|
||||
"no-empty-function": "off",
|
||||
"@angular-eslint/no-host-metadata-property": "off",
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
|
||||
+14
-17
@@ -1,19 +1,19 @@
|
||||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# compiled output
|
||||
# Compiled output
|
||||
/dist
|
||||
/out-tsc
|
||||
/src/generated
|
||||
/tmp
|
||||
/out-tsc
|
||||
/bazel-out
|
||||
/src/generated
|
||||
|
||||
# Cache folder for the Angular CLI.
|
||||
.angular/cache
|
||||
|
||||
# dependencies
|
||||
# Node
|
||||
/node_modules
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.idea/
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
@@ -21,31 +21,28 @@
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# IDE - VSCode
|
||||
# Visual Studio Code
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.history/*
|
||||
|
||||
# misc
|
||||
# Miscellaneous
|
||||
/.angular/cache
|
||||
/.firebase/
|
||||
/.sass-cache
|
||||
.sass-cache/
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
debug.log
|
||||
firebase-debug.log
|
||||
npm-debug.log
|
||||
testem.log
|
||||
/typings
|
||||
yarn-error.log
|
||||
|
||||
# e2e
|
||||
/e2e/*.js
|
||||
/e2e/*.map
|
||||
protractor-results*.txt
|
||||
|
||||
# System Files
|
||||
# System files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
load("@aio_npm//@angular-devkit/architect-cli:index.bzl", "architect", "architect_test")
|
||||
load("@build_bazel_rules_nodejs//:index.bzl", "npm_package_bin")
|
||||
load("//tools:defaults.bzl", "npm_package_bin")
|
||||
|
||||
# The write_source_files macro is used to write bazel outputs to the source tree and test that they are up to date.
|
||||
# See: https://docs.aspect.build/aspect-build/bazel-lib/v0.5.0/docs/docs/write_source_files-docgen.html
|
||||
|
||||
@@ -4,28 +4,69 @@ import fetch, {RequestInit} from 'node-fetch';
|
||||
import {assertNotMissingOrEmpty} from './utils';
|
||||
|
||||
// Constants
|
||||
const CIRCLE_CI_API_URL = 'https://circleci.com/api/v2/project/gh';
|
||||
const CIRCLE_CI_BASE_API_URL = 'https://circleci.com/api/v2';
|
||||
const CIRCLE_CI_BUILD_API_URL = `${CIRCLE_CI_BASE_API_URL}/project/gh`;
|
||||
const CIRCLE_CI_PIPELINE_API_URL = `${CIRCLE_CI_BASE_API_URL}/pipeline`;
|
||||
|
||||
// Interfaces - Types
|
||||
|
||||
// API docs: https://circleci.com/docs/api/v2#operation/getJobArtifacts
|
||||
// Example: https://circleci.com/api/v2/project/gh/angular/angular/1163941/artifacts
|
||||
export interface ArtifactInfo {
|
||||
/** The path of this build artifacts. */
|
||||
path: string;
|
||||
pretty_path: string;
|
||||
node_index: number;
|
||||
|
||||
/** The full URL where this artifact can be downloaded from. */
|
||||
url: string;
|
||||
|
||||
// There are other fields but they are not used in this code.
|
||||
}
|
||||
|
||||
export type ArtifactResponse = ArtifactInfo[];
|
||||
export type ArtifactResponse = {items: ArtifactInfo[]};
|
||||
|
||||
// API docs: https://circleci.com/docs/api/v2#operation/getJobDetails
|
||||
// Example: https://circleci.com/api/v2/project/gh/angular/angular/job/1163941
|
||||
export interface BuildInfo {
|
||||
reponame: string;
|
||||
failed: boolean;
|
||||
branch: string;
|
||||
username: string;
|
||||
build_num: number;
|
||||
has_artifacts: boolean;
|
||||
outcome: string; // e.g. 'success'
|
||||
vcs_revision: string; // HEAD SHA
|
||||
// there are other fields but they are not used in this code
|
||||
/** The job number. */
|
||||
number: number;
|
||||
|
||||
/** The job name (e.g. `'aio_preview'`). */
|
||||
name: string;
|
||||
|
||||
/** Info about the organization which the project related to this job belongs to. */
|
||||
organization: {
|
||||
name: string;
|
||||
};
|
||||
|
||||
/** Info about the project related to this job. */
|
||||
project: {
|
||||
name: string;
|
||||
};
|
||||
|
||||
/** Info about the [pipeline](https://circleci.com/docs/2.0/pipelines/) that this job is part of. */
|
||||
pipeline: {
|
||||
id: string;
|
||||
};
|
||||
|
||||
// There are other fields but they are not used in this code.
|
||||
}
|
||||
|
||||
// API docs: https://circleci.com/docs/api/v2#operation/getPipelineById
|
||||
// https://circleci.com/api/v2/pipeline/356227c0-32f6-4f99-bfc2-3938db90a147
|
||||
export interface PipelineInfo {
|
||||
/** The pipeline ID. */
|
||||
id: string;
|
||||
|
||||
/** Info related to/retrieved from the version control system provider (e.g. GitHub). */
|
||||
vcs: {
|
||||
/** The PR number. */
|
||||
review_id: string;
|
||||
|
||||
/** The HEAD SHA. */
|
||||
revision: string;
|
||||
};
|
||||
|
||||
// There are other fields but they are not used in this code.
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,13 +100,13 @@ export class CircleCiApi {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the info for a build from the CircleCI API
|
||||
* Get the info for a build (aka job) from the CircleCI API.
|
||||
* @param buildNumber The CircleCI build number that generated the artifact.
|
||||
* @returns A promise to the info about the build
|
||||
* @returns A promise to the info about the build.
|
||||
*/
|
||||
public async getBuildInfo(buildNumber: number): Promise<BuildInfo> {
|
||||
try {
|
||||
const url = `${CIRCLE_CI_API_URL}/${this.githubOrg}/${this.githubRepo}/job/${buildNumber}`;
|
||||
const url = `${CIRCLE_CI_BUILD_API_URL}/${this.githubOrg}/${this.githubRepo}/job/${buildNumber}`;
|
||||
const response = await this.fetchFromCircleCi(url);
|
||||
return response.json();
|
||||
} catch (error) {
|
||||
@@ -79,10 +120,10 @@ export class CircleCiApi {
|
||||
* @returns A promise to the URL that can be requested to download the actual build artifact file.
|
||||
*/
|
||||
public async getBuildArtifactUrl(buildNumber: number, artifactPath: string): Promise<string> {
|
||||
const baseUrl = `${CIRCLE_CI_API_URL}/${this.githubOrg}/${this.githubRepo}/${buildNumber}`;
|
||||
const baseUrl = `${CIRCLE_CI_BUILD_API_URL}/${this.githubOrg}/${this.githubRepo}/${buildNumber}`;
|
||||
try {
|
||||
const response = await this.fetchFromCircleCi(`${baseUrl}/artifacts`);
|
||||
const artifacts = await response.json() as {items: ArtifactResponse};
|
||||
const artifacts = await response.json() as ArtifactResponse;
|
||||
const artifact = artifacts.items.find(item => item.path === artifactPath);
|
||||
if (!artifact) {
|
||||
throw new Error(`Missing artifact (${artifactPath}) for CircleCI build: ${buildNumber}`);
|
||||
@@ -92,4 +133,19 @@ export class CircleCiApi {
|
||||
throw new Error(`CircleCI artifact URL request failed (${(error as Error).message})`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the info for a [pipeline](https://circleci.com/docs/2.0/pipelines/) from the CircleCI API.
|
||||
* @param pipelineId The CircleCI pipeline ID that generated the artifact.
|
||||
* @returns A promise to the info about the pipeline.
|
||||
*/
|
||||
public async getPipelineInfo(pipelineId: string): Promise<PipelineInfo> {
|
||||
try {
|
||||
const url = `${CIRCLE_CI_PIPELINE_API_URL}/${pipelineId}`;
|
||||
const response = await this.fetchFromCircleCi(url);
|
||||
return response.json();
|
||||
} catch (error) {
|
||||
throw new Error(`CircleCI pipeline info request failed (${(error as Error).message})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ export interface GithubInfo {
|
||||
pr: number;
|
||||
repo: string;
|
||||
sha: string;
|
||||
success: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,12 +35,12 @@ export class BuildRetriever {
|
||||
*/
|
||||
public async getGithubInfo(buildNum: number): Promise<GithubInfo> {
|
||||
const buildInfo = await this.api.getBuildInfo(buildNum);
|
||||
const pipelineInfo = await this.api.getPipelineInfo(buildInfo.pipeline.id);
|
||||
const githubInfo: GithubInfo = {
|
||||
org: buildInfo.username,
|
||||
pr: getPrFromBranch(buildInfo.branch),
|
||||
repo: buildInfo.reponame,
|
||||
sha: buildInfo.vcs_revision,
|
||||
success: !buildInfo.failed,
|
||||
org: buildInfo.organization.name,
|
||||
pr: +pipelineInfo.vcs.review_id,
|
||||
repo: buildInfo.project.name,
|
||||
sha: pipelineInfo.vcs.revision,
|
||||
};
|
||||
return githubInfo;
|
||||
}
|
||||
@@ -76,12 +75,3 @@ export class BuildRetriever {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getPrFromBranch(branch: string): number {
|
||||
// CircleCI only exposes PR numbers via the `branch` field :-(
|
||||
const match = /^pull\/(\d+)$/.exec(branch);
|
||||
if (!match) {
|
||||
throw new Error(`No PR found in branch field: ${branch}`);
|
||||
}
|
||||
return +match[1];
|
||||
}
|
||||
|
||||
+1
-7
@@ -120,13 +120,7 @@ export class PreviewServerFactory {
|
||||
return;
|
||||
}
|
||||
|
||||
const { pr, sha, org, repo, success } = await buildRetriever.getGithubInfo(buildNum);
|
||||
|
||||
if (!success) {
|
||||
res.sendStatus(204);
|
||||
logger.log(`PR:${pr}, Build:${buildNum} - Skipping preview processing because this build did not succeed.`);
|
||||
return;
|
||||
}
|
||||
const { pr, sha, org, repo } = await buildRetriever.getGithubInfo(buildNum);
|
||||
|
||||
assert(cfg.githubOrg === org,
|
||||
`Invalid webhook: expected "githubOrg" property to equal "${cfg.githubOrg}" but got "${org}".`);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
export const enum BuildNums {
|
||||
BUILD_INFO_ERROR = 1,
|
||||
BUILD_INFO_404,
|
||||
BUILD_INFO_BUILD_FAILED,
|
||||
BUILD_INFO_INVALID_GH_ORG,
|
||||
BUILD_INFO_INVALID_GH_REPO,
|
||||
PIPELINE_INFO_ERROR,
|
||||
PIPELINE_INFO_404,
|
||||
CHANGED_FILES_ERROR,
|
||||
CHANGED_FILES_404,
|
||||
CHANGED_FILES_NONE,
|
||||
@@ -21,6 +22,17 @@ export const enum BuildNums {
|
||||
TRUST_CHECK_INACTIVE_TRUSTED_USER,
|
||||
}
|
||||
|
||||
export const enum PipelineIds {
|
||||
PIPELINE_INFO_ERROR = 'pipeline-error',
|
||||
PIPELINE_INFO_404 = 'pipeline-404',
|
||||
CHANGED_FILES_ERROR = 'pipeline-cfe',
|
||||
CHANGED_FILES_404 = 'pipeline-cf404',
|
||||
CHANGED_FILES_NONE = 'pipeline-cfn',
|
||||
TRUST_CHECK_ERROR = 'pipeline-tce',
|
||||
TRUST_CHECK_UNTRUSTED = 'pipeline-tcu',
|
||||
PIPELINE_INFO_OK = 'pipeline-ok',
|
||||
}
|
||||
|
||||
export const enum PrNums {
|
||||
CHANGED_FILES_ERROR = 1,
|
||||
CHANGED_FILES_404,
|
||||
|
||||
+58
-35
@@ -3,7 +3,7 @@ import * as nock from 'nock';
|
||||
import * as tar from 'tar-stream';
|
||||
import {gzipSync} from 'zlib';
|
||||
import {getEnvVar, Logger} from '../common/utils';
|
||||
import {BuildNums, PrNums, SHA} from './constants';
|
||||
import {BuildNums, PipelineIds, PrNums, SHA} from './constants';
|
||||
|
||||
// We are using the `nock` library to fake responses from REST requests, when testing.
|
||||
// This is necessary, because the test preview-server runs as a separate node process to
|
||||
@@ -30,11 +30,17 @@ const INACTIVE_TRUSTED_USER = 'inactive-trusted-user';
|
||||
const UNTRUSTED_USER = 'untrusted-user';
|
||||
|
||||
const BASIC_BUILD_INFO = {
|
||||
branch: `pull/${PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER}`,
|
||||
failed: false,
|
||||
reponame: AIO_GITHUB_REPO,
|
||||
username: AIO_GITHUB_ORGANIZATION,
|
||||
vcs_revision: SHA,
|
||||
name: 'test_job',
|
||||
organization: {name: AIO_GITHUB_ORGANIZATION},
|
||||
project: {name: AIO_GITHUB_REPO},
|
||||
pipeline: {id: PipelineIds.PIPELINE_INFO_OK},
|
||||
};
|
||||
const BASIC_PIPELINE_INFO = {
|
||||
id: PipelineIds.PIPELINE_INFO_OK,
|
||||
vcs: {
|
||||
review_id: `${PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER}`,
|
||||
revision: SHA,
|
||||
},
|
||||
};
|
||||
|
||||
const ISSUE_INFO_TRUSTED_LABEL = { labels: [{ name: AIO_TRUSTED_PR_LABEL }], user: { login: UNTRUSTED_USER } };
|
||||
@@ -47,7 +53,6 @@ const INACTIVE_STATE = { state: 'inactive' };
|
||||
const TEST_TEAM_INFO = AIO_GITHUB_TEAM_SLUGS.map((slug, index) => ({ slug, id: index }));
|
||||
|
||||
const CIRCLE_CI_API_HOST = 'https://circleci.com';
|
||||
const CIRCLE_CI_TOKEN_PARAM = `circle-token=${AIO_CIRCLE_CI_TOKEN}`;
|
||||
const ARTIFACT_1 = { path: 'artifact-1', url: `${CIRCLE_CI_API_HOST}/artifacts/artifact-1`, _urlPath: '/artifacts/artifact-1' };
|
||||
const ARTIFACT_2 = { path: 'artifact-2', url: `${CIRCLE_CI_API_HOST}/artifacts/artifact-2`, _urlPath: '/artifacts/artifact-2' };
|
||||
const ARTIFACT_3 = { path: 'artifact-3', url: `${CIRCLE_CI_API_HOST}/artifacts/artifact-3`, _urlPath: '/artifacts/artifact-3' };
|
||||
@@ -57,11 +62,13 @@ const ARTIFACT_VALID_TRUSTED_USER = { path: AIO_ARTIFACT_PATH, url: `${CIRCLE_CI
|
||||
const ARTIFACT_VALID_TRUSTED_LABEL = { path: AIO_ARTIFACT_PATH, url: `${CIRCLE_CI_API_HOST}/artifacts/valid/label`, _urlPath: '/artifacts/valid/label' };
|
||||
const ARTIFACT_VALID_UNTRUSTED = { path: AIO_ARTIFACT_PATH, url: `${CIRCLE_CI_API_HOST}/artifacts/valid/untrusted`, _urlPath: '/artifacts/valid/untrusted' };
|
||||
|
||||
const CIRCLE_CI_BUILD_INFO_URL = `/api/v1.1/project/github/${AIO_GITHUB_ORGANIZATION}/${AIO_GITHUB_REPO}`;
|
||||
const CIRCLE_CI_BUILD_INFO_URL = `/api/v2/project/gh/${AIO_GITHUB_ORGANIZATION}/${AIO_GITHUB_REPO}`;
|
||||
const CIRCLE_CI_PIPELINE_INFO_URL = '/api/v2/pipeline';
|
||||
|
||||
const buildInfoUrl = (buildNum: number) => `${CIRCLE_CI_BUILD_INFO_URL}/${buildNum}?${CIRCLE_CI_TOKEN_PARAM}`;
|
||||
const buildArtifactsUrl = (buildNum: number) => `${CIRCLE_CI_BUILD_INFO_URL}/${buildNum}/artifacts?${CIRCLE_CI_TOKEN_PARAM}`;
|
||||
const buildInfo = (prNum: number) => ({ ...BASIC_BUILD_INFO, branch: `pull/${prNum}` });
|
||||
const buildInfoUrl = (buildNum: number) => `${CIRCLE_CI_BUILD_INFO_URL}/job/${buildNum}`;
|
||||
const buildArtifactsUrl = (buildNum: number) => `${CIRCLE_CI_BUILD_INFO_URL}/${buildNum}/artifacts`;
|
||||
const pipelineInfoUrl = (pipelineId: string) => `${CIRCLE_CI_PIPELINE_INFO_URL}/${pipelineId}`;
|
||||
const buildInfo = (pipelineId: string) => ({ ...BASIC_BUILD_INFO, pipeline: { id: pipelineId } });
|
||||
|
||||
const GITHUB_API_HOST = 'https://api.github.com';
|
||||
const GITHUB_ISSUES_URL = `/repos/${AIO_GITHUB_ORGANIZATION}/${AIO_GITHUB_REPO}/issues`;
|
||||
@@ -73,6 +80,15 @@ const getFilesUrl = (prNum: number, pageNum = 1) => `${GITHUB_PULLS_URL}/${prNum
|
||||
const getCommentUrl = (prNum: number) => `${getIssueUrl(prNum)}/comments`;
|
||||
const getTeamMembershipUrl = (teamId: number, username: string) => `/teams/${teamId}/memberships/${username}`;
|
||||
|
||||
const setUpCircleCiApiForBuild =
|
||||
(buildNum: number, pipelineId: string, prNum = PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER, sha = SHA) => {
|
||||
circleCiApi.get(buildInfoUrl(buildNum)).reply(200, buildInfo(pipelineId));
|
||||
circleCiApi.get(pipelineInfoUrl(pipelineId)).reply(200, {
|
||||
id: pipelineId,
|
||||
vcs: { review_id: `${prNum}`, revision: sha },
|
||||
});
|
||||
};
|
||||
|
||||
const createArchive = (buildNum: number, prNum: number, sha: string) => {
|
||||
logger.log('createArchive', buildNum, prNum, sha);
|
||||
const pack = tar.pack();
|
||||
@@ -84,7 +100,7 @@ const createArchive = (buildNum: number, prNum: number, sha: string) => {
|
||||
};
|
||||
|
||||
// Create request scopes
|
||||
const circleCiApi = nock(CIRCLE_CI_API_HOST).persist();
|
||||
const circleCiApi = nock(CIRCLE_CI_API_HOST).persist().matchHeader('Circle-Token', AIO_CIRCLE_CI_TOKEN);
|
||||
const githubApi = nock(GITHUB_API_HOST).persist().matchHeader('Authorization', `token ${AIO_GITHUB_TOKEN}`);
|
||||
|
||||
//////////////////////////////
|
||||
@@ -92,50 +108,57 @@ const githubApi = nock(GITHUB_API_HOST).persist().matchHeader('Authorization', `
|
||||
// GENERAL responses
|
||||
githubApi.get(GITHUB_TEAMS_URL + '?page=1&per_page=100').reply(200, TEST_TEAM_INFO);
|
||||
githubApi.post(getCommentUrl(PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER)).reply(200);
|
||||
circleCiApi.get(pipelineInfoUrl(PipelineIds.PIPELINE_INFO_OK)).reply(200, BASIC_PIPELINE_INFO);
|
||||
|
||||
// BUILD_INFO errors
|
||||
// BUILD INFO errors
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_INFO_ERROR)).replyWithError('BUILD_INFO_ERROR');
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_INFO_404)).reply(404, 'BUILD_INFO_404');
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_INFO_BUILD_FAILED)).reply(200, { ...BASIC_BUILD_INFO, failed: true });
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_INFO_INVALID_GH_ORG)).reply(200, { ...BASIC_BUILD_INFO, username: 'bad' });
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_INFO_INVALID_GH_REPO)).reply(200, { ...BASIC_BUILD_INFO, reponame: 'bad' });
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_INFO_INVALID_GH_ORG)).reply(200, { ...BASIC_BUILD_INFO, organization: { name: 'bad' } });
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_INFO_INVALID_GH_REPO)).reply(200, { ...BASIC_BUILD_INFO, project: { name: 'bad' } });
|
||||
|
||||
// PIPELINE INFO errors
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.PIPELINE_INFO_ERROR)).reply(200, { ...BASIC_BUILD_INFO, pipeline: { id: PipelineIds.PIPELINE_INFO_ERROR } });
|
||||
circleCiApi.get(pipelineInfoUrl(PipelineIds.PIPELINE_INFO_ERROR)).replyWithError('PIPELINE_INFO_ERROR');
|
||||
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.PIPELINE_INFO_404)).reply(200, { ...BASIC_BUILD_INFO, pipeline: { id: PipelineIds.PIPELINE_INFO_404 } });
|
||||
circleCiApi.get(pipelineInfoUrl(PipelineIds.PIPELINE_INFO_ERROR)).reply(404, 'PIPELINE_INFO_404');
|
||||
|
||||
// CHANGED FILE errors
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.CHANGED_FILES_ERROR)).reply(200, buildInfo(PrNums.CHANGED_FILES_ERROR));
|
||||
setUpCircleCiApiForBuild(BuildNums.CHANGED_FILES_ERROR, PipelineIds.CHANGED_FILES_ERROR, PrNums.CHANGED_FILES_ERROR);
|
||||
githubApi.get(getFilesUrl(PrNums.CHANGED_FILES_ERROR)).replyWithError('CHANGED_FILES_ERROR');
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.CHANGED_FILES_404)).reply(200, buildInfo(PrNums.CHANGED_FILES_404));
|
||||
setUpCircleCiApiForBuild(BuildNums.CHANGED_FILES_404, PipelineIds.CHANGED_FILES_404, PrNums.CHANGED_FILES_404);
|
||||
githubApi.get(getFilesUrl(PrNums.CHANGED_FILES_404)).reply(404, 'CHANGED_FILES_404');
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.CHANGED_FILES_NONE)).reply(200, buildInfo(PrNums.CHANGED_FILES_NONE));
|
||||
setUpCircleCiApiForBuild(BuildNums.CHANGED_FILES_NONE, PipelineIds.CHANGED_FILES_NONE, PrNums.CHANGED_FILES_NONE);
|
||||
githubApi.get(getFilesUrl(PrNums.CHANGED_FILES_NONE)).reply(200, []);
|
||||
|
||||
// ARTIFACT URL errors
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_ARTIFACTS_ERROR)).reply(200, buildInfo(PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER));
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_ARTIFACTS_ERROR)).reply(200, BASIC_BUILD_INFO);
|
||||
circleCiApi.get(buildArtifactsUrl(BuildNums.BUILD_ARTIFACTS_ERROR)).replyWithError('BUILD_ARTIFACTS_ERROR');
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_ARTIFACTS_404)).reply(200, buildInfo(PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER));
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_ARTIFACTS_404)).reply(200, BASIC_BUILD_INFO);
|
||||
circleCiApi.get(buildArtifactsUrl(BuildNums.BUILD_ARTIFACTS_404)).reply(404, 'BUILD_ARTIFACTS_ERROR');
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_ARTIFACTS_EMPTY)).reply(200, buildInfo(PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER));
|
||||
circleCiApi.get(buildArtifactsUrl(BuildNums.BUILD_ARTIFACTS_EMPTY)).reply(200, []);
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_ARTIFACTS_MISSING)).reply(200, buildInfo(PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER));
|
||||
circleCiApi.get(buildArtifactsUrl(BuildNums.BUILD_ARTIFACTS_MISSING)).reply(200, [ARTIFACT_1, ARTIFACT_2, ARTIFACT_3]);
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_ARTIFACTS_EMPTY)).reply(200, BASIC_BUILD_INFO);
|
||||
circleCiApi.get(buildArtifactsUrl(BuildNums.BUILD_ARTIFACTS_EMPTY)).reply(200, { items: [] });
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.BUILD_ARTIFACTS_MISSING)).reply(200, BASIC_BUILD_INFO);
|
||||
circleCiApi.get(buildArtifactsUrl(BuildNums.BUILD_ARTIFACTS_MISSING)).reply(200, { items: [ARTIFACT_1, ARTIFACT_2, ARTIFACT_3] });
|
||||
|
||||
// ARTIFACT DOWNLOAD errors
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.DOWNLOAD_ARTIFACT_ERROR)).reply(200, buildInfo(PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER));
|
||||
circleCiApi.get(buildArtifactsUrl(BuildNums.DOWNLOAD_ARTIFACT_ERROR)).reply(200, [ARTIFACT_ERROR]);
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.DOWNLOAD_ARTIFACT_ERROR)).reply(200, BASIC_BUILD_INFO);
|
||||
circleCiApi.get(buildArtifactsUrl(BuildNums.DOWNLOAD_ARTIFACT_ERROR)).reply(200, { items: [ARTIFACT_ERROR] });
|
||||
circleCiApi.get(ARTIFACT_ERROR._urlPath).replyWithError(ARTIFACT_ERROR._urlPath);
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.DOWNLOAD_ARTIFACT_404)).reply(200, buildInfo(PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER));
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.DOWNLOAD_ARTIFACT_404)).reply(200, BASIC_BUILD_INFO);
|
||||
circleCiApi.get(buildArtifactsUrl(BuildNums.DOWNLOAD_ARTIFACT_404)).reply(200, [ARTIFACT_404]);
|
||||
circleCiApi.get(ARTIFACT_ERROR._urlPath).reply(404, ARTIFACT_ERROR._urlPath);
|
||||
|
||||
// TRUST CHECK errors
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.TRUST_CHECK_ERROR)).reply(200, buildInfo(PrNums.TRUST_CHECK_ERROR));
|
||||
setUpCircleCiApiForBuild(BuildNums.TRUST_CHECK_ERROR, PipelineIds.TRUST_CHECK_ERROR, PrNums.TRUST_CHECK_ERROR);
|
||||
githubApi.get(getFilesUrl(PrNums.TRUST_CHECK_ERROR)).reply(200, [{ filename: 'aio/a' }]);
|
||||
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_ERROR)).reply(200, [ARTIFACT_VALID_TRUSTED_USER]);
|
||||
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_ERROR)).reply(200, { items: [ARTIFACT_VALID_TRUSTED_USER] });
|
||||
githubApi.get(getIssueUrl(PrNums.TRUST_CHECK_ERROR)).replyWithError('TRUST_CHECK_ERROR');
|
||||
|
||||
// ACTIVE TRUSTED USER response
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER)).reply(200, BASIC_BUILD_INFO);
|
||||
githubApi.get(getFilesUrl(PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER)).reply(200, [{ filename: 'aio/a' }]);
|
||||
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER)).reply(200, [ARTIFACT_VALID_TRUSTED_USER]);
|
||||
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER)).reply(200, { items: [ARTIFACT_VALID_TRUSTED_USER] });
|
||||
circleCiApi.get(ARTIFACT_VALID_TRUSTED_USER._urlPath).reply(200, createArchive(BuildNums.TRUST_CHECK_ACTIVE_TRUSTED_USER, PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER, SHA));
|
||||
githubApi.get(getIssueUrl(PrNums.TRUST_CHECK_ACTIVE_TRUSTED_USER)).reply(200, ISSUE_INFO_ACTIVE_TRUSTED_USER);
|
||||
githubApi.get(getTeamMembershipUrl(0, ACTIVE_TRUSTED_USER)).reply(200, ACTIVE_STATE);
|
||||
@@ -143,7 +166,7 @@ githubApi.get(getTeamMembershipUrl(0, ACTIVE_TRUSTED_USER)).reply(200, ACTIVE_ST
|
||||
// TRUSTED LABEL response
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.TRUST_CHECK_TRUSTED_LABEL)).reply(200, BASIC_BUILD_INFO);
|
||||
githubApi.get(getFilesUrl(PrNums.TRUST_CHECK_TRUSTED_LABEL)).reply(200, [{ filename: 'aio/a' }]);
|
||||
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_TRUSTED_LABEL)).reply(200, [ARTIFACT_VALID_TRUSTED_LABEL]);
|
||||
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_TRUSTED_LABEL)).reply(200, { items: [ARTIFACT_VALID_TRUSTED_LABEL] });
|
||||
circleCiApi.get(ARTIFACT_VALID_TRUSTED_LABEL._urlPath).reply(200, createArchive(BuildNums.TRUST_CHECK_TRUSTED_LABEL, PrNums.TRUST_CHECK_TRUSTED_LABEL, SHA));
|
||||
githubApi.get(getIssueUrl(PrNums.TRUST_CHECK_TRUSTED_LABEL)).reply(200, ISSUE_INFO_TRUSTED_LABEL);
|
||||
githubApi.get(getTeamMembershipUrl(0, ACTIVE_TRUSTED_USER)).reply(200, ACTIVE_STATE);
|
||||
@@ -151,14 +174,14 @@ githubApi.get(getTeamMembershipUrl(0, ACTIVE_TRUSTED_USER)).reply(200, ACTIVE_ST
|
||||
// INACTIVE TRUSTED USER response
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.TRUST_CHECK_INACTIVE_TRUSTED_USER)).reply(200, BASIC_BUILD_INFO);
|
||||
githubApi.get(getFilesUrl(PrNums.TRUST_CHECK_INACTIVE_TRUSTED_USER)).reply(200, [{ filename: 'aio/a' }]);
|
||||
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_INACTIVE_TRUSTED_USER)).reply(200, [ARTIFACT_VALID_TRUSTED_USER]);
|
||||
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_INACTIVE_TRUSTED_USER)).reply(200, { items: [ARTIFACT_VALID_TRUSTED_USER] });
|
||||
githubApi.get(getIssueUrl(PrNums.TRUST_CHECK_INACTIVE_TRUSTED_USER)).reply(200, ISSUE_INFO_INACTIVE_TRUSTED_USER);
|
||||
githubApi.get(getTeamMembershipUrl(0, INACTIVE_TRUSTED_USER)).reply(200, INACTIVE_STATE);
|
||||
|
||||
// UNTRUSTED reponse
|
||||
circleCiApi.get(buildInfoUrl(BuildNums.TRUST_CHECK_UNTRUSTED)).reply(200, buildInfo(PrNums.TRUST_CHECK_UNTRUSTED));
|
||||
setUpCircleCiApiForBuild(BuildNums.TRUST_CHECK_UNTRUSTED, PipelineIds.TRUST_CHECK_UNTRUSTED, PrNums.TRUST_CHECK_UNTRUSTED);
|
||||
githubApi.get(getFilesUrl(PrNums.TRUST_CHECK_UNTRUSTED)).reply(200, [{ filename: 'aio/a' }]);
|
||||
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_UNTRUSTED)).reply(200, [ARTIFACT_VALID_UNTRUSTED]);
|
||||
circleCiApi.get(buildArtifactsUrl(BuildNums.TRUST_CHECK_UNTRUSTED)).reply(200, { items: [ARTIFACT_VALID_UNTRUSTED] });
|
||||
circleCiApi.get(ARTIFACT_VALID_UNTRUSTED._urlPath).reply(200, createArchive(BuildNums.TRUST_CHECK_UNTRUSTED, PrNums.TRUST_CHECK_UNTRUSTED, SHA));
|
||||
githubApi.get(getIssueUrl(PrNums.TRUST_CHECK_UNTRUSTED)).reply(200, ISSUE_INFO_UNTRUSTED);
|
||||
githubApi.get(getTeamMembershipUrl(0, UNTRUSTED_USER)).reply(404);
|
||||
|
||||
@@ -145,13 +145,11 @@ describe('preview-server', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should respond with 500 if the CircleCI API request errors', async () => {
|
||||
it('should respond with 500 if any of the CircleCI API requests errors', async () => {
|
||||
await curl(payload(BuildNums.BUILD_INFO_ERROR)).then(h.verifyResponse(500));
|
||||
await curl(payload(BuildNums.BUILD_INFO_404)).then(h.verifyResponse(500));
|
||||
});
|
||||
|
||||
it('should respond with 204 if the build on CircleCI failed', async () => {
|
||||
await curl(payload(BuildNums.BUILD_INFO_BUILD_FAILED)).then(h.verifyResponse(204));
|
||||
await curl(payload(BuildNums.PIPELINE_INFO_ERROR)).then(h.verifyResponse(500));
|
||||
await curl(payload(BuildNums.PIPELINE_INFO_404)).then(h.verifyResponse(500));
|
||||
});
|
||||
|
||||
it('should respond with 500 if the github org from CircleCI does not match what is configured', async () => {
|
||||
|
||||
@@ -49,6 +49,6 @@
|
||||
"supertest": "^4.0.2",
|
||||
"tslint": "^6.1.3",
|
||||
"tslint-jasmine-noSkipOrFocus": "^1.0.9",
|
||||
"typescript": "~4.6.2"
|
||||
"typescript": "~4.7.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,8 @@ import {CircleCiApi} from '../../lib/common/circle-ci-api';
|
||||
const ORG = 'testorg';
|
||||
const REPO = 'testrepo';
|
||||
const TOKEN = 'xxxx';
|
||||
const BASE_URL = `https://circleci.com/api/v2/project/gh/${ORG}/${REPO}`;
|
||||
const BASE_BUILD_URL = `https://circleci.com/api/v2/project/gh/${ORG}/${REPO}`;
|
||||
const BASE_PIPELINE_URL = 'https://circleci.com/api/v2/pipeline';
|
||||
|
||||
describe('CircleCIApi', () => {
|
||||
describe('constructor()', () => {
|
||||
@@ -27,11 +28,11 @@ describe('CircleCIApi', () => {
|
||||
describe('fetchFromCircleCI', () => {
|
||||
it('should include the authentication token in the headers on every request', async () => {
|
||||
const api = new CircleCiApi(ORG, REPO, TOKEN);
|
||||
const request = nock(BASE_URL)
|
||||
const request = nock(BASE_BUILD_URL)
|
||||
.get('/')
|
||||
.matchHeader('Circle-Token', TOKEN)
|
||||
.reply(200);
|
||||
await api.fetchFromCircleCi(`${BASE_URL}/`);
|
||||
await api.fetchFromCircleCi(`${BASE_BUILD_URL}/`);
|
||||
request.done();
|
||||
})
|
||||
})
|
||||
@@ -42,7 +43,7 @@ describe('CircleCIApi', () => {
|
||||
const buildNum = 12345;
|
||||
const expectedBuildInfo: any = { org: ORG, repo: REPO, build_num: buildNum };
|
||||
|
||||
const request = nock(BASE_URL)
|
||||
const request = nock(BASE_BUILD_URL)
|
||||
.get(`/job/${buildNum}`)
|
||||
.reply(200, expectedBuildInfo);
|
||||
|
||||
@@ -55,17 +56,17 @@ describe('CircleCIApi', () => {
|
||||
const api = new CircleCiApi(ORG, REPO, TOKEN);
|
||||
const buildNum = 12345;
|
||||
const errorMessage = 'Invalid request';
|
||||
const request = nock(BASE_URL).get(`/job/${buildNum}`);
|
||||
const request = nock(BASE_BUILD_URL).get(`/job/${buildNum}`);
|
||||
|
||||
request.replyWithError(errorMessage);
|
||||
await expectAsync(api.getBuildInfo(buildNum)).toBeRejectedWithError(
|
||||
`CircleCI build info request failed ` +
|
||||
`(request to ${BASE_URL}/job/${buildNum} failed, reason: ${errorMessage})`);
|
||||
`(request to ${BASE_BUILD_URL}/job/${buildNum} failed, reason: ${errorMessage})`);
|
||||
|
||||
request.reply(404, errorMessage);
|
||||
await expectAsync(api.getBuildInfo(buildNum)).toBeRejectedWithError(
|
||||
`CircleCI build info request failed ` +
|
||||
`(request to ${BASE_URL}/job/${buildNum} failed, reason: ${errorMessage})`);
|
||||
`(request to ${BASE_BUILD_URL}/job/${buildNum} failed, reason: ${errorMessage})`);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -76,7 +77,7 @@ describe('CircleCIApi', () => {
|
||||
const artifact0: any = { path: 'some/path/0', url: 'https://url/0' };
|
||||
const artifact1: any = { path: 'some/path/1', url: 'https://url/1' };
|
||||
const artifact2: any = { path: 'some/path/2', url: 'https://url/2' };
|
||||
const request = nock(BASE_URL)
|
||||
const request = nock(BASE_BUILD_URL)
|
||||
.get(`/${buildNum}/artifacts`)
|
||||
.reply(200, {items: [artifact0, artifact1, artifact2]});
|
||||
|
||||
@@ -89,17 +90,17 @@ describe('CircleCIApi', () => {
|
||||
const api = new CircleCiApi(ORG, REPO, TOKEN);
|
||||
const buildNum = 12345;
|
||||
const errorMessage = 'Invalid request';
|
||||
const request = nock(BASE_URL).get(`/${buildNum}/artifacts`);
|
||||
const request = nock(BASE_BUILD_URL).get(`/${buildNum}/artifacts`);
|
||||
|
||||
request.replyWithError(errorMessage);
|
||||
await expectAsync(api.getBuildArtifactUrl(buildNum, 'some/path/1')).toBeRejectedWithError(
|
||||
`CircleCI artifact URL request failed ` +
|
||||
`(request to ${BASE_URL}/${buildNum}/artifacts failed, reason: ${errorMessage})`);
|
||||
`(request to ${BASE_BUILD_URL}/${buildNum}/artifacts failed, reason: ${errorMessage})`);
|
||||
|
||||
request.reply(404, errorMessage);
|
||||
await expectAsync(api.getBuildArtifactUrl(buildNum, 'some/path/1')).toBeRejectedWithError(
|
||||
`CircleCI artifact URL request failed ` +
|
||||
`(request to ${BASE_URL}/${buildNum}/artifacts failed, reason: ${errorMessage})`);
|
||||
`(request to ${BASE_BUILD_URL}/${buildNum}/artifacts failed, reason: ${errorMessage})`);
|
||||
});
|
||||
|
||||
it('should throw an error if the response does not contain the specified artifact', async () => {
|
||||
@@ -108,7 +109,7 @@ describe('CircleCIApi', () => {
|
||||
const artifact0: any = { path: 'some/path/0', url: 'https://url/0' };
|
||||
const artifact1: any = { path: 'some/path/1', url: 'https://url/1' };
|
||||
const artifact2: any = { path: 'some/path/2', url: 'https://url/2' };
|
||||
nock(BASE_URL)
|
||||
nock(BASE_BUILD_URL)
|
||||
.get(`/${buildNum}/artifacts`)
|
||||
.reply(200, {items: [artifact0, artifact1, artifact2]});
|
||||
|
||||
@@ -117,4 +118,37 @@ describe('CircleCIApi', () => {
|
||||
`(Missing artifact (some/path/3) for CircleCI build: ${buildNum})`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getPipelineInfo', () => {
|
||||
it('should make a request to the CircleCI API for the given pipeline ID', async () => {
|
||||
const api = new CircleCiApi(ORG, REPO, TOKEN);
|
||||
const pipelineId = 'a1-b2-c3';
|
||||
const expectedPipelineInfo: any = { org: ORG, repo: REPO, pipeline_id: pipelineId };
|
||||
|
||||
const request = nock(BASE_PIPELINE_URL)
|
||||
.get(`/${pipelineId}`)
|
||||
.reply(200, expectedPipelineInfo);
|
||||
|
||||
const pipelineInfo = await api.getPipelineInfo(pipelineId);
|
||||
expect(pipelineInfo).toEqual(expectedPipelineInfo);
|
||||
request.done();
|
||||
});
|
||||
|
||||
it('should throw an error if the request fails', async () => {
|
||||
const api = new CircleCiApi(ORG, REPO, TOKEN);
|
||||
const pipelineId = 'a1-b2-c3';
|
||||
const errorMessage = 'Invalid request';
|
||||
const request = nock(BASE_PIPELINE_URL).get(`/${pipelineId}`);
|
||||
|
||||
request.replyWithError(errorMessage);
|
||||
await expectAsync(api.getPipelineInfo(pipelineId)).toBeRejectedWithError(
|
||||
`CircleCI pipeline info request failed ` +
|
||||
`(request to ${BASE_PIPELINE_URL}/${pipelineId} failed, reason: ${errorMessage})`);
|
||||
|
||||
request.reply(404, errorMessage);
|
||||
await expectAsync(api.getPipelineInfo(pipelineId)).toBeRejectedWithError(
|
||||
`CircleCI pipeline info request failed ` +
|
||||
`(request to ${BASE_PIPELINE_URL}/${pipelineId} failed, reason: ${errorMessage})`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+18
-18
@@ -1,7 +1,7 @@
|
||||
import * as fs from 'fs';
|
||||
import * as nock from 'nock';
|
||||
import {resolve as resolvePath} from 'path';
|
||||
import {BuildInfo, CircleCiApi} from '../../lib/common/circle-ci-api';
|
||||
import {BuildInfo, CircleCiApi, PipelineInfo} from '../../lib/common/circle-ci-api';
|
||||
import {Logger} from '../../lib/common/utils';
|
||||
import {BuildRetriever} from '../../lib/preview-server/build-retriever';
|
||||
|
||||
@@ -13,6 +13,7 @@ describe('BuildRetriever', () => {
|
||||
|
||||
let api: CircleCiApi;
|
||||
let BUILD_INFO: BuildInfo;
|
||||
let PIPELINE_INFO: PipelineInfo;
|
||||
let WRITEFILE_RESULT: any;
|
||||
let writeFileSpy: jasmine.Spy;
|
||||
let EXISTS_RESULT: boolean;
|
||||
@@ -21,18 +22,23 @@ describe('BuildRetriever', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
BUILD_INFO = {
|
||||
branch: 'pull/777',
|
||||
build_num: 12345,
|
||||
failed: false,
|
||||
has_artifacts: true,
|
||||
outcome: 'success',
|
||||
reponame: 'REPO',
|
||||
username: 'ORG',
|
||||
vcs_revision: 'COMMIT',
|
||||
number: 12345,
|
||||
name: 'test_job',
|
||||
organization: {name: 'ORG'},
|
||||
project: {name: 'REPO'},
|
||||
pipeline: {id: 'test_pipeline'},
|
||||
};
|
||||
PIPELINE_INFO = {
|
||||
id: 'test_pipeline',
|
||||
vcs: {
|
||||
review_id: '777',
|
||||
revision: 'COMMIT',
|
||||
},
|
||||
};
|
||||
|
||||
api = new CircleCiApi('ORG', 'REPO', 'TOKEN');
|
||||
spyOn(api, 'getBuildInfo').and.resolveTo(BUILD_INFO);
|
||||
spyOn(api, 'getPipelineInfo').and.resolveTo(PIPELINE_INFO);
|
||||
getBuildArtifactUrlSpy = spyOn(api, 'getBuildArtifactUrl').and.resolveTo(BASE_URL + ARTIFACT_PATH);
|
||||
|
||||
WRITEFILE_RESULT = undefined;
|
||||
@@ -65,18 +71,12 @@ describe('BuildRetriever', () => {
|
||||
|
||||
|
||||
describe('getGithubInfo', () => {
|
||||
it('should request the info from CircleCI', async () => {
|
||||
it('should request the build and pipeline info from CircleCI', async () => {
|
||||
const retriever = new BuildRetriever(api, MAX_DOWNLOAD_SIZE, DOWNLOAD_DIR);
|
||||
const info = await retriever.getGithubInfo(12345);
|
||||
expect(api.getBuildInfo).toHaveBeenCalledWith(12345);
|
||||
expect(info).toEqual({org: 'ORG', pr: 777, repo: 'REPO', sha: 'COMMIT', success: true});
|
||||
});
|
||||
|
||||
it('should error if it is not possible to extract the PR number from the branch', async () => {
|
||||
BUILD_INFO.branch = 'master';
|
||||
const retriever = new BuildRetriever(api, MAX_DOWNLOAD_SIZE, DOWNLOAD_DIR);
|
||||
|
||||
await expectAsync(retriever.getGithubInfo(12345)).toBeRejectedWithError('No PR found in branch field: master');
|
||||
expect(api.getPipelineInfo).toHaveBeenCalledWith('test_pipeline');
|
||||
expect(info).toEqual({org: 'ORG', pr: 777, repo: 'REPO', sha: 'COMMIT'});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
-10
@@ -410,7 +410,6 @@ describe('PreviewServerFactory', () => {
|
||||
pr: PR,
|
||||
repo: defaultConfig.githubRepo,
|
||||
sha: SHA,
|
||||
success: true,
|
||||
};
|
||||
BASIC_PAYLOAD = { payload: { build_num: BUILD_NUM, build_parameters: { CIRCLE_JOB: 'aio_preview' } } };
|
||||
AFFECTS_SIGNIFICANT_FILES = true;
|
||||
@@ -481,15 +480,6 @@ describe('PreviewServerFactory', () => {
|
||||
await agent.post(URL).send(BASIC_PAYLOAD).expect(202);
|
||||
});
|
||||
|
||||
it('should not create a preview if the build was not successful', async () => {
|
||||
BUILD_INFO.success = false;
|
||||
await agent.post(URL).send(BASIC_PAYLOAD).expect(204);
|
||||
expect(getGithubInfoSpy).toHaveBeenCalledWith(BUILD_NUM);
|
||||
expect(downloadBuildArtifactSpy).not.toHaveBeenCalled();
|
||||
expect(getPrIsTrustedSpy).not.toHaveBeenCalled();
|
||||
expect(createBuildSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should fail if the CircleCI request fails', async () => {
|
||||
// Note it is important to put the `reject` into `and.callFake`;
|
||||
// If you just `and.returnValue` the rejected promise
|
||||
|
||||
@@ -2563,10 +2563,10 @@ typedarray-to-buffer@^3.1.5:
|
||||
dependencies:
|
||||
is-typedarray "^1.0.0"
|
||||
|
||||
typescript@~4.6.2:
|
||||
version "4.6.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4"
|
||||
integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==
|
||||
typescript@~4.7.2:
|
||||
version "4.7.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.2.tgz#1f9aa2ceb9af87cca227813b4310fff0b51593c4"
|
||||
integrity sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A==
|
||||
|
||||
undefsafe@^2.0.2:
|
||||
version "2.0.2"
|
||||
|
||||
@@ -6,7 +6,7 @@ Assuming you have cloned the repository containing the preview server code (as d
|
||||
[here](vm-setup--create-docker-image.md)), you can use the `update-preview-server.sh` script on the
|
||||
VM host to update the preview server based on changes in the source code.
|
||||
|
||||
The script will pull the latest changes from the origin's master branch and examine if there have
|
||||
The script will pull the latest changes from the origin's main branch and examine if there have
|
||||
been any changes in files inside the preview server source code directory (see below). If there are,
|
||||
it will create a new image and verify that it works as expected. Finally, it will stop and remove
|
||||
the old docker container and image, create a new container based on the new image and start it.
|
||||
|
||||
@@ -25,8 +25,8 @@ readonly CONTAINER_NAME=aio
|
||||
readonly lastDeployedCommit=$(git rev-parse HEAD)
|
||||
echo "Currently at commit $lastDeployedCommit."
|
||||
|
||||
# Pull latest master from origin.
|
||||
git pull origin master
|
||||
# Pull latest main from origin.
|
||||
git pull origin main
|
||||
|
||||
# Do not update the server unless files inside `aio-builds-setup/` have changed
|
||||
# or the last attempt failed (identified by the provisional image still being around).
|
||||
@@ -67,5 +67,9 @@ readonly CONTAINER_NAME=aio
|
||||
--volume $HOST_LOGS_DIR:/var/log/aio \
|
||||
"$LATEST_IMAGE_NAME"
|
||||
|
||||
# Clean up unused docker containers and images (to reclaim space).
|
||||
sudo docker container prune --force
|
||||
sudo docker image prune --all --force
|
||||
|
||||
echo "The new docker image has been successfully deployed."
|
||||
)
|
||||
|
||||
@@ -10,7 +10,7 @@ Install the CLI using the `npm` package manager:
|
||||
|
||||
<code-example format="shell" language="shell">
|
||||
|
||||
npm install -g @angular/cli
|
||||
npm install -g @angular/cli<aio-angular-dist-tag class="pln"></aio-angular-dist-tag>
|
||||
|
||||
</code-example>
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
@name `inject()` must be called from an injection context
|
||||
@category runtime
|
||||
@shortDescription `inject()` must be called from an injection context (a constructor, a factory function or a field initializer)
|
||||
|
||||
@description
|
||||
You see this error when you try to use the `inject()` function outside of the allowed injection context. The injection context is available during the class creation and initialization.
|
||||
|
||||
In practice the `inject()` calls are allowed in a constructor, a constructor parameter and a field initializer:
|
||||
|
||||
```typescript
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class Car {
|
||||
radio: Radio|undefined;
|
||||
|
||||
// OK: field initializer
|
||||
spareTyre = inject(Tyre);
|
||||
|
||||
constructor() {
|
||||
// OK: constructor body
|
||||
this.radio = inject(Radio);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
It is also legal to call `inject` from a provider's factory:
|
||||
|
||||
```typescript
|
||||
providers: [
|
||||
{provide: Car, useFactory: () => {
|
||||
// OK: a class factory
|
||||
const engine = inject(Engine);
|
||||
return new Car(engine);
|
||||
}}
|
||||
]
|
||||
```
|
||||
|
||||
Calls to the `inject()` function outside of the class creation context will result in error. Most notably, calls to `inject()` are disallowed after a class instance was created, in methods (including lifecycle hooks):
|
||||
|
||||
```typescript
|
||||
@Component({ ... })
|
||||
export class CarComponent {
|
||||
ngOnInit() {
|
||||
// ERROR: too late, the component instance was already created
|
||||
const engine = inject(Engine);
|
||||
engine.start();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@debugging
|
||||
|
||||
Work backwards from the stack trace of the error to identify a place where the disallowed call to `inject()` is located.
|
||||
|
||||
To fix the error move the `inject()` call to an allowed place (usually a class constructor or a field initializer).
|
||||
|
||||
<!-- links -->
|
||||
|
||||
<!-- external links -->
|
||||
|
||||
<!-- end links -->
|
||||
|
||||
@reviewed 2022-05-27
|
||||
@@ -1,20 +1,25 @@
|
||||
@name Pipe Not Found
|
||||
@category runtime
|
||||
@videoUrl https://www.youtube.com/embed/maI2u6Sxk9M
|
||||
@videoCaption Note: The video predates standalone pipes, please refer to additional instructions below if you use standalone pipes.
|
||||
@shortDescription Pipe not found!
|
||||
|
||||
@description
|
||||
Angular can't find a pipe with this name.
|
||||
|
||||
The pipe referenced in the template has not been named or declared properly.
|
||||
A [pipe](guide/pipes) must be either declared or imported in the `NgModule` where it is used, and the name used in a template must match the name defined in the pipe decorator.
|
||||
|
||||
In order for a [pipe](guide/pipes) to be used:
|
||||
- it must be declared as a part of an `NgModule` (added to the `declarations` array) or marked as standalone (by adding the `standalone: true` flag to the Pipe decorator).
|
||||
- it must be imported in an `NgModule` or a standalone component where it is used.
|
||||
- the name used in a template must match the name defined in the Pipe decorator.
|
||||
|
||||
@debugging
|
||||
Use the pipe name to trace the templates or modules where this pipe is declared and used.
|
||||
Use the pipe name to trace where the pipe is declared and used.
|
||||
|
||||
To resolve this error, ensure that:
|
||||
|
||||
* A local custom pipe is uniquely named in the pipe's decorator, and declared in the `NgModule`, or
|
||||
* A pipe from another `NgModule` is added to the imports of the `NgModule` where it is used
|
||||
- If the pipe is local to the `NgModule`, it is uniquely named in the pipe's decorator and declared in the `NgModule`.
|
||||
- If the pipe is standalone or from another `NgModule`, it is added to the `imports` field of the current `NgModule` or standalone component.
|
||||
|
||||
If you recently added an import or declaration, you may need to restart your server to see these changes.
|
||||
|
||||
@@ -24,4 +29,4 @@ If you recently added an import or declaration, you may need to restart your ser
|
||||
|
||||
<!-- end links -->
|
||||
|
||||
@reviewed 2022-02-28
|
||||
@reviewed 2022-05-22
|
||||
|
||||
@@ -7,7 +7,7 @@ One or more elements cannot be resolved during compilation because the element i
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
This is the compiler equivalent of a common runtime error `NG0304: '${tagName}' is not a known element: …`.
|
||||
This is the compiler equivalent of a common runtime error `NG0304: '${tagName}' is not a known element: ...`.
|
||||
|
||||
</div>
|
||||
|
||||
@@ -15,7 +15,8 @@ This is the compiler equivalent of a common runtime error `NG0304: '${tagName}'
|
||||
Use the element name in the error to find the file(s) where the element is being used.
|
||||
|
||||
Check that the name and selector are correct.
|
||||
If the component is from a different module or import, check that the component is exported from its origin module and imported into the correct `*.modules.ts` file, and declared in the imports list.
|
||||
|
||||
Make sure that the component is correctly imported inside your NgModule or standalone component, by checking its presence in the `imports` field. If the component is declared in an NgModule (meaning that it is not standalone) make sure that it is exported correctly from it, by checking its presence in the `exports` field.
|
||||
|
||||
When using custom elements or web components, ensure that you add [`CUSTOM_ELEMENTS_SCHEMA`](api/core/CUSTOM_ELEMENTS_SCHEMA) to the application module.
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# boilerplate files
|
||||
**/.vscode/
|
||||
**/src/environments/environment.prod.ts
|
||||
**/src/environments/environment.ts
|
||||
**/src/assets/.gitkeep
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"experimentalDecorators": true,
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"target": "es2017",
|
||||
"target": "es2020",
|
||||
"module": "es2020",
|
||||
"lib": [
|
||||
"es2020",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// #docplaster …
|
||||
// #docplaster ...
|
||||
// #docregion webpack-config
|
||||
import linkerPlugin from '@angular/compiler-cli/linker/babel';
|
||||
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
import { Hero } from './hero';
|
||||
|
||||
export const HEROES: Hero[] = [
|
||||
{ id: 11, name: 'Dr Nice' },
|
||||
{ id: 12, name: 'Narco' },
|
||||
{ id: 12, name: 'Dr. Nice' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' },
|
||||
{ id: 15, name: 'Magneta' },
|
||||
{ id: 16, name: 'RubberMan' },
|
||||
{ id: 17, name: 'Dynama' },
|
||||
{ id: 18, name: 'Dr IQ' },
|
||||
{ id: 18, name: 'Dr. IQ' },
|
||||
{ id: 19, name: 'Magma' },
|
||||
{ id: 20, name: 'Tornado' }
|
||||
];
|
||||
|
||||
@@ -69,7 +69,4 @@
|
||||
<!-- #enddocregion style-delegation -->
|
||||
</div>
|
||||
|
||||
<!-- #docregion attribute-decorator -->
|
||||
<app-my-input-with-attribute-decorator type="number"></app-my-input-with-attribute-decorator>
|
||||
<!-- #enddocregion attribute-decorator -->
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import { Component } from '@angular/core';
|
||||
export class VoteTakerComponent {
|
||||
agreed = 0;
|
||||
disagreed = 0;
|
||||
voters = ['Narco', 'Celeritas', 'Bombasto'];
|
||||
voters = ['Dr IQ', 'Celeritas', 'Bombasto'];
|
||||
|
||||
onVoted(agreed: boolean) {
|
||||
if (agreed) {
|
||||
|
||||
@@ -1,42 +1,7 @@
|
||||
import { Component, Directive, Input, TemplateRef, ContentChild, HostBinding, HostListener } from '@angular/core';
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html'
|
||||
})
|
||||
export class AppComponent {}
|
||||
|
||||
@Directive({
|
||||
selector: 'button[appExampleZippyToggle]',
|
||||
})
|
||||
export class ZippyToggleDirective {
|
||||
@HostBinding('attr.aria-expanded') ariaExpanded = this.zippy.expanded;
|
||||
@HostBinding('attr.aria-controls') ariaControls = this.zippy.contentId;
|
||||
@HostListener('click') toggleZippy() {
|
||||
this.zippy.expanded = !this.zippy.expanded;
|
||||
}
|
||||
constructor(public zippy: ZippyComponent) {}
|
||||
}
|
||||
|
||||
// #docregion zippycontentdirective
|
||||
@Directive({
|
||||
selector: '[appExampleZippyContent]'
|
||||
})
|
||||
export class ZippyContentDirective {
|
||||
constructor(public templateRef: TemplateRef<unknown>) {}
|
||||
}
|
||||
// #enddocregion zippycontentdirective
|
||||
|
||||
let nextId = 0;
|
||||
|
||||
@Component({
|
||||
selector: 'app-example-zippy',
|
||||
templateUrl: 'example-zippy.template.html',
|
||||
})
|
||||
export class ZippyComponent {
|
||||
contentId = `zippy-${nextId++}`;
|
||||
@Input() expanded = false;
|
||||
// #docregion contentchild
|
||||
@ContentChild(ZippyContentDirective) content!: ZippyContentDirective;
|
||||
// #enddocregion contentchild
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@ import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import {
|
||||
AppComponent,
|
||||
ZippyComponent,
|
||||
ZippyContentDirective,
|
||||
ZippyToggleDirective,
|
||||
} from './app.component';
|
||||
} from './example-zippy.component';
|
||||
import { ZippyBasicComponent } from './zippy-basic/zippy-basic.component';
|
||||
import { ZippyMultislotComponent } from './zippy-multislot/zippy-multislot.component';
|
||||
import { ZippyNgprojectasComponent } from './zippy-ngprojectas/zippy-ngprojectas.component';
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Component, Directive, Input, TemplateRef, ContentChild, HostBinding, HostListener } from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
selector: 'button[appExampleZippyToggle]',
|
||||
})
|
||||
export class ZippyToggleDirective {
|
||||
@HostBinding('attr.aria-expanded') ariaExpanded = this.zippy.expanded;
|
||||
@HostBinding('attr.aria-controls') ariaControls = this.zippy.contentId;
|
||||
@HostListener('click') toggleZippy() {
|
||||
this.zippy.expanded = !this.zippy.expanded;
|
||||
}
|
||||
constructor(public zippy: ZippyComponent) {}
|
||||
}
|
||||
|
||||
let nextId = 0;
|
||||
|
||||
// #docregion zippycontentdirective
|
||||
@Directive({
|
||||
selector: '[appExampleZippyContent]'
|
||||
})
|
||||
export class ZippyContentDirective {
|
||||
constructor(public templateRef: TemplateRef<unknown>) {}
|
||||
}
|
||||
// #enddocregion zippycontentdirective
|
||||
|
||||
@Component({
|
||||
selector: 'app-example-zippy',
|
||||
templateUrl: 'example-zippy.template.html',
|
||||
})
|
||||
export class ZippyComponent {
|
||||
contentId = `zippy-${nextId++}`;
|
||||
@Input() expanded = false;
|
||||
// #docregion contentchild
|
||||
@ContentChild(ZippyContentDirective) content!: ZippyContentDirective;
|
||||
// #enddocregion contentchild
|
||||
}
|
||||
@@ -52,7 +52,7 @@ describe('Dependency Injection Tests', () => {
|
||||
});
|
||||
|
||||
it('Hero displays as expected', async () => {
|
||||
expectedMsg = 'Dr Nice';
|
||||
expectedMsg = 'Dr. Nice';
|
||||
expect(await element(by.css('#hero')).getText()).toEqual(expectedMsg);
|
||||
});
|
||||
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
import { Hero } from './hero';
|
||||
|
||||
export const HEROES: Hero[] = [
|
||||
{ id: 11, isSecret: false, name: 'Dr Nice' },
|
||||
{ id: 12, isSecret: false, name: 'Narco' },
|
||||
{ id: 12, isSecret: false, name: 'Dr. Nice' },
|
||||
{ id: 13, isSecret: false, name: 'Bombasto' },
|
||||
{ id: 14, isSecret: false, name: 'Celeritas' },
|
||||
{ id: 15, isSecret: false, name: 'Magneta' },
|
||||
|
||||
@@ -4,8 +4,8 @@ export interface Hero {
|
||||
}
|
||||
|
||||
export const HEROES: Hero[] = [
|
||||
{ id: 11, name: 'Dr Nice' },
|
||||
{ id: 12, name: 'Narco' },
|
||||
{ id: 12, name: 'Dr. Nice' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' }
|
||||
{ id: 14, name: 'Celeritas' },
|
||||
{ id: 15, name: 'Magneta' }
|
||||
];
|
||||
|
||||
@@ -28,10 +28,7 @@
|
||||
<div class="group">
|
||||
<h3>Binding to a nested component</h3>
|
||||
<h4>Custom events with EventEmitter</h4>
|
||||
<!-- #docregion event-binding-to-component -->
|
||||
<app-item-detail (deleteRequest)="deleteItem($event)" [item]="currentItem"></app-item-detail>
|
||||
<!-- #enddocregion event-binding-to-component -->
|
||||
|
||||
|
||||
<h4>Click to see event target class:</h4>
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<div class="detail">
|
||||
<p>This is the ItemDetailComponent</p>
|
||||
<!-- #docregion line-through -->
|
||||
<img src="{{itemImageUrl}}" alt="{{item.name}}" [style.display]="displayNone">
|
||||
<span [style.text-decoration]="lineThrough">{{ item.name }}
|
||||
</span>
|
||||
<button type="button" (click)="delete()">Delete</button>
|
||||
<!-- #enddocregion line-through -->
|
||||
</div>
|
||||
|
||||
@@ -15,7 +15,6 @@ export class ItemDetailComponent {
|
||||
displayNone = '';
|
||||
@Input() prefix = '';
|
||||
|
||||
// #docregion deleteRequest
|
||||
// This component makes a request but it can't actually delete a hero.
|
||||
@Output() deleteRequest = new EventEmitter<Item>();
|
||||
|
||||
@@ -24,6 +23,5 @@ export class ItemDetailComponent {
|
||||
this.displayNone = this.displayNone ? '' : 'none';
|
||||
this.lineThrough = this.lineThrough ? '' : 'line-through';
|
||||
}
|
||||
// #enddocregion deleteRequest
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ import { products } from '../products';
|
||||
})
|
||||
export class ProductListComponent {
|
||||
|
||||
products = products;
|
||||
products = [...products];
|
||||
|
||||
share() {
|
||||
window.alert('The product has been shared!');
|
||||
|
||||
@@ -10,7 +10,7 @@ import { products } from '../products';
|
||||
// #docregion on-notify
|
||||
export class ProductListComponent {
|
||||
|
||||
products = products;
|
||||
products = [...products];
|
||||
|
||||
share() {
|
||||
window.alert('The product has been shared!');
|
||||
|
||||
@@ -7,6 +7,4 @@ import { Component } from '@angular/core';
|
||||
})
|
||||
export class ShippingComponent {
|
||||
|
||||
constructor() { }
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// #docplaster
|
||||
// #docregion imports
|
||||
import { Component } from '@angular/core';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
import { CartService } from '../cart.service';
|
||||
// #enddocregion
|
||||
|
||||
@@ -11,15 +12,18 @@ import { CartService } from '../cart.service';
|
||||
styleUrls: ['./shipping.component.css']
|
||||
})
|
||||
// #docregion props
|
||||
export class ShippingComponent {
|
||||
export class ShippingComponent implements OnInit {
|
||||
|
||||
shippingCosts = this.cartService.getShippingPrices();
|
||||
shippingCosts!: Observable<{ type: string, price: number }[]>;
|
||||
// #enddocregion props
|
||||
|
||||
// #docregion inject-cart-service
|
||||
constructor(private cartService: CartService) { }
|
||||
// #enddocregion inject-cart-service
|
||||
|
||||
|
||||
// #docregion props
|
||||
|
||||
ngOnInit(): void {
|
||||
this.shippingCosts = this.cartService.getShippingPrices();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ describe('Http Tests', () => {
|
||||
describe('Heroes', () => {
|
||||
it('retrieves the list of heroes at startup', async () => {
|
||||
expect(await page.heroesListItems.count()).toBe(4);
|
||||
expect(await page.heroesListItems.get(0).getText()).toContain('Dr Nice');
|
||||
expect(await page.heroesListItems.get(0).getText()).toContain('Dr. Nice');
|
||||
await checkLogForMessage('GET "api/heroes"');
|
||||
});
|
||||
|
||||
|
||||
@@ -3,10 +3,10 @@ import { InMemoryDbService } from 'angular-in-memory-web-api';
|
||||
export class InMemoryDataService implements InMemoryDbService {
|
||||
createDb() {
|
||||
const heroes = [
|
||||
{ id: 11, name: 'Dr Nice' },
|
||||
{ id: 12, name: 'Narco' },
|
||||
{ id: 12, name: 'Dr. Nice' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' },
|
||||
{ id: 15, name: 'Magneta' },
|
||||
];
|
||||
const query = [
|
||||
{ name: '@angular/core', version: '20.1.0', description: 'angular core package' },
|
||||
|
||||
@@ -62,7 +62,7 @@ export class UploaderService {
|
||||
|
||||
case HttpEventType.UploadProgress:
|
||||
// Compute and show the % done:
|
||||
const percentDone = Math.round(100 * event.loaded / (event.total ?? 0));
|
||||
const percentDone = event.total ? Math.round(100 * event.loaded / event.total) : 0;
|
||||
return `File "${file.name}" is ${percentDone}% uploaded.`;
|
||||
|
||||
case HttpEventType.Response:
|
||||
|
||||
@@ -16,16 +16,12 @@
|
||||
|
||||
<h3>Evaluating template expressions </h3>
|
||||
<h4>Simple evaluation (to a string):</h4>
|
||||
<!-- #docregion convert-string -->
|
||||
<!-- "The sum of 1 + 1 is 2" -->
|
||||
<p>The sum of 1 + 1 is {{1 + 1}}.</p>
|
||||
<!-- #enddocregion convert-string -->
|
||||
|
||||
<h4>Evaluates using a method (also evaluates to a string):</h4>
|
||||
<!-- #docregion invoke-method -->
|
||||
<!-- "The sum of 1 + 1 is not 4" -->
|
||||
<p>The sum of 1 + 1 is not {{1 + 1 + getVal()}}.</p>
|
||||
<!-- #enddocregion invoke-method -->
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
@@ -6,8 +6,8 @@ export interface Hero {
|
||||
}
|
||||
|
||||
export const heroes: Hero[] = [
|
||||
{ id: 1, name: 'Dr Nice', emotion: 'happy' },
|
||||
{ id: 2, name: 'Narco', emotion: 'sad' },
|
||||
{ id: 1, name: 'Dr. Nice', emotion: 'happy' },
|
||||
{ id: 2, name: 'RubberMan', emotion: 'sad' },
|
||||
{ id: 3, name: 'Windstorm', emotion: 'confused' },
|
||||
{ id: 4, name: 'Magneta' }
|
||||
];
|
||||
|
||||
@@ -161,8 +161,8 @@ export function docRegionMulticastSequence(console: Console, runSequence: boolea
|
||||
// (at 2 seconds): 2nd subscribe: 2
|
||||
// (at 3 seconds): Emitting 3
|
||||
// (at 3 seconds): 1st subscribe: 3
|
||||
// (at 3 seconds): 1st sequence finished
|
||||
// (at 3 seconds): 2nd subscribe: 3
|
||||
// (at 3 seconds): 1st sequence finished
|
||||
// (at 3 seconds): 2nd sequence finished
|
||||
|
||||
// #enddocregion multicast_sequence
|
||||
|
||||
@@ -86,12 +86,14 @@ describe('typeahead', () => {
|
||||
static install(mockTime = 0): MockClock['tick'] {
|
||||
const mocked = new this(mockTime);
|
||||
|
||||
spyOn(global, 'clearInterval').and.callFake(id => mocked.clearTask(id));
|
||||
spyOn(global, 'clearTimeout').and.callFake(id => mocked.clearTask(id));
|
||||
spyOn(global, 'clearInterval').and.callFake(id => mocked.clearTask(id as MockTask['id']));
|
||||
spyOn(global, 'clearTimeout').and.callFake(id => mocked.clearTask(id as MockTask['id']));
|
||||
spyOn(global, 'setInterval').and.callFake(
|
||||
(fn, delay, ...args) => mocked.createTask(fn, delay, true, ...args));
|
||||
((fn: () => unknown, delay: number, ...args: any[]) =>
|
||||
mocked.createTask(fn, delay, true, ...args)) as typeof setInterval);
|
||||
spyOn(global, 'setTimeout').and.callFake(
|
||||
(fn, delay, ...args) => mocked.createTask(fn, delay, false, ...args));
|
||||
((fn: () => unknown, delay: number, ...args: any[]) =>
|
||||
mocked.createTask(fn, delay, false, ...args)) as typeof setTimeout);
|
||||
|
||||
spyOn(Date, 'now').and.callFake(() => mocked.now);
|
||||
|
||||
|
||||
@@ -46,27 +46,21 @@
|
||||
<hr />
|
||||
|
||||
<h2>Property binding and interpolation</h2>
|
||||
<!-- #docregion property-binding-interpolation -->
|
||||
<p><img alt="Interpolated item" src="{{itemImageUrl}}"> is the <i>interpolated</i> image.</p>
|
||||
<p><img alt="Property Bound item" [src]="itemImageUrl"> is the <i>property bound</i> image.</p>
|
||||
|
||||
<p><span>"{{interpolationTitle}}" is the <i>interpolated</i> title.</span></p>
|
||||
<p>"<span [innerHTML]="propertyTitle"></span>" is the <i>property bound</i> title.</p>
|
||||
<!-- #enddocregion property-binding-interpolation -->
|
||||
|
||||
<hr />
|
||||
|
||||
<h2>Malicious content</h2>
|
||||
|
||||
<!-- #docregion malicious-interpolated -->
|
||||
<p><span>"{{evilTitle}}" is the <i>interpolated</i> evil title.</span></p>
|
||||
<!-- #enddocregion malicious-interpolated -->
|
||||
|
||||
<!-- #docregion malicious-content -->
|
||||
<!--
|
||||
Angular generates a warning for the following line as it sanitizes them
|
||||
WARNING: sanitizing HTML stripped some content (see https://g.co/ng/security#xss).
|
||||
-->
|
||||
<p>"<span [innerHTML]="evilTitle"></span>" is the <i>property bound</i> evil title.</p>
|
||||
<!-- #enddocregion malicious-content -->
|
||||
</div>
|
||||
|
||||
@@ -13,9 +13,7 @@ export class AppComponent {
|
||||
// #docregion boolean
|
||||
isUnchanged = true;
|
||||
// #enddocregion boolean
|
||||
// #docregion directive-property
|
||||
classes = 'special';
|
||||
// #enddocregion directive-property
|
||||
// #docregion parent-data-type
|
||||
parentItem = 'lamp';
|
||||
// #enddocregion parent-data-type
|
||||
@@ -30,7 +28,5 @@ export class AppComponent {
|
||||
interpolationTitle = 'Interpolation';
|
||||
propertyTitle = 'Property binding';
|
||||
|
||||
// #docregion malicious-content
|
||||
evilTitle = 'Template <script>alert("evil never sleeps")</script> Syntax';
|
||||
// #enddocregion malicious-content
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { browser, element, by, ExpectedConditions as EC } from 'protractor';
|
||||
|
||||
const numDashboardTabs = 5;
|
||||
const numCrises = 4;
|
||||
const numHeroes = 10;
|
||||
const numHeroes = 9;
|
||||
|
||||
describe('Router', () => {
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Hero } from './hero';
|
||||
|
||||
export const HEROES: Hero[] = [
|
||||
{ id: 11, name: 'Dr Nice' },
|
||||
{ id: 12, name: 'Narco' },
|
||||
{ id: 12, name: 'Dr. Nice' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' },
|
||||
{ id: 15, name: 'Magneta' },
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
import { browser, element, by } from 'protractor';
|
||||
|
||||
describe('Set Document Title', () => {
|
||||
|
||||
beforeEach(() => browser.get(''));
|
||||
|
||||
it('should set the document title', async () => {
|
||||
const elems = await element.all(by.css('ul li a'));
|
||||
const titles = [
|
||||
'Good morning!',
|
||||
'Good afternoon!',
|
||||
'Good evening!',
|
||||
];
|
||||
|
||||
for (let i = 0; i < elems.length; i++) {
|
||||
await elems[i].click();
|
||||
expect(await browser.getTitle()).toEqual(titles[i]);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,29 +0,0 @@
|
||||
// #docplaster
|
||||
// #docregion
|
||||
// Import the native Angular services.
|
||||
import { Component } from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
template: `
|
||||
<p>
|
||||
Select a title to set on the current HTML document:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li><button type="button" (click)="setTitle('Good morning!')">Good morning</button></li>
|
||||
<li><button type="button" (click)="setTitle('Good afternoon!')">Good afternoon</button></li>
|
||||
<li><button type="button" (click)="setTitle('Good evening!')">Good evening</button></li>
|
||||
</ul>
|
||||
`,
|
||||
})
|
||||
// #docregion class
|
||||
export class AppComponent {
|
||||
public constructor(private titleService: Title) { }
|
||||
|
||||
public setTitle(newTitle: string) {
|
||||
this.titleService.setTitle(newTitle);
|
||||
}
|
||||
}
|
||||
// #enddocregion class
|
||||
@@ -1,19 +0,0 @@
|
||||
// #docregion
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule, Title } from '@angular/platform-browser';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
providers: [
|
||||
Title
|
||||
],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
export class AppModule { }
|
||||
@@ -1,22 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<base href="/">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
|
||||
<title>
|
||||
Setting The Document Title Using The Title Service
|
||||
</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>
|
||||
Setting The Document Title Using The Title Service
|
||||
</h1>
|
||||
|
||||
<app-root></app-root>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,12 +0,0 @@
|
||||
// #docregion
|
||||
import { enableProdMode } from '@angular/core';
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
|
||||
import { AppModule } from './app/app.module';
|
||||
import { environment } from './environments/environment';
|
||||
|
||||
if (environment.production) {
|
||||
enableProdMode();
|
||||
}
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"description": "Set The Document Title In Angular",
|
||||
"files": [
|
||||
"!**/*.d.ts",
|
||||
"!**/*.js",
|
||||
"!**/*.[1].*"
|
||||
],
|
||||
"file": "src/app/app.component.ts",
|
||||
"tags": [ "cookbook" ]
|
||||
}
|
||||
@@ -6,12 +6,12 @@ describe('Structural Directives', () => {
|
||||
|
||||
it('first div should show hero name with *ngIf', async () => {
|
||||
const allDivs = element.all(by.tagName('div'));
|
||||
expect(await allDivs.get(0).getText()).toEqual('Dr Nice');
|
||||
expect(await allDivs.get(0).getText()).toEqual('Dr. Nice');
|
||||
});
|
||||
|
||||
it('first li should show hero name with *ngFor', async () => {
|
||||
const allLis = element.all(by.tagName('li'));
|
||||
expect(await allLis.get(0).getText()).toEqual('Dr Nice');
|
||||
expect(await allLis.get(0).getText()).toEqual('Dr. Nice');
|
||||
});
|
||||
|
||||
it('ngSwitch have two <happy-hero> instances', async () => {
|
||||
@@ -27,11 +27,6 @@ describe('Structural Directives', () => {
|
||||
expect(await paragraph.get(0).getText()).not.toContain('I waved');
|
||||
});
|
||||
|
||||
it('should have only one "Hip!" (the other is erased)', async () => {
|
||||
const paragraph = element.all(by.cssContainingText('p', 'Hip!'));
|
||||
expect(await paragraph.count()).toEqual(1);
|
||||
});
|
||||
|
||||
it('appUnless should show 3 paragraph (A)s and (B)s at the start', async () => {
|
||||
const paragraph = element.all(by.css('p.unless'));
|
||||
expect(await paragraph.count()).toEqual(3);
|
||||
|
||||
@@ -110,15 +110,20 @@
|
||||
|
||||
<p class="code"><div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd"></p>
|
||||
<!--#docregion inside-ngfor -->
|
||||
<div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd">
|
||||
<div
|
||||
*ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById"
|
||||
[class.odd]="odd">
|
||||
({{i}}) {{hero.name}}
|
||||
</div>
|
||||
|
||||
<!--#enddocregion inside-ngfor -->
|
||||
<p class="code"><ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById"/></p>
|
||||
<!--#docregion inside-ngfor -->
|
||||
<ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById">
|
||||
<div [class.odd]="odd">({{i}}) {{hero.name}}</div>
|
||||
<ng-template ngFor let-hero [ngForOf]="heroes"
|
||||
let-i="index" let-odd="odd" [ngForTrackBy]="trackById">
|
||||
<div [class.odd]="odd">
|
||||
({{i}}) {{hero.name}}
|
||||
</div>
|
||||
</ng-template>
|
||||
<!--#enddocregion inside-ngfor -->
|
||||
|
||||
@@ -162,16 +167,6 @@
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><ng-template></h2>
|
||||
<!-- #docregion template-tag -->
|
||||
<p>Hip!</p>
|
||||
<ng-template>
|
||||
<p>Hip!</p>
|
||||
</ng-template>
|
||||
<p>Hooray!</p>
|
||||
<!-- #enddocregion template-tag -->
|
||||
|
||||
<hr>
|
||||
|
||||
<h2 id="appUnless">UnlessDirective</h2>
|
||||
<!-- #docregion toggle-info -->
|
||||
@@ -215,3 +210,7 @@
|
||||
</p>
|
||||
</ng-template>
|
||||
|
||||
<hr />
|
||||
|
||||
<h2 id="appIfLoaded">IfLoadedDirective</h2>
|
||||
<app-hero></app-hero>
|
||||
|
||||
@@ -5,15 +5,19 @@ import { BrowserModule } from '@angular/platform-browser';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { heroSwitchComponents } from './hero-switch.components';
|
||||
import { HeroComponent } from './hero.component';
|
||||
import { IfLoadedDirective } from './if-loaded.directive';
|
||||
import { UnlessDirective } from './unless.directive';
|
||||
|
||||
@NgModule({
|
||||
imports: [ BrowserModule, FormsModule ],
|
||||
imports: [BrowserModule, FormsModule],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
heroSwitchComponents,
|
||||
UnlessDirective
|
||||
HeroComponent,
|
||||
IfLoadedDirective,
|
||||
UnlessDirective,
|
||||
],
|
||||
bootstrap: [ AppComponent ]
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppModule { }
|
||||
export class AppModule {}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { LoadingState } from './loading-state';
|
||||
import { Hero, heroes } from './hero';
|
||||
|
||||
@Component({
|
||||
selector: 'app-hero',
|
||||
template: `
|
||||
<button (click)="onLoadHero()">Load Hero</button>
|
||||
<p *appIfLoaded="heroLoadingState">{{ heroLoadingState.data | json }}</p>
|
||||
`,
|
||||
})
|
||||
export class HeroComponent {
|
||||
heroLoadingState: LoadingState<Hero> = { type: 'loading' };
|
||||
|
||||
onLoadHero(): void {
|
||||
this.heroLoadingState = { type: 'loaded', data: heroes[0] };
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,8 @@ export interface Hero {
|
||||
}
|
||||
|
||||
export const heroes: Hero[] = [
|
||||
{ id: 1, name: 'Dr Nice', emotion: 'happy'},
|
||||
{ id: 2, name: 'Narco', emotion: 'sad' },
|
||||
{ id: 1, name: 'Dr. Nice', emotion: 'happy'},
|
||||
{ id: 2, name: 'RubberMan', emotion: 'sad' },
|
||||
{ id: 3, name: 'Windstorm', emotion: 'confused' },
|
||||
{ id: 4, name: 'Magneta'}
|
||||
];
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';
|
||||
|
||||
import { Loaded, LoadingState } from './loading-state';
|
||||
|
||||
@Directive({ selector: '[appIfLoaded]' })
|
||||
export class IfLoadedDirective<T> {
|
||||
private isViewCreated = false;
|
||||
|
||||
@Input('appIfLoaded') set state(state: LoadingState<T>) {
|
||||
if (!this.isViewCreated && state.type === 'loaded') {
|
||||
this.viewContainerRef.createEmbeddedView(this.templateRef);
|
||||
this.isViewCreated = true;
|
||||
} else if (this.isViewCreated && state.type !== 'loaded') {
|
||||
this.viewContainerRef.clear();
|
||||
this.isViewCreated = false;
|
||||
}
|
||||
}
|
||||
|
||||
constructor(
|
||||
private readonly viewContainerRef: ViewContainerRef,
|
||||
private readonly templateRef: TemplateRef<unknown>
|
||||
) {}
|
||||
|
||||
static ngTemplateGuard_appIfLoaded<T>(
|
||||
dir: IfLoadedDirective<T>,
|
||||
state: LoadingState<T>
|
||||
): state is Loaded<T> {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export type Loaded<T> = { type: 'loaded', data: T };
|
||||
|
||||
export type Loading = { type: 'loading' };
|
||||
|
||||
export type LoadingState<T> = Loaded<T> | Loading;
|
||||
@@ -97,7 +97,5 @@ value of the input will have no effect. -->
|
||||
|
||||
See the console output to see that when you declare the variable on an <code>ng-template</code>, the variable refers to a <code>TemplateRef</code> instance, which represents the template.
|
||||
|
||||
<!-- #docregion template-ref -->
|
||||
<ng-template #ref3></ng-template>
|
||||
<button type="button" (click)="log(ref3)">Log type of #ref</button>
|
||||
<!-- #enddocregion template-ref -->
|
||||
|
||||
@@ -11,8 +11,8 @@ export class Hero {
|
||||
325
|
||||
),
|
||||
new Hero(1, 'Dr Nice', 'happy'),
|
||||
new Hero(2, 'Narco', 'sad' ),
|
||||
new Hero(3, 'Windstorm', 'confused' ),
|
||||
new Hero(2, 'RubberMan', 'sad'),
|
||||
new Hero(3, 'Windstorm', 'confused'),
|
||||
new Hero(4, 'Magneta')
|
||||
];
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// For more examples:
|
||||
// https://github.com/angular/angular/blob/master/modules/@angular/router/test/integration.spec.ts
|
||||
// https://github.com/angular/angular/blob/main/packages/router/test/integration.spec.ts
|
||||
|
||||
import { waitForAsync, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ describe('HeroDetailComponent - no TestBed', () => {
|
||||
let router: jasmine.SpyObj<Router>;
|
||||
|
||||
beforeEach((done: DoneFn) => {
|
||||
expectedHero = {id: 42, name: 'Bubba' };
|
||||
expectedHero = { id: 42, name: 'Bubba' };
|
||||
const activatedRoute = new ActivatedRouteStub({ id: expectedHero.id });
|
||||
router = jasmine.createSpyObj('Router', ['navigate']);
|
||||
|
||||
@@ -27,7 +27,7 @@ describe('HeroDetailComponent - no TestBed', () => {
|
||||
comp.ngOnInit();
|
||||
|
||||
// OnInit calls HDS.getHero; wait for it to get the fake hero
|
||||
hds.getHero.calls.first().returnValue.subscribe(done);
|
||||
hds.getHero.calls.first().returnValue.subscribe(() => done());
|
||||
});
|
||||
|
||||
it('should expose the hero retrieved from the service', () => {
|
||||
|
||||
@@ -8,14 +8,13 @@ const maxQuotes = Infinity; // 0;
|
||||
export class InMemoryDataService implements InMemoryDbService {
|
||||
createDb() {
|
||||
const heroes = [
|
||||
{ id: 11, name: 'Dr Nice' },
|
||||
{ id: 12, name: 'Narco' },
|
||||
{ id: 12, name: 'Dr. Nice' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' },
|
||||
{ id: 15, name: 'Magneta' },
|
||||
{ id: 16, name: 'RubberMan' },
|
||||
{ id: 17, name: 'Dynama' },
|
||||
{ id: 18, name: 'Dr IQ' },
|
||||
{ id: 18, name: 'Dr. IQ' },
|
||||
{ id: 19, name: 'Magma' },
|
||||
{ id: 20, name: 'Tornado' }
|
||||
];
|
||||
|
||||
@@ -54,7 +54,7 @@ function initialPageTests() {
|
||||
|
||||
it('has the right number of heroes', async () => {
|
||||
const page = getPageElts();
|
||||
expect(await page.heroes.count()).toEqual(10);
|
||||
expect(await page.heroes.count()).toEqual(9);
|
||||
});
|
||||
|
||||
it('has no selected hero and no hero details', async () => {
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
<h2>My Heroes</h2>
|
||||
<ul class="heroes">
|
||||
<li>
|
||||
<span class="badge">{{hero.id}}</span> {{hero.name}}
|
||||
<button type="button">
|
||||
<span class="badge">{{hero.id}}</span>
|
||||
<span class="name">{{hero.name}}</span>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- #enddocregion list -->
|
||||
|
||||
@@ -11,17 +11,13 @@
|
||||
<!-- #enddocregion li -->
|
||||
</ul>
|
||||
|
||||
<!-- #docregion ng-if -->
|
||||
<!-- #docregion selectedHero-details -->
|
||||
<div *ngIf="selectedHero">
|
||||
|
||||
<!-- #docregion selectedHero-details -->
|
||||
<h2>{{selectedHero.name | uppercase}} Details</h2>
|
||||
<div>id: {{selectedHero.id}}</div>
|
||||
<div>
|
||||
<label for="hero-name">Hero name: </label>
|
||||
<input id="hero-name" [(ngModel)]="selectedHero.name" placeholder="name">
|
||||
</div>
|
||||
<!-- #enddocregion selectedHero-details -->
|
||||
|
||||
</div>
|
||||
<!-- #enddocregion ng-if -->
|
||||
<!-- #enddocregion selectedHero-details -->
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { Hero } from './hero';
|
||||
|
||||
export const HEROES: Hero[] = [
|
||||
{ id: 11, name: 'Dr Nice' },
|
||||
{ id: 12, name: 'Narco' },
|
||||
{ id: 12, name: 'Dr. Nice' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' },
|
||||
{ id: 15, name: 'Magneta' },
|
||||
{ id: 16, name: 'RubberMan' },
|
||||
{ id: 17, name: 'Dynama' },
|
||||
{ id: 18, name: 'Dr IQ' },
|
||||
{ id: 18, name: 'Dr. IQ' },
|
||||
{ id: 19, name: 'Magma' },
|
||||
{ id: 20, name: 'Tornado' }
|
||||
];
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user