Compare commits
353 Commits
docs/issue
...
7.2.7
Author | SHA1 | Date | |
---|---|---|---|
cb339b87f3 | |||
fdcf877f83 | |||
5b5b9897c9 | |||
0e7365724e | |||
4ef1a3cd97 | |||
38b5ed05ea | |||
642c015f23 | |||
0977d95802 | |||
d374787db6 | |||
a634deb885 | |||
bcbd7ed8f0 | |||
f7de2be3f3 | |||
1e97d511c7 | |||
7e1e00c21e | |||
481f4b7412 | |||
4bc0084e5a | |||
b6864494a1 | |||
0021437ee1 | |||
d91ecd2c8b | |||
d0018e6bf6 | |||
587ca854cc | |||
8b9f03d9fa | |||
40f1f94fe0 | |||
2270467d60 | |||
8efda5b353 | |||
7b7f2d9c1b | |||
c469e25cf2 | |||
a21cde2960 | |||
9b774348b3 | |||
ce219ccfa2 | |||
53bbb01047 | |||
c6741bf36a | |||
cc06bf50f3 | |||
21e78ad022 | |||
05e855092b | |||
2817764433 | |||
145639d0f8 | |||
3eb327b67b | |||
be6af26dc1 | |||
637e81e9bb | |||
abc3cbb33f | |||
27eb8f2723 | |||
81671cea9a | |||
843fc7df9f | |||
cfe4732e41 | |||
48cabb44c7 | |||
9d0db2fe4b | |||
069146e7f3 | |||
fc895ba189 | |||
9a51528072 | |||
7fc38d4947 | |||
b1f84ec78f | |||
f351e8a5b1 | |||
ff2c342356 | |||
01b05b3f7c | |||
3b78f9eb0f | |||
f6ca619343 | |||
ab69c31fc5 | |||
38de40c9ec | |||
53352c40c3 | |||
dd3cab6eb1 | |||
ea1a3d3603 | |||
cf1b436010 | |||
cdcbb53a2d | |||
db2db6e7f5 | |||
1df6b16263 | |||
f4871212b7 | |||
2a23eca917 | |||
b5da4c6676 | |||
b8c2f3b93f | |||
75cf86e70f | |||
bf25165354 | |||
a2ba4448da | |||
ac6b2b4dc3 | |||
b6dffa9763 | |||
54b57def58 | |||
e2b3cc8118 | |||
5e701a2c88 | |||
27a3df146d | |||
8cce7efbb2 | |||
d225c3a6e3 | |||
b23582d57e | |||
d3c6e512a3 | |||
a873fab10c | |||
ecef0dd65e | |||
1cc74eaece | |||
e2b3be87cb | |||
3ca6c928f9 | |||
5933d16f3e | |||
0f839bcfd0 | |||
edda94edfa | |||
b5e36eaa3e | |||
08a1f51704 | |||
9690e36f78 | |||
68e741227b | |||
50a2327520 | |||
b07346c8e3 | |||
8e95849751 | |||
cd143f67af | |||
dd85351162 | |||
c1c68889de | |||
866f4be782 | |||
80e4019c83 | |||
d9f3316021 | |||
424a3b95aa | |||
7e883c2319 | |||
6a7fd70ddf | |||
73f9db53c2 | |||
2bf526bbfb | |||
8bd7d5befc | |||
aa163bea93 | |||
2f73c554c9 | |||
fb2d15fda1 | |||
018507fa02 | |||
95bb72d322 | |||
ce6e6c3f81 | |||
e4b1bdbfa0 | |||
6477c9e04a | |||
3f380b3b78 | |||
c4c0e9dbc5 | |||
4ddf57c58d | |||
624f01c311 | |||
6a713521e3 | |||
57a5ba3438 | |||
1b6fb5bc19 | |||
bd9da268c1 | |||
1e58a2194f | |||
da81c9cb54 | |||
ef6d26d4fa | |||
13bc1cd853 | |||
1fa1379318 | |||
d9efacc07e | |||
47f5b5f2d4 | |||
019fe77f64 | |||
a0e3a8e0f7 | |||
8908156eae | |||
2ee265fb1f | |||
116512b06d | |||
1d841973eb | |||
3694e1a38c | |||
88d8813ccc | |||
49bfb63442 | |||
48848c9ca4 | |||
a1f1ea993d | |||
be8a403bc9 | |||
c378402af4 | |||
91ce8c17ff | |||
786be967fd | |||
e88d5e0df2 | |||
f39f01e00b | |||
ce750e6f5b | |||
beba944843 | |||
50981cbb1f | |||
76e40eed35 | |||
d491a20f3b | |||
74c202a5cd | |||
483e8d28ec | |||
a6fd118f79 | |||
fe6e76c1e7 | |||
de560019f2 | |||
52ed53d071 | |||
5b72d4d676 | |||
c1aa1bf872 | |||
dad1bc7ca3 | |||
2109c30afe | |||
874919a25b | |||
c64e666755 | |||
1da403d8f3 | |||
60c5ebd46a | |||
b71d1987cd | |||
e6325eb9ef | |||
114519ab6a | |||
a9a095d44a | |||
5f9d574d4d | |||
baeb446392 | |||
0d1bfdc505 | |||
fa130e9445 | |||
194710fc1d | |||
6ae5e2b32a | |||
d85d396c26 | |||
1a25144297 | |||
449da8c18e | |||
0f37ed1060 | |||
5c85b4f1e9 | |||
22bc6ef22a | |||
bf928d1c9e | |||
d11c2f915b | |||
98c99e5073 | |||
2c63108faa | |||
0ff48a1266 | |||
ea2a3f8335 | |||
cbed4851a3 | |||
7c157780a9 | |||
cc1b2a5373 | |||
5076185fc8 | |||
65375f4c21 | |||
068a6070dc | |||
47e9761a01 | |||
bef52d20b5 | |||
fe50710021 | |||
71b66fb862 | |||
8db05b408e | |||
351610ca8d | |||
ef78e33560 | |||
12b8a6e351 | |||
260ac20e92 | |||
aed48e00d2 | |||
a9d46e4952 | |||
2f19ad9b46 | |||
81678e62db | |||
cf82fbceba | |||
1d67cb0ce1 | |||
318bd83a6e | |||
f767c22b31 | |||
8346a6dca2 | |||
6397885e74 | |||
8cee56e8c5 | |||
a1b9995731 | |||
35f7ff047a | |||
4ad691a33d | |||
c5af3f8617 | |||
bc1032866c | |||
63e6d1a896 | |||
cb9fd9b4d7 | |||
d5dca0764c | |||
bcd1a09dec | |||
898c0134e7 | |||
763d2150cc | |||
beacbfcb8e | |||
f72319cf6e | |||
5877b3f702 | |||
cf310ba1fa | |||
c2d2953ee4 | |||
5c5fe34241 | |||
32737a6bf7 | |||
7642308c14 | |||
f1c08d83b0 | |||
617412f9c3 | |||
cf716684a9 | |||
54565ed389 | |||
ab08385336 | |||
eb8ccf65d1 | |||
cb93027f32 | |||
607fd8e970 | |||
f4ac96d0ff | |||
1c7d156abd | |||
4c00059260 | |||
93d78c9c51 | |||
49bee4c0d8 | |||
d8c75f1bb0 | |||
6d40ef2d6b | |||
4ea6c27dcf | |||
a4d9192fbc | |||
7b772e93a3 | |||
05168395b0 | |||
03293c4fec | |||
479019f457 | |||
68515818b9 | |||
8bc369f828 | |||
3d1a4d5cc3 | |||
5c56b778e0 | |||
585e871c96 | |||
6ae7aee2c3 | |||
701270d039 | |||
02a852a34a | |||
531f940212 | |||
de80f1b6dd | |||
ca3965afe0 | |||
f269e433a7 | |||
8750b09fca | |||
ea2eef737b | |||
0ceab97a03 | |||
fbbdaaacc0 | |||
080de58a88 | |||
5390948360 | |||
0d860051af | |||
edbba24b60 | |||
6ae8d7691d | |||
af3cf36ce9 | |||
1be2f11965 | |||
495ce325b2 | |||
92411043d1 | |||
aa3f75b3c9 | |||
d64aadf57a | |||
51f7f081a3 | |||
b9fd62413f | |||
c5664bf245 | |||
c66a076614 | |||
28d34b699d | |||
47840bee71 | |||
305331f634 | |||
5e6c24cb01 | |||
0ec4e1372a | |||
84c1bad3a1 | |||
1640832f56 | |||
8ab036262d | |||
76e8c0ac7b | |||
0e81e418fb | |||
60255b68c0 | |||
ae7b3c8d45 | |||
9556ba7bca | |||
80994b25b9 | |||
2f154b980f | |||
342d352a00 | |||
f240ae5084 | |||
e4fc8bad35 | |||
5c680d4aa8 | |||
f05c5f82c8 | |||
2e0c58ec3e | |||
21093b9090 | |||
a6153accf0 | |||
dee789c204 | |||
12dd552fcd | |||
079bcffe07 | |||
30256e8fe8 | |||
8ee69831fc | |||
c3d8e2888d | |||
bea677136b | |||
11728bbbd9 | |||
1da4b03940 | |||
54ba0f021f | |||
836a5c72a0 | |||
f589933440 | |||
ef3ec34aa3 | |||
37a6d2d033 | |||
354f3639bb | |||
c4b06868b1 | |||
e3853e842e | |||
aee5cbd057 | |||
e9614eff1a | |||
80f9f7e8ef | |||
7d2589556f | |||
468fcab59d | |||
f720e972d4 | |||
b51ae7e59a | |||
eedb06936f | |||
ee5a094424 | |||
9773b5a173 | |||
eed171839e | |||
1057b52def | |||
302506e940 | |||
cc35feb445 | |||
21b875d4d0 | |||
dac9c09235 | |||
5cba438eb5 | |||
2b001cb2b1 | |||
0be8487f09 | |||
e1e69ca828 | |||
f376c46d78 | |||
fad4145f48 | |||
6b394f62be | |||
16aad8b2d8 | |||
25bbcbcbe5 |
@ -1,4 +1,6 @@
|
|||||||
node_modules
|
node_modules
|
||||||
dist
|
dist
|
||||||
|
aio/content
|
||||||
aio/node_modules
|
aio/node_modules
|
||||||
aio/tools/examples/shared/node_modules
|
aio/tools/examples/shared/node_modules
|
||||||
|
integration/bazel
|
||||||
|
20
.bazelrc
20
.bazelrc
@ -22,8 +22,14 @@ test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test
|
|||||||
# Filesystem interactions #
|
# Filesystem interactions #
|
||||||
###############################
|
###############################
|
||||||
|
|
||||||
# Don't create symlinks like bazel-out in the project.
|
# Create symlinks in the project:
|
||||||
# These cause VSCode to traverse a massive tree, opening file handles and
|
# - dist/bin for outputs
|
||||||
|
# - dist/testlogs, dist/genfiles
|
||||||
|
# - bazel-out
|
||||||
|
# NB: bazel-out should be excluded from the editor configuration.
|
||||||
|
# The checked-in /.vscode/settings.json does this for VSCode.
|
||||||
|
# Other editors may require manual config to ignore this directory.
|
||||||
|
# In the past, we say a problem where VSCode traversed a massive tree, opening file handles and
|
||||||
# eventually a surprising failure with auto-discovery of the C++ toolchain in
|
# eventually a surprising failure with auto-discovery of the C++ toolchain in
|
||||||
# MacOS High Sierra.
|
# MacOS High Sierra.
|
||||||
# See https://github.com/bazelbuild/bazel/issues/4603
|
# See https://github.com/bazelbuild/bazel/issues/4603
|
||||||
@ -36,6 +42,16 @@ build --watchfs
|
|||||||
run --nolegacy_external_runfiles
|
run --nolegacy_external_runfiles
|
||||||
test --nolegacy_external_runfiles
|
test --nolegacy_external_runfiles
|
||||||
|
|
||||||
|
# Turn on --incompatible_strict_action_env which was on by default
|
||||||
|
# in Bazel 0.21.0 but turned off again in 0.22.0. Follow
|
||||||
|
# https://github.com/bazelbuild/bazel/issues/7026 for more details.
|
||||||
|
# This flag is needed to so that the bazel cache is not invalidated
|
||||||
|
# when running bazel via `yarn bazel`.
|
||||||
|
# See https://github.com/angular/angular/issues/27514.
|
||||||
|
build --incompatible_strict_action_env
|
||||||
|
run --incompatible_strict_action_env
|
||||||
|
test --incompatible_strict_action_env
|
||||||
|
|
||||||
###############################
|
###############################
|
||||||
# Release support #
|
# Release support #
|
||||||
# Turn on these settings with #
|
# Turn on these settings with #
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
# We do this by copying this file to /etc/bazel.bazelrc at the start of the build.
|
# We do this by copying this file to /etc/bazel.bazelrc at the start of the build.
|
||||||
# See documentation in /docs/BAZEL.md
|
# See documentation in /docs/BAZEL.md
|
||||||
|
|
||||||
|
# Save downloaded repositories in a location that can be cached by CircleCI. This helps us
|
||||||
|
# speeding up the analysis time significantly with Bazel managed node dependencies on the CI.
|
||||||
|
build --repository_cache=/home/circleci/bazel_repository_cache
|
||||||
|
|
||||||
# Don't be spammy in the logs
|
# Don't be spammy in the logs
|
||||||
# TODO(gmagolan): Hide progress again once build performance improves
|
# TODO(gmagolan): Hide progress again once build performance improves
|
||||||
# Presently, CircleCI can timeout during bazel test ... with the following
|
# Presently, CircleCI can timeout during bazel test ... with the following
|
||||||
|
@ -11,16 +11,43 @@
|
|||||||
# needed for jobs that run tests without Bazel. Bazel runs tests with browsers that will be
|
# needed for jobs that run tests without Bazel. Bazel runs tests with browsers that will be
|
||||||
# fetched by the Webtesting rules. Therefore for jobs that run tests with Bazel, we don't need a
|
# fetched by the Webtesting rules. Therefore for jobs that run tests with Bazel, we don't need a
|
||||||
# docker image with browsers pre-installed.
|
# docker image with browsers pre-installed.
|
||||||
# **NOTE**: If you change the version of the docker images, also change the `cache_key` suffix.
|
# **NOTE 1**: If you change the version of the `*-browsers` docker image, make sure the
|
||||||
|
# `CI_CHROMEDRIVER_VERSION_ARG` env var (in `.circleci/env.sh`) points to a ChromeDriver
|
||||||
|
# version that is compatible with the Chrome version in the image.
|
||||||
|
# **NOTE 2**: If you change the version of the docker images, also change the `cache_key` suffix.
|
||||||
var_1: &default_docker_image circleci/node:10.12
|
var_1: &default_docker_image circleci/node:10.12
|
||||||
var_2: &browsers_docker_image circleci/node:10.12-browsers
|
var_2: &browsers_docker_image circleci/node:10.12-browsers
|
||||||
var_3: &cache_key v2-angular-{{ .Branch }}-{{ checksum "yarn.lock" }}-node-10.12
|
# We don't want to include the current branch name in the cache key because that would prevent
|
||||||
|
# PRs from being able to restore the cache since the branch names are always different for PRs.
|
||||||
|
# The cache key should only consist of dynamic values that change whenever something in the
|
||||||
|
# cache changes. For example:
|
||||||
|
# 1) yarn lock file changes --> cached "node_modules" are different.
|
||||||
|
# 2) bazel repository definitions change --> cached bazel repositories are different.
|
||||||
|
# **NOTE 1 **: If you change the cache key prefix, also sync the restore_cache fallback to match.
|
||||||
|
# **NOTE 2 **: Keep the static part of the cache key as prefix to enable correct fallbacks.
|
||||||
|
# See https://circleci.com/docs/2.0/caching/#restoring-cache for how prefixes work in CircleCI.
|
||||||
|
var_3: &cache_key v3-angular-node-10.12-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
||||||
|
|
||||||
# Define common ENV vars
|
# Initializes the CI environment by setting up common environment variables.
|
||||||
var_4: &define_env_vars
|
var_4: &init_environment
|
||||||
run:
|
run:
|
||||||
name: Define environment variables
|
name: Initializing environment (setting up variables, overwriting Yarn)
|
||||||
command: ./.circleci/env.sh
|
# Overwrite the yarn installed in the docker container with our own version.
|
||||||
|
command: |
|
||||||
|
./.circleci/env.sh
|
||||||
|
ourYarn=$(realpath ./third_party/github.com/yarnpkg/yarn/releases/download/v1.13.0/bin/yarn.js)
|
||||||
|
sudo chmod a+x $ourYarn
|
||||||
|
sudo ln -fs $ourYarn /usr/local/bin/yarn
|
||||||
|
echo "Yarn version: $(yarn --version)"
|
||||||
|
|
||||||
|
# Add GitHub to known hosts.
|
||||||
|
mkdir -p ~/.ssh
|
||||||
|
echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==' >> ~/.ssh/known_hosts
|
||||||
|
|
||||||
|
# use git+ssh instead of https
|
||||||
|
git config --global url."ssh://git@github.com".insteadOf "https://github.com" || true
|
||||||
|
git config --global gc.auto 0 || true
|
||||||
|
|
||||||
|
|
||||||
var_5: &setup_bazel_remote_execution
|
var_5: &setup_bazel_remote_execution
|
||||||
run:
|
run:
|
||||||
@ -40,29 +67,97 @@ var_6: &job_defaults
|
|||||||
# Similar to travis behavior, but not quite the same.
|
# Similar to travis behavior, but not quite the same.
|
||||||
# See https://discuss.circleci.com/t/1662
|
# See https://discuss.circleci.com/t/1662
|
||||||
var_7: &post_checkout
|
var_7: &post_checkout
|
||||||
post: git pull --ff-only origin "refs/pull/${CI_PULL_REQUEST//*pull\//}/merge"
|
run:
|
||||||
|
name: Post checkout step
|
||||||
|
command: >
|
||||||
|
if [[ -n "${CIRCLE_PR_NUMBER}" ]]; then
|
||||||
|
# Fetch the head and merge commits for this PR.
|
||||||
|
git fetch origin +refs/pull/$CIRCLE_PR_NUMBER/head:pr/$CIRCLE_PR_NUMBER/head
|
||||||
|
git fetch origin +refs/pull/$CIRCLE_PR_NUMBER/merge:pr/$CIRCLE_PR_NUMBER/merge
|
||||||
|
# Checkout the merged PR for testing as CircleCI will just use the PR head otherwise.
|
||||||
|
git checkout -qf pr/$CIRCLE_PR_NUMBER/merge
|
||||||
|
# Reset the merge commit into its PR head.
|
||||||
|
git reset pr/$CIRCLE_PR_NUMBER/head
|
||||||
|
# Commit the merge changes into the head of the PR.
|
||||||
|
# This way we keep the last commit message.
|
||||||
|
git config user.name "angular-ci"
|
||||||
|
git config user.email "angular-ci"
|
||||||
|
git commit . --amend --no-edit
|
||||||
|
fi
|
||||||
|
|
||||||
var_8: &yarn_install
|
var_8: &yarn_install
|
||||||
run:
|
run:
|
||||||
name: Running Yarn install
|
name: Running Yarn install
|
||||||
command: yarn install --frozen-lockfile --non-interactive
|
command: |
|
||||||
|
# Yarn's requests sometimes take more than 10mins to complete.
|
||||||
|
# Print something to stdout, to prevent CircleCI from failing due to not output.
|
||||||
|
while true; do sleep 60; echo "[`date`] Keeping alive..."; done &
|
||||||
|
KEEP_ALIVE_PID=$!
|
||||||
|
yarn install --frozen-lockfile --non-interactive
|
||||||
|
kill $KEEP_ALIVE_PID
|
||||||
|
|
||||||
var_9: &setup_circleci_bazel_config
|
var_9: &setup_circleci_bazel_config
|
||||||
run:
|
run:
|
||||||
name: Setting up CircleCI bazel configuration
|
name: Setting up CircleCI bazel configuration
|
||||||
command: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
command: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||||
|
|
||||||
|
var_10: &restore_cache
|
||||||
|
restore_cache:
|
||||||
|
keys:
|
||||||
|
- *cache_key
|
||||||
|
# This fallback should be the cache_key without variables.
|
||||||
|
- v3-angular-node-10.12-
|
||||||
|
|
||||||
|
# Branch filter that can be specified for jobs that should only run on publish branches
|
||||||
|
# (e.g. master or the patch branch)
|
||||||
|
var_12: &publish_branches_filter
|
||||||
|
branches:
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
# e.g. 7.0.x, 7.1.x, etc.
|
||||||
|
- /\d+\.\d+\.x/
|
||||||
|
|
||||||
|
# Workspace initially persisted by the `install` job, and then enhanced by `test_aio` and
|
||||||
|
# `build-npm-packages`.
|
||||||
|
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
|
||||||
|
# https://circleci.com/blog/deep-diving-into-circleci-workspaces/
|
||||||
|
var_13: &attach_workspace
|
||||||
|
attach_workspace:
|
||||||
|
at: ~/
|
||||||
|
|
||||||
version: 2
|
version: 2
|
||||||
jobs:
|
jobs:
|
||||||
|
setup:
|
||||||
|
<<: *job_defaults
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- *post_checkout
|
||||||
|
# This cache is saved in the build-npm-packages so that Bazel cache is also included.
|
||||||
|
- *restore_cache
|
||||||
|
- *init_environment
|
||||||
|
- *yarn_install
|
||||||
|
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||||
|
# Make the bazel directories and add a file to them if they don't exist already so that
|
||||||
|
# persist_to_workspace does not fail.
|
||||||
|
- run: |
|
||||||
|
if [ ! -d ~/bazel_repository_cache ]; then
|
||||||
|
mkdir ~/bazel_repository_cache
|
||||||
|
touch ~/bazel_repository_cache/MARKER
|
||||||
|
fi
|
||||||
|
# Persist any changes at this point to be reused by further jobs.
|
||||||
|
# **NOTE 1 **: Folders persisted here should be kept in sync with `var_13: &attach_workspace`.
|
||||||
|
# **NOTE 2 **: To add new content to the workspace, always persist on the same root.
|
||||||
|
- persist_to_workspace:
|
||||||
|
root: ~/
|
||||||
|
paths:
|
||||||
|
- ./ng
|
||||||
|
- ./bazel_repository_cache
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
- *init_environment
|
||||||
- restore_cache:
|
|
||||||
key: *cache_key
|
|
||||||
- *define_env_vars
|
|
||||||
- *yarn_install
|
|
||||||
|
|
||||||
- run: 'yarn bazel:format -mode=check ||
|
- run: 'yarn bazel:format -mode=check ||
|
||||||
(echo "BUILD files not formatted. Please run ''yarn bazel:format''" ; exit 1)'
|
(echo "BUILD files not formatted. Please run ''yarn bazel:format''" ; exit 1)'
|
||||||
@ -70,19 +165,15 @@ jobs:
|
|||||||
- run: 'yarn bazel:lint ||
|
- run: 'yarn bazel:lint ||
|
||||||
(echo -e "\n.bzl files have lint errors. Please run ''yarn bazel:lint-fix''"; exit 1)'
|
(echo -e "\n.bzl files have lint errors. Please run ''yarn bazel:lint-fix''"; exit 1)'
|
||||||
|
|
||||||
- run: ./node_modules/.bin/gulp lint
|
- run: yarn gulp lint
|
||||||
|
|
||||||
test:
|
test:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
resource_class: xlarge
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
- *init_environment
|
||||||
- restore_cache:
|
|
||||||
key: *cache_key
|
|
||||||
- *define_env_vars
|
|
||||||
- *setup_circleci_bazel_config
|
- *setup_circleci_bazel_config
|
||||||
- *yarn_install
|
|
||||||
|
|
||||||
# Setup remote execution and run RBE-compatible tests.
|
# Setup remote execution and run RBE-compatible tests.
|
||||||
- *setup_bazel_remote_execution
|
- *setup_bazel_remote_execution
|
||||||
@ -91,24 +182,14 @@ jobs:
|
|||||||
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
- run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc
|
||||||
- run: yarn bazel test //... --build_tag_filters=-ivy-only,local --test_tag_filters=-ivy-only,local
|
- run: yarn bazel test //... --build_tag_filters=-ivy-only,local --test_tag_filters=-ivy-only,local
|
||||||
|
|
||||||
- save_cache:
|
|
||||||
key: *cache_key
|
|
||||||
paths:
|
|
||||||
- "node_modules"
|
|
||||||
- "~/bazel_repository_cache"
|
|
||||||
|
|
||||||
# Temporary job to test what will happen when we flip the Ivy flag to true
|
# Temporary job to test what will happen when we flip the Ivy flag to true
|
||||||
test_ivy_aot:
|
test_ivy_aot:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
resource_class: xlarge
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
- *init_environment
|
||||||
- restore_cache:
|
|
||||||
key: *cache_key
|
|
||||||
- *define_env_vars
|
|
||||||
- *setup_circleci_bazel_config
|
- *setup_circleci_bazel_config
|
||||||
- *yarn_install
|
|
||||||
- *setup_bazel_remote_execution
|
- *setup_bazel_remote_execution
|
||||||
|
|
||||||
# We need to explicitly specify the --symlink_prefix option because otherwise we would
|
# We need to explicitly specify the --symlink_prefix option because otherwise we would
|
||||||
@ -141,11 +222,8 @@ jobs:
|
|||||||
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
||||||
- image: *browsers_docker_image
|
- image: *browsers_docker_image
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
- *init_environment
|
||||||
- restore_cache:
|
|
||||||
key: *cache_key
|
|
||||||
- *define_env_vars
|
|
||||||
# Build aio
|
# Build aio
|
||||||
- run: yarn --cwd aio build --progress=false
|
- run: yarn --cwd aio build --progress=false
|
||||||
# Lint the code
|
# Lint the code
|
||||||
@ -157,9 +235,9 @@ jobs:
|
|||||||
# (Run before unit and e2e tests, which destroy the `dist/` directory.)
|
# (Run before unit and e2e tests, which destroy the `dist/` directory.)
|
||||||
- run: yarn --cwd aio payload-size
|
- run: yarn --cwd aio payload-size
|
||||||
# Run unit tests
|
# Run unit tests
|
||||||
- run: yarn --cwd aio test --watch=false
|
- run: yarn --cwd aio test --progress=false --watch=false
|
||||||
# Run e2e tests
|
# Run e2e tests
|
||||||
- run: yarn --cwd aio e2e
|
- run: yarn --cwd aio e2e --configuration=ci
|
||||||
# Run unit tests for Firebase redirects
|
# Run unit tests for Firebase redirects
|
||||||
- run: yarn --cwd aio redirects-test
|
- run: yarn --cwd aio redirects-test
|
||||||
|
|
||||||
@ -169,11 +247,8 @@ jobs:
|
|||||||
# Needed because before deploying the deploy-production script runs the PWA score tests.
|
# Needed because before deploying the deploy-production script runs the PWA score tests.
|
||||||
- image: *browsers_docker_image
|
- image: *browsers_docker_image
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
- *init_environment
|
||||||
- restore_cache:
|
|
||||||
key: *cache_key
|
|
||||||
- *define_env_vars
|
|
||||||
# Deploy angular.io to production (if necessary)
|
# Deploy angular.io to production (if necessary)
|
||||||
- run: setPublicVar CI_STABLE_BRANCH "$(npm info @angular/core dist-tags.latest | sed -r 's/^\s*([0-9]+\.[0-9]+)\.[0-9]+.*$/\1.x/')"
|
- run: setPublicVar CI_STABLE_BRANCH "$(npm info @angular/core dist-tags.latest | sed -r 's/^\s*([0-9]+\.[0-9]+)\.[0-9]+.*$/\1.x/')"
|
||||||
- run: yarn --cwd aio deploy-production
|
- run: yarn --cwd aio deploy-production
|
||||||
@ -184,33 +259,31 @@ jobs:
|
|||||||
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
# Needed because the AIO tests and the PWA score test depend on Chrome being available.
|
||||||
- image: *browsers_docker_image
|
- image: *browsers_docker_image
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
- *init_environment
|
||||||
- restore_cache:
|
|
||||||
key: *cache_key
|
|
||||||
- attach_workspace:
|
|
||||||
at: dist
|
|
||||||
- *define_env_vars
|
|
||||||
# Build aio (with local Angular packages)
|
# Build aio (with local Angular packages)
|
||||||
- run: yarn --cwd aio build-local --progress=false
|
- run: yarn --cwd aio build-local --progress=false
|
||||||
# Run PWA-score tests
|
# Run PWA-score tests
|
||||||
# (Run before unit and e2e tests, which destroy the `dist/` directory.)
|
# (Run before unit and e2e tests, which destroy the `dist/` directory.)
|
||||||
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
- run: yarn --cwd aio test-pwa-score-localhost $CI_AIO_MIN_PWA_SCORE
|
||||||
# Run unit tests
|
# Run unit tests
|
||||||
- run: yarn --cwd aio test --watch=false
|
- run: yarn --cwd aio test --progress=false --watch=false
|
||||||
# Run e2e tests
|
# Run e2e tests
|
||||||
- run: yarn --cwd aio e2e
|
- run: yarn --cwd aio e2e --configuration=ci
|
||||||
|
|
||||||
|
test_aio_local_ivy:
|
||||||
|
<<: *job_defaults
|
||||||
|
steps:
|
||||||
|
- *attach_workspace
|
||||||
|
- *init_environment
|
||||||
|
# Build aio with Ivy (using local Angular packages)
|
||||||
|
- run: yarn --cwd aio build-with-ivy --progress=false
|
||||||
|
|
||||||
test_aio_tools:
|
test_aio_tools:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
- *init_environment
|
||||||
- restore_cache:
|
|
||||||
key: *cache_key
|
|
||||||
- attach_workspace:
|
|
||||||
at: dist
|
|
||||||
- *define_env_vars
|
|
||||||
# Install
|
# Install
|
||||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||||
- run: yarn --cwd aio extract-cli-command-docs
|
- run: yarn --cwd aio extract-cli-command-docs
|
||||||
@ -218,45 +291,37 @@ jobs:
|
|||||||
- run: yarn --cwd aio tools-test
|
- run: yarn --cwd aio tools-test
|
||||||
- run: ./aio/aio-builds-setup/scripts/test.sh
|
- run: ./aio/aio-builds-setup/scripts/test.sh
|
||||||
|
|
||||||
test_docs_examples_0:
|
test_docs_examples:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
docker:
|
docker:
|
||||||
# Needed because the example e2e tests depend on Chrome.
|
# Needed because the example e2e tests depend on Chrome.
|
||||||
- image: *browsers_docker_image
|
- image: *browsers_docker_image
|
||||||
|
parallelism: 3
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
- *init_environment
|
||||||
- restore_cache:
|
|
||||||
key: *cache_key
|
|
||||||
- attach_workspace:
|
|
||||||
at: dist
|
|
||||||
- *define_env_vars
|
|
||||||
# Install root
|
|
||||||
- *yarn_install
|
|
||||||
# Install aio
|
# Install aio
|
||||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||||
# Run examples tests
|
# Run examples tests. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
||||||
- run: yarn --cwd aio example-e2e --setup --local --shard=0/2
|
# Since the parallelism is set to "3", there will be three parallel CircleCI containers
|
||||||
|
# with either "0", "1" or "2" as node index. This can be passed to the "--shard" argument.
|
||||||
|
- run: yarn --cwd aio example-e2e --setup --local --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL}
|
||||||
|
|
||||||
test_docs_examples_1:
|
test_docs_examples_ivy:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
docker:
|
docker:
|
||||||
# Needed because the example e2e tests depend on Chrome.
|
# Needed because the example e2e tests depend on Chrome.
|
||||||
- image: *browsers_docker_image
|
- image: *browsers_docker_image
|
||||||
|
parallelism: 3
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
- *init_environment
|
||||||
- restore_cache:
|
|
||||||
key: *cache_key
|
|
||||||
- attach_workspace:
|
|
||||||
at: dist
|
|
||||||
- *define_env_vars
|
|
||||||
# Install root
|
|
||||||
- *yarn_install
|
|
||||||
# Install aio
|
# Install aio
|
||||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||||
# Run examples tests
|
# Run examples tests with ivy. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
||||||
- run: yarn --cwd aio example-e2e --setup --local --shard=1/2
|
# Since the parallelism is set to "3", there will be three parallel CircleCI containers
|
||||||
|
# with either "0", "1" or "2" as node index. This can be passed to the "--shard" argument.
|
||||||
|
- run: yarn --cwd aio example-e2e --setup --local --ivy --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL}
|
||||||
|
|
||||||
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
# This job should only be run on PR builds, where `CI_PULL_REQUEST` is not `false`.
|
||||||
aio_preview:
|
aio_preview:
|
||||||
@ -264,12 +329,8 @@ jobs:
|
|||||||
environment:
|
environment:
|
||||||
AIO_SNAPSHOT_ARTIFACT_PATH: &aio_preview_artifact_path 'aio/tmp/snapshot.tgz'
|
AIO_SNAPSHOT_ARTIFACT_PATH: &aio_preview_artifact_path 'aio/tmp/snapshot.tgz'
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
- *init_environment
|
||||||
- restore_cache:
|
|
||||||
key: *cache_key
|
|
||||||
- *define_env_vars
|
|
||||||
- *yarn_install
|
|
||||||
- run: ./aio/scripts/build-artifacts.sh $AIO_SNAPSHOT_ARTIFACT_PATH $CI_PULL_REQUEST $CI_COMMIT
|
- run: ./aio/scripts/build-artifacts.sh $AIO_SNAPSHOT_ARTIFACT_PATH $CI_PULL_REQUEST $CI_COMMIT
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: *aio_preview_artifact_path
|
path: *aio_preview_artifact_path
|
||||||
@ -285,45 +346,64 @@ jobs:
|
|||||||
# Needed because the test-preview script runs e2e tests and the PWA score test with Chrome.
|
# Needed because the test-preview script runs e2e tests and the PWA score test with Chrome.
|
||||||
- image: *browsers_docker_image
|
- image: *browsers_docker_image
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
- *init_environment
|
||||||
- restore_cache:
|
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||||
key: *cache_key
|
|
||||||
- *define_env_vars
|
|
||||||
- run: yarn install --cwd aio --frozen-lockfile --non-interactive
|
|
||||||
- run:
|
- run:
|
||||||
name: Wait for preview and run tests
|
name: Wait for preview and run tests
|
||||||
command: node aio/scripts/test-preview.js $CI_PULL_REQUEST $CI_COMMIT $CI_AIO_MIN_PWA_SCORE
|
command: node aio/scripts/test-preview.js $CI_PULL_REQUEST $CI_COMMIT $CI_AIO_MIN_PWA_SCORE
|
||||||
|
|
||||||
# This job exists only for backwards-compatibility with old scripts and tests
|
|
||||||
# that rely on the pre-Bazel dist/packages-dist layout.
|
# The `build-npm-packages` tasks exist for backwards-compatibility with old scripts and
|
||||||
# It duplicates some work with the job above: we build the bazel packages
|
# tests that rely on the pre-Bazel `dist/packages-dist` output structure (build.sh).
|
||||||
# twice. Even though we have a remote cache, these jobs will typically run in
|
# Having multiple jobs that independently build in this manner duplicates some work; we build
|
||||||
# parallel so up-to-date outputs will not be available at the time the build
|
# the bazel packages more than once. Even though we have a remote cache, these jobs will
|
||||||
|
# typically run in parallel so up-to-date outputs will not be available at the time the build
|
||||||
# starts.
|
# starts.
|
||||||
# No new jobs should depend on this one.
|
|
||||||
build-packages-dist:
|
# Build the view engine npm packages. No new jobs should depend on this.
|
||||||
|
build-npm-packages:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
resource_class: xlarge
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
- *init_environment
|
||||||
- restore_cache:
|
|
||||||
key: *cache_key
|
|
||||||
- *define_env_vars
|
|
||||||
- *setup_circleci_bazel_config
|
- *setup_circleci_bazel_config
|
||||||
- *yarn_install
|
|
||||||
- *setup_bazel_remote_execution
|
- *setup_bazel_remote_execution
|
||||||
|
|
||||||
- run: scripts/build-packages-dist.sh
|
- run: scripts/build-packages-dist.sh
|
||||||
|
|
||||||
# Save the npm packages from //packages/... for other workflow jobs to read
|
# Save the npm packages from //packages/... for other workflow jobs to read
|
||||||
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
|
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
root: dist
|
root: ~/
|
||||||
paths:
|
paths:
|
||||||
- packages-dist
|
- ng/dist/packages-dist
|
||||||
- packages-dist-ivy-aot
|
|
||||||
|
# Save dependencies and bazel repository cache to use on subsequent runs.
|
||||||
|
- save_cache:
|
||||||
|
key: *cache_key
|
||||||
|
paths:
|
||||||
|
- "node_modules"
|
||||||
|
- "aio/node_modules"
|
||||||
|
- "~/bazel_repository_cache"
|
||||||
|
|
||||||
|
# Build the ivy npm packages.
|
||||||
|
build-ivy-npm-packages:
|
||||||
|
<<: *job_defaults
|
||||||
|
resource_class: xlarge
|
||||||
|
steps:
|
||||||
|
- *attach_workspace
|
||||||
|
- *init_environment
|
||||||
|
- *setup_circleci_bazel_config
|
||||||
|
- *setup_bazel_remote_execution
|
||||||
|
|
||||||
|
- run: scripts/build-ivy-npm-packages.sh
|
||||||
|
|
||||||
|
# Save the npm packages from //packages/... for other workflow jobs to read
|
||||||
|
- persist_to_workspace:
|
||||||
|
root: ~/
|
||||||
|
paths:
|
||||||
|
- ng/dist/packages-dist-ivy-aot
|
||||||
|
|
||||||
# We run the integration tests outside of Bazel for now.
|
# We run the integration tests outside of Bazel for now.
|
||||||
# They are a separate workflow job so that they can be easily re-run.
|
# They are a separate workflow job so that they can be easily re-run.
|
||||||
@ -333,6 +413,7 @@ jobs:
|
|||||||
# See comments inside the integration/run_tests.sh script.
|
# See comments inside the integration/run_tests.sh script.
|
||||||
integration_test:
|
integration_test:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
|
parallelism: 4
|
||||||
docker:
|
docker:
|
||||||
# Needed because the integration tests expect Chrome to be installed (e.g cli-hello-world)
|
# Needed because the integration tests expect Chrome to be installed (e.g cli-hello-world)
|
||||||
- image: *browsers_docker_image
|
- image: *browsers_docker_image
|
||||||
@ -341,23 +422,19 @@ jobs:
|
|||||||
# on a 4G worker so we use a larger machine here too.
|
# on a 4G worker so we use a larger machine here too.
|
||||||
resource_class: xlarge
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
- *init_environment
|
||||||
- restore_cache:
|
# Runs the integration tests in parallel across multiple CircleCI container instances. The
|
||||||
key: *cache_key
|
# amount of container nodes for this job is controlled by the "parallelism" option.
|
||||||
- attach_workspace:
|
- run: ./integration/run_tests.sh ${CIRCLE_NODE_INDEX} ${CIRCLE_NODE_TOTAL}
|
||||||
at: dist
|
|
||||||
- *define_env_vars
|
|
||||||
- run: ./integration/run_tests.sh
|
|
||||||
|
|
||||||
# This job updates the content of repos like github.com/angular/core-builds
|
# This job updates the content of repos like github.com/angular/core-builds
|
||||||
# for every green build on angular/angular.
|
# for every green build on angular/angular.
|
||||||
publish_snapshot:
|
publish_snapshot:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
- *init_environment
|
||||||
- *define_env_vars
|
|
||||||
# See below - ideally this job should not trigger for non-upstream builds.
|
# See below - ideally this job should not trigger for non-upstream builds.
|
||||||
# But since it does, we have to check this condition.
|
# But since it does, we have to check this condition.
|
||||||
- run:
|
- run:
|
||||||
@ -368,8 +445,6 @@ jobs:
|
|||||||
|| "$CI_REPO_OWNER" != "angular"
|
|| "$CI_REPO_OWNER" != "angular"
|
||||||
|| "$CI_REPO_NAME" != "angular"
|
|| "$CI_REPO_NAME" != "angular"
|
||||||
]] && circleci step halt || true'
|
]] && circleci step halt || true'
|
||||||
- attach_workspace:
|
|
||||||
at: dist
|
|
||||||
# CircleCI has a config setting to force SSH for all github connections
|
# CircleCI has a config setting to force SSH for all github connections
|
||||||
# This is not compatible with our mechanism of using a Personal Access Token
|
# This is not compatible with our mechanism of using a Personal Access Token
|
||||||
# Clear the global setting
|
# Clear the global setting
|
||||||
@ -386,44 +461,98 @@ jobs:
|
|||||||
# which does not load the browser through the Bazel webtesting rules.
|
# which does not load the browser through the Bazel webtesting rules.
|
||||||
- image: *browsers_docker_image
|
- image: *browsers_docker_image
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
- *init_environment
|
||||||
- restore_cache:
|
|
||||||
key: *cache_key
|
|
||||||
- *define_env_vars
|
|
||||||
- run:
|
- run:
|
||||||
name: Run tests against the deployed apps
|
name: Run tests against the deployed apps
|
||||||
command: ./aio/scripts/test-production.sh $CI_AIO_MIN_PWA_SCORE
|
command: ./aio/scripts/test-production.sh $CI_AIO_MIN_PWA_SCORE
|
||||||
- run:
|
- run:
|
||||||
name: Notify caretaker about failure
|
name: Notify caretaker about failure
|
||||||
command: 'curl --request POST --header "Content-Type: application/json" --data "{\"text\":\":x: \`$CIRCLE_JOB\` job failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}" $CI_SECRET_SLACK_CARETAKER_WEBHOOK_URL'
|
# `$SLACK_CARETAKER_WEBHOOK_URL` is a secret env var defined in CircleCI project settings.
|
||||||
|
# The URL comes from https://angular-team.slack.com/apps/A0F7VRE7N-circleci.
|
||||||
|
command: 'curl --request POST --header "Content-Type: application/json" --data "{\"text\":\":x: \`$CIRCLE_JOB\` job failed on build $CIRCLE_BUILD_NUM: $CIRCLE_BUILD_URL :scream:\"}" $SLACK_CARETAKER_WEBHOOK_URL'
|
||||||
when: on_fail
|
when: on_fail
|
||||||
|
|
||||||
|
legacy-unit-tests-saucelabs:
|
||||||
|
<<: *job_defaults
|
||||||
|
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
||||||
|
# container for this job. This is necessary because we launch a lot of browsers concurrently
|
||||||
|
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
||||||
|
resource_class: xlarge
|
||||||
|
steps:
|
||||||
|
- *attach_workspace
|
||||||
|
- *init_environment
|
||||||
|
- run:
|
||||||
|
name: Preparing environment for running tests on Saucelabs.
|
||||||
|
command: |
|
||||||
|
setPublicVar KARMA_JS_BROWSERS $(node -e 'console.log(require("./browser-providers.conf").sauceAliases.CI_REQUIRED.join(","))')
|
||||||
|
setSecretVar SAUCE_ACCESS_KEY $(echo $SAUCE_ACCESS_KEY | rev)
|
||||||
|
- run:
|
||||||
|
name: Starting Saucelabs tunnel
|
||||||
|
command: ./scripts/saucelabs/start-tunnel.sh
|
||||||
|
background: true
|
||||||
|
- run: yarn tsc -p packages
|
||||||
|
- run: yarn tsc -p modules
|
||||||
|
# Waits for the Saucelabs tunnel to be ready. This ensures that we don't run tests
|
||||||
|
# too early without Saucelabs not being ready.
|
||||||
|
- run: ./scripts/saucelabs/wait-for-tunnel.sh
|
||||||
|
- run: yarn karma start ./karma-js.conf.js --single-run --browsers=${KARMA_JS_BROWSERS}
|
||||||
|
- run: ./scripts/saucelabs/stop-tunnel.sh
|
||||||
|
|
||||||
|
legacy-misc-tests:
|
||||||
|
<<: *job_defaults
|
||||||
|
steps:
|
||||||
|
- *attach_workspace
|
||||||
|
- *init_environment
|
||||||
|
- run: yarn gulp check-cycle
|
||||||
|
# TODO: disabled because the Bazel packages-dist does not seem to have map files for
|
||||||
|
# the ESM5/ES2015 output. See: https://github.com/angular/angular/issues/27966
|
||||||
|
# - run: yarn gulp source-map-test
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
version: 2
|
version: 2
|
||||||
default_workflow:
|
default_workflow:
|
||||||
jobs:
|
jobs:
|
||||||
- lint
|
- setup
|
||||||
- test
|
- lint:
|
||||||
- test_ivy_aot
|
requires:
|
||||||
- build-packages-dist
|
- setup
|
||||||
- test_aio
|
- test:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
|
- test_ivy_aot:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
|
- build-npm-packages:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
|
- test_aio:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
- deploy_aio:
|
- deploy_aio:
|
||||||
requires:
|
requires:
|
||||||
- test_aio
|
- test_aio
|
||||||
|
- legacy-misc-tests:
|
||||||
|
requires:
|
||||||
|
- build-npm-packages
|
||||||
- test_aio_local:
|
- test_aio_local:
|
||||||
requires:
|
requires:
|
||||||
- build-packages-dist
|
- build-npm-packages
|
||||||
|
# - test_aio_local_ivy:
|
||||||
|
# requires:
|
||||||
|
# - build-npm-packages
|
||||||
- test_aio_tools:
|
- test_aio_tools:
|
||||||
requires:
|
requires:
|
||||||
- build-packages-dist
|
- build-npm-packages
|
||||||
- test_docs_examples_0:
|
- test_docs_examples:
|
||||||
requires:
|
requires:
|
||||||
- build-packages-dist
|
- build-npm-packages
|
||||||
- test_docs_examples_1:
|
# - test_docs_examples_ivy:
|
||||||
requires:
|
# requires:
|
||||||
- build-packages-dist
|
# - build-npm-packages
|
||||||
- aio_preview:
|
- aio_preview:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
# Only run on PR builds. (There can be no previews for non-PR builds.)
|
# Only run on PR builds. (There can be no previews for non-PR builds.)
|
||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
@ -433,7 +562,7 @@ workflows:
|
|||||||
- aio_preview
|
- aio_preview
|
||||||
- integration_test:
|
- integration_test:
|
||||||
requires:
|
requires:
|
||||||
- build-packages-dist
|
- build-npm-packages
|
||||||
- publish_snapshot:
|
- publish_snapshot:
|
||||||
# Note: no filters on this job because we want it to run for all upstream branches
|
# Note: no filters on this job because we want it to run for all upstream branches
|
||||||
# We'd really like to filter out pull requests here, but not yet available:
|
# We'd really like to filter out pull requests here, but not yet available:
|
||||||
@ -446,19 +575,44 @@ workflows:
|
|||||||
- integration_test
|
- integration_test
|
||||||
# Only publish if `aio`/`docs` tests using the locally built Angular packages pass
|
# Only publish if `aio`/`docs` tests using the locally built Angular packages pass
|
||||||
- test_aio_local
|
- test_aio_local
|
||||||
- test_docs_examples_0
|
# - test_aio_local_ivy
|
||||||
- test_docs_examples_1
|
- test_docs_examples
|
||||||
|
# - test_docs_examples_ivy
|
||||||
# Get the artifacts to publish from the build-packages-dist job
|
# Get the artifacts to publish from the build-packages-dist job
|
||||||
# since the publishing script expects the legacy outputs layout.
|
# since the publishing script expects the legacy outputs layout.
|
||||||
- build-packages-dist
|
- build-npm-packages
|
||||||
|
- legacy-misc-tests
|
||||||
|
|
||||||
|
saucelabs_tests:
|
||||||
|
jobs:
|
||||||
|
- setup
|
||||||
|
- legacy-unit-tests-saucelabs:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
|
triggers:
|
||||||
|
- schedule:
|
||||||
|
# Runs the Saucelabs legacy tests every hour. We still want to run Saucelabs
|
||||||
|
# frequently as the caretaker needs up-to-date results when merging PRs or creating
|
||||||
|
# a new release. Also we primarily moved the Saucelabs job into a cronjob that doesn't
|
||||||
|
# run for PRs, in order to ensure that PRs are not affected by Saucelabs flakiness or
|
||||||
|
# incidents. This is still guaranteed (even if we run the job every hour).
|
||||||
|
cron: "0 * * * *"
|
||||||
|
filters: *publish_branches_filter
|
||||||
|
|
||||||
aio_monitoring:
|
aio_monitoring:
|
||||||
jobs:
|
jobs:
|
||||||
- aio_monitoring
|
- aio_monitoring
|
||||||
triggers:
|
triggers:
|
||||||
- schedule:
|
- schedule:
|
||||||
|
# Runs AIO monitoring job at 00:00AM every day.
|
||||||
cron: "0 0 * * *"
|
cron: "0 0 * * *"
|
||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
|
|
||||||
|
# TODO:
|
||||||
|
# - don't build the g3 branch
|
||||||
|
# - verify that we are bootstrapping with the right yarn version coming from the docker image
|
||||||
|
# - check local chrome version pulled from docker image
|
||||||
|
# - remove /tools/ngcontainer
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#
|
#
|
||||||
# Usage: `setPublicVar <name> <value>`
|
# Usage: `setPublicVar <name> <value>`
|
||||||
function setPublicVar() {
|
function setPublicVar() {
|
||||||
setSecretVar $1 $2;
|
setSecretVar $1 "$2";
|
||||||
echo "$1=$2";
|
echo "$1=$2";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
readonly projectDir=$(realpath "$(dirname ${BASH_SOURCE[0]})/..")
|
||||||
|
readonly envHelpersPath="$projectDir/.circleci/env-helpers.inc.sh";
|
||||||
|
readonly getCommitRangePath="$projectDir/.circleci/get-commit-range.js";
|
||||||
|
|
||||||
# Load helpers and make them available everywhere (through `$BASH_ENV`).
|
# Load helpers and make them available everywhere (through `$BASH_ENV`).
|
||||||
readonly envHelpersPath="`dirname $0`/env-helpers.inc.sh";
|
|
||||||
source $envHelpersPath;
|
source $envHelpersPath;
|
||||||
echo "source $envHelpersPath;" >> $BASH_ENV;
|
echo "source $envHelpersPath;" >> $BASH_ENV;
|
||||||
|
|
||||||
@ -9,14 +13,22 @@ echo "source $envHelpersPath;" >> $BASH_ENV;
|
|||||||
####################################################################################################
|
####################################################################################################
|
||||||
# Define PUBLIC environment variables for CircleCI.
|
# Define PUBLIC environment variables for CircleCI.
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
setPublicVar PROJECT_ROOT "$(pwd)";
|
# See https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables for more info.
|
||||||
|
####################################################################################################
|
||||||
|
setPublicVar PROJECT_ROOT "$projectDir";
|
||||||
setPublicVar CI_AIO_MIN_PWA_SCORE "95";
|
setPublicVar CI_AIO_MIN_PWA_SCORE "95";
|
||||||
# This is the branch being built; e.g. `pull/12345` for PR builds.
|
# This is the branch being built; e.g. `pull/12345` for PR builds.
|
||||||
setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
|
setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
|
||||||
|
# ChromeDriver version compatible with the Chrome version included in the docker image used in
|
||||||
|
# `.circleci/config.yml`. See http://chromedriver.chromium.org/downloads for a list of versions.
|
||||||
|
# This variable is intended to be passed as an arg to the `webdriver-manager update` command (e.g.
|
||||||
|
# `"postinstall": "webdriver-manager update $CI_CHROMEDRIVER_VERSION_ARG"`).
|
||||||
|
setPublicVar CI_CHROMEDRIVER_VERSION_ARG "--versions.chrome 2.45";
|
||||||
setPublicVar CI_COMMIT "$CIRCLE_SHA1";
|
setPublicVar CI_COMMIT "$CIRCLE_SHA1";
|
||||||
# `CI_COMMIT_RANGE` will only be available when `CIRCLE_COMPARE_URL` is also available,
|
# `CI_COMMIT_RANGE` will only be available when `CIRCLE_COMPARE_URL` is also available (or can be
|
||||||
# i.e. on push builds (a.k.a. non-PR builds). That is fine, since we only need it in push builds.
|
# retrieved via `get-compare-url.js`), i.e. on push builds (a.k.a. non-PR, non-scheduled builds and
|
||||||
setPublicVar CI_COMMIT_RANGE "$(sed -r 's|^.*/([0-9a-f]+\.\.\.[0-9a-f]+)$|\1|i' <<< ${CIRCLE_COMPARE_URL:-})";
|
# rerun workflows of such builds). That is fine, since we only need it in push builds.
|
||||||
|
setPublicVar CI_COMMIT_RANGE "`[[ ${CIRCLE_PR_NUMBER:-false} != false ]] && echo "" || node $getCommitRangePath "$CIRCLE_BUILD_NUM" "$CIRCLE_COMPARE_URL"`";
|
||||||
setPublicVar CI_PULL_REQUEST "${CIRCLE_PR_NUMBER:-false}";
|
setPublicVar CI_PULL_REQUEST "${CIRCLE_PR_NUMBER:-false}";
|
||||||
setPublicVar CI_REPO_NAME "$CIRCLE_PROJECT_REPONAME";
|
setPublicVar CI_REPO_NAME "$CIRCLE_PROJECT_REPONAME";
|
||||||
setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
|
setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
|
||||||
@ -27,8 +39,27 @@ setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
|
|||||||
####################################################################################################
|
####################################################################################################
|
||||||
setSecretVar CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN "$AIO_DEPLOY_TOKEN";
|
setSecretVar CI_SECRET_AIO_DEPLOY_FIREBASE_TOKEN "$AIO_DEPLOY_TOKEN";
|
||||||
setSecretVar CI_SECRET_PAYLOAD_FIREBASE_TOKEN "$ANGULAR_PAYLOAD_TOKEN";
|
setSecretVar CI_SECRET_PAYLOAD_FIREBASE_TOKEN "$ANGULAR_PAYLOAD_TOKEN";
|
||||||
# Defined in https://angular-team.slack.com/apps/A0F7VRE7N-circleci.
|
|
||||||
setSecretVar CI_SECRET_SLACK_CARETAKER_WEBHOOK_URL "$SLACK_CARETAKER_WEBHOOK_URL";
|
|
||||||
|
####################################################################################################
|
||||||
|
# Define SauceLabs environment variables for CircleCI.
|
||||||
|
####################################################################################################
|
||||||
|
# In order to have a meaningful SauceLabs badge on the repo page,
|
||||||
|
# the angular2-ci account is used only when pushing commits to master;
|
||||||
|
# in all other cases, the regular angular-ci account is used.
|
||||||
|
if [ "${CI_PULL_REQUEST}" = "false" ] && [ "${CI_REPO_OWNER}" = "angular" ] && [ "${CI_BRANCH}" = "master" ]; then
|
||||||
|
setPublicVar SAUCE_USERNAME "angular2-ci";
|
||||||
|
setSecretVar SAUCE_ACCESS_KEY "693ebc16208a-0b5b-1614-8d66-a2662f4e";
|
||||||
|
else
|
||||||
|
setPublicVar SAUCE_USERNAME "angular-ci";
|
||||||
|
setSecretVar SAUCE_ACCESS_KEY "9b988f434ff8-fbca-8aa4-4ae3-35442987";
|
||||||
|
fi
|
||||||
|
setPublicVar SAUCE_READY_FILE /tmp/angular/sauce-connect-ready-file.lock
|
||||||
|
setPublicVar SAUCE_PID_FILE /tmp/angular/sauce-connect-pid-file.lock
|
||||||
|
setPublicVar SAUCE_TUNNEL_IDENTIFIER "angular-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_INDEX}"
|
||||||
|
# Amount of seconds we wait for sauceconnect to establish a tunnel instance. In order to not
|
||||||
|
# acquire CircleCI instances for too long if sauceconnect failed, we need a connect timeout.
|
||||||
|
setPublicVar SAUCE_READY_FILE_TIMEOUT 120
|
||||||
|
|
||||||
|
|
||||||
# Source `$BASH_ENV` to make the variables available immediately.
|
# Source `$BASH_ENV` to make the variables available immediately.
|
||||||
|
159
.circleci/get-commit-range.js
Normal file
159
.circleci/get-commit-range.js
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
/**
|
||||||
|
* **Usage:**
|
||||||
|
* ```
|
||||||
|
* node get-commit-range <build-number> [<compare-url> [<circle-token>]]
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Returns the value of the `CIRCLE_COMPARE_URL` environment variable (if defined) or, if this is
|
||||||
|
* not a PR build (i.e. `CIRCLE_PR_NUMBER` is not defined), retrieves the equivalent of
|
||||||
|
* `CIRCLE_COMPARE_URL` for jobs that are part of a rerun workflow.
|
||||||
|
*
|
||||||
|
* **Context:**
|
||||||
|
* CircleCI sets the `CIRCLE_COMPARE_URL` environment variable (from which we can extract the commit
|
||||||
|
* range) on push builds (a.k.a. non-PR, non-scheduled builds). Yet, when a workflow is rerun
|
||||||
|
* (either from the beginning or from failed jobs) - e.g. when a job flakes - CircleCI does not set
|
||||||
|
* the `CIRCLE_COMPARE_URL`.
|
||||||
|
*
|
||||||
|
* **Implementation details:**
|
||||||
|
* This script relies on the fact that all rerun workflows share the same CircleCI workspace and the
|
||||||
|
* (undocumented) fact that the workspace ID happens to be the same as the workflow ID that first
|
||||||
|
* created it.
|
||||||
|
*
|
||||||
|
* For example, for a job on push build workflow, the CircleCI API will return data that look like:
|
||||||
|
* ```js
|
||||||
|
* {
|
||||||
|
* compare: 'THE_COMPARE_URL_WE_ARE_LOOKING_FOR',
|
||||||
|
* //...
|
||||||
|
* previous: {
|
||||||
|
* // ...
|
||||||
|
* build_num: 12345,
|
||||||
|
* },
|
||||||
|
* //...
|
||||||
|
* workflows: {
|
||||||
|
* //...
|
||||||
|
* workflow_id: 'SOME_ID_A',
|
||||||
|
* workspace_id: 'SOME_ID_A', // Same as `workflow_id`.
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If the workflow is rerun, the data for jobs on the new workflow will look like:
|
||||||
|
* ```js
|
||||||
|
* {
|
||||||
|
* compare: null, // ¯\_(ツ)_/¯
|
||||||
|
* //...
|
||||||
|
* previous: {
|
||||||
|
* // ...
|
||||||
|
* build_num: 23456,
|
||||||
|
* },
|
||||||
|
* //...
|
||||||
|
* workflows: {
|
||||||
|
* //...
|
||||||
|
* workflow_id: 'SOME_ID_B',
|
||||||
|
* workspace_id: 'SOME_ID_A', // Different from current `workflow_id`.
|
||||||
|
* // Same as original `workflow_id`. \o/
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This script uses the `previous.build_num` (which points to the previous build number on the same
|
||||||
|
* branch) to traverse the jobs backwards, until it finds a job from the original workflow. Such a
|
||||||
|
* job (if found) should also contain the compare URL.
|
||||||
|
*
|
||||||
|
* **NOTE 1:**
|
||||||
|
* This is only useful on workflows which are created by rerunning a workflow for which
|
||||||
|
* `CIRCLE_COMPARE_URL` was defined.
|
||||||
|
*
|
||||||
|
* **NOTE 2:**
|
||||||
|
* The `circleToken` will be used for CircleCI API requests if provided, but it is not needed for
|
||||||
|
* accessing the read-only endpoints that we need (as long as the current project is FOSS and the
|
||||||
|
* corresponding setting is turned on in "Advanced Settings" in the project dashboard).
|
||||||
|
*
|
||||||
|
* ---
|
||||||
|
* Inspired by https://circleci.com/orbs/registry/orb/iynere/compare-url
|
||||||
|
* (source code: https://github.com/iynere/compare-url-orb).
|
||||||
|
*
|
||||||
|
* We are not using the `compare-url` orb for the following reasons:
|
||||||
|
* 1. (By looking at the code) it would only work if the rerun workflow is the latest workflow on
|
||||||
|
* the branch (which is not guaranteed to be true).
|
||||||
|
* 2. It is less efficient (e.g. makes unnecessary CircleCI API requests for builds on different
|
||||||
|
* branches, installs extra dependencies, persists files to the workspace (as a means of passing
|
||||||
|
* the result to the calling job), etc.).
|
||||||
|
* 3. It is slightly more complicated to setup and consume than our own script.
|
||||||
|
* 4. Its implementation is more complicated than needed for our usecase (e.g. handles different git
|
||||||
|
* providers, handles newly created branches, etc.).
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Imports
|
||||||
|
const {get: httpsGet} = require('https');
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
const API_URL_BASE = 'https://circleci.com/api/v1.1/project/github/angular/angular';
|
||||||
|
const COMPARE_URL_RE = /^.*\/([0-9a-f]+\.\.\.[0-9a-f]+)$/i;
|
||||||
|
|
||||||
|
// Run
|
||||||
|
_main(process.argv.slice(2));
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
async function _main([buildNumber, compareUrl = '', circleToken = '']) {
|
||||||
|
try {
|
||||||
|
if (!buildNumber || isNaN(buildNumber)) {
|
||||||
|
throw new Error(
|
||||||
|
'Missing or invalid arguments.\n' +
|
||||||
|
'Expected: buildNumber (number), compareUrl? (string), circleToken? (string)');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!compareUrl) {
|
||||||
|
compareUrl = await getCompareUrl(buildNumber, circleToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
const commitRangeMatch = COMPARE_URL_RE.exec(compareUrl)
|
||||||
|
const commitRange = commitRangeMatch ? commitRangeMatch[1] : '';
|
||||||
|
|
||||||
|
console.log(commitRange);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBuildInfo(buildNumber, circleToken) {
|
||||||
|
console.error(`BUILD ${buildNumber}`);
|
||||||
|
const url = `${API_URL_BASE}/${buildNumber}?circle-token=${circleToken}`;
|
||||||
|
return getJson(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getCompareUrl(buildNumber, circleToken) {
|
||||||
|
let info = await getBuildInfo(buildNumber, circleToken);
|
||||||
|
const targetWorkflowId = info.workflows.workspace_id;
|
||||||
|
|
||||||
|
while (info.workflows.workflow_id !== targetWorkflowId) {
|
||||||
|
info = await getBuildInfo(info.previous.build_num, circleToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
return info.compare || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function getJson(url) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const opts = {headers: {Accept: 'application/json'}};
|
||||||
|
const onResponse = res => {
|
||||||
|
const statusCode = res.statusCode || -1;
|
||||||
|
const isSuccess = (200 <= statusCode) && (statusCode <= 400);
|
||||||
|
let responseText = '';
|
||||||
|
|
||||||
|
res.
|
||||||
|
on('error', reject).
|
||||||
|
on('data', d => responseText += d).
|
||||||
|
on('end', () => isSuccess ?
|
||||||
|
resolve(JSON.parse(responseText)) :
|
||||||
|
reject(`Error getting '${url}' (status ${statusCode}):\n${responseText}`));
|
||||||
|
};
|
||||||
|
|
||||||
|
httpsGet(url, opts, onResponse).
|
||||||
|
on('error', reject).
|
||||||
|
end();
|
||||||
|
});
|
||||||
|
}
|
25
.github/CODEOWNERS
vendored
25
.github/CODEOWNERS
vendored
@ -54,6 +54,7 @@
|
|||||||
# kara - Kara Erickson
|
# kara - Kara Erickson
|
||||||
# kyliau - Keen Yee Liau
|
# kyliau - Keen Yee Liau
|
||||||
# matsko - Matias Niemelä
|
# matsko - Matias Niemelä
|
||||||
|
# mgechev - Minko Gechev
|
||||||
# mhevery - Misko Hevery
|
# mhevery - Misko Hevery
|
||||||
# ocombe - Olivier Combe
|
# ocombe - Olivier Combe
|
||||||
# petebacondarwin - Pete Bacon Darwin
|
# petebacondarwin - Pete Bacon Darwin
|
||||||
@ -93,6 +94,7 @@
|
|||||||
# Used for approving minor documentation-only changes that don't require engineering review.
|
# Used for approving minor documentation-only changes that don't require engineering review.
|
||||||
# (secret team to avoid review requests, it also doesn't inherit from @angular/framework because nested teams can't be secret)
|
# (secret team to avoid review requests, it also doesn't inherit from @angular/framework because nested teams can't be secret)
|
||||||
#
|
#
|
||||||
|
# - brandonroberts
|
||||||
# - gkalpak
|
# - gkalpak
|
||||||
# - jenniferfell
|
# - jenniferfell
|
||||||
# - petebacondarwin
|
# - petebacondarwin
|
||||||
@ -112,6 +114,7 @@
|
|||||||
# - alexeagle
|
# - alexeagle
|
||||||
# - kyliau
|
# - kyliau
|
||||||
# - IgorMinar
|
# - IgorMinar
|
||||||
|
# - mgechev
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -121,6 +124,7 @@
|
|||||||
# - alexeagle
|
# - alexeagle
|
||||||
# - filipesilva
|
# - filipesilva
|
||||||
# - hansl
|
# - hansl
|
||||||
|
# - mgechev
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -258,6 +262,7 @@
|
|||||||
# @angular/docs-infra
|
# @angular/docs-infra
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
#
|
#
|
||||||
|
# - brandonroberts
|
||||||
# - gkalpak
|
# - gkalpak
|
||||||
# - IgorMinar
|
# - IgorMinar
|
||||||
# - petebacondarwin
|
# - petebacondarwin
|
||||||
@ -308,6 +313,8 @@
|
|||||||
# ===========================================================
|
# ===========================================================
|
||||||
#
|
#
|
||||||
# - alexeagle
|
# - alexeagle
|
||||||
|
# - filipesilva
|
||||||
|
# - gkalpak
|
||||||
# - IgorMinar
|
# - IgorMinar
|
||||||
|
|
||||||
|
|
||||||
@ -724,20 +731,13 @@ testing/** @angular/fw-test
|
|||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/aio/content/marketing/** @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/marketing/** @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/images/bios/** @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/marketing/** @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/marketing/** @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/navigation.json @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/navigation.json @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/license.md @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/license.md @angular/fw-docs-marketing @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
|
||||||
# Public API
|
|
||||||
# ================================================
|
|
||||||
|
|
||||||
/tools/public_api_guard/** @angular/fw-public-api
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
# Build & CI Owners
|
# Build & CI Owners
|
||||||
# ================================================
|
# ================================================
|
||||||
@ -747,6 +747,7 @@ testing/** @angular/fw-test
|
|||||||
/.circleci/** @angular/fw-dev-infra
|
/.circleci/** @angular/fw-dev-infra
|
||||||
/.github/** @angular/fw-dev-infra
|
/.github/** @angular/fw-dev-infra
|
||||||
/docs/BAZEL.md @angular/fw-dev-infra
|
/docs/BAZEL.md @angular/fw-dev-infra
|
||||||
|
/packages/* @angular/fw-dev-infra
|
||||||
/scripts/** @angular/fw-dev-infra
|
/scripts/** @angular/fw-dev-infra
|
||||||
/third_party/** @angular/fw-dev-infra
|
/third_party/** @angular/fw-dev-infra
|
||||||
/tools/** @angular/fw-dev-infra
|
/tools/** @angular/fw-dev-infra
|
||||||
@ -754,6 +755,14 @@ testing/** @angular/fw-test
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ================================================
|
||||||
|
# Public API
|
||||||
|
# ================================================
|
||||||
|
|
||||||
|
/tools/public_api_guard/** @angular/fw-public-api
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
# CODEOWNERS Owners owners ...
|
# CODEOWNERS Owners owners ...
|
||||||
# ================================================
|
# ================================================
|
||||||
|
8
.github/angular-robot.yml
vendored
8
.github/angular-robot.yml
vendored
@ -56,9 +56,9 @@ merge:
|
|||||||
- "**/.gitkeep"
|
- "**/.gitkeep"
|
||||||
- "**/yarn.lock"
|
- "**/yarn.lock"
|
||||||
- "**/package.json"
|
- "**/package.json"
|
||||||
|
- "**/third_party/**"
|
||||||
- "**/tsconfig-build.json"
|
- "**/tsconfig-build.json"
|
||||||
- "**/tsconfig.json"
|
- "**/tsconfig.json"
|
||||||
- "**/rollup.config.js"
|
|
||||||
- "**/BUILD.bazel"
|
- "**/BUILD.bazel"
|
||||||
- "**/*.md"
|
- "**/*.md"
|
||||||
- "packages/**/integrationtest/**"
|
- "packages/**/integrationtest/**"
|
||||||
@ -101,9 +101,13 @@ merge:
|
|||||||
|
|
||||||
# list of PR statuses that need to be successful
|
# list of PR statuses that need to be successful
|
||||||
requiredStatuses:
|
requiredStatuses:
|
||||||
- "continuous-integration/travis-ci/pr"
|
|
||||||
- "ci/circleci: build"
|
- "ci/circleci: build"
|
||||||
- "ci/circleci: lint"
|
- "ci/circleci: lint"
|
||||||
|
- "ci/circleci: publish_snapshot"
|
||||||
|
- "ci/angular: size"
|
||||||
|
- "cla/google"
|
||||||
|
- "google3"
|
||||||
|
|
||||||
|
|
||||||
# the comment that will be added when the merge label is added despite failing checks, leave empty or set to false to disable
|
# 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
|
# {{MERGE_LABEL}} will be replaced by the value of the mergeLabel option
|
||||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,7 +1,7 @@
|
|||||||
.DS_STORE
|
.DS_STORE
|
||||||
|
|
||||||
/dist/
|
/dist/
|
||||||
/bazel-*
|
/bazel-out/
|
||||||
/integration/bazel/bazel-*
|
/integration/bazel/bazel-*
|
||||||
e2e_test.*
|
e2e_test.*
|
||||||
node_modules
|
node_modules
|
||||||
@ -13,9 +13,9 @@ pubspec.lock
|
|||||||
.c9
|
.c9
|
||||||
.idea/
|
.idea/
|
||||||
.settings/
|
.settings/
|
||||||
|
.vscode/launch.json
|
||||||
*.swo
|
*.swo
|
||||||
modules/.settings
|
modules/.settings
|
||||||
.vscode
|
|
||||||
modules/.vscode
|
modules/.vscode
|
||||||
|
|
||||||
# Don't check in secret files
|
# Don't check in secret files
|
||||||
|
66
.travis.yml
66
.travis.yml
@ -1,66 +0,0 @@
|
|||||||
language: node_js
|
|
||||||
sudo: false
|
|
||||||
dist: trusty
|
|
||||||
node_js:
|
|
||||||
- '10.9.0'
|
|
||||||
|
|
||||||
addons:
|
|
||||||
# firefox: "38.0"
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
# needed to install g++ that is used by npms's native modules
|
|
||||||
- ubuntu-toolchain-r-test
|
|
||||||
packages:
|
|
||||||
# needed to install g++ that is used by npms's native modules
|
|
||||||
- g++-4.8
|
|
||||||
|
|
||||||
branches:
|
|
||||||
except:
|
|
||||||
- g3
|
|
||||||
|
|
||||||
cache:
|
|
||||||
yarn: true
|
|
||||||
directories:
|
|
||||||
- ./node_modules
|
|
||||||
- ./.chrome/chromium
|
|
||||||
- ./aio/node_modules
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
# GITHUB_TOKEN_ANGULAR=<github token, a personal access token of the angular-builds account, account access in valentine>
|
|
||||||
# This is needed for the e2e Travis matrix task to publish packages to github for continuous packages delivery.
|
|
||||||
- secure: "aCdHveZuY8AT4Jr1JoJB4LxZsnGWRe/KseZh1YXYe5UtufFCtTVHvUcLn0j2aLBF0KpdyS+hWf0i4np9jthKu2xPKriefoPgCMpisYeC0MFkwbmv+XlgkUbgkgVZMGiVyX7DCYXVahxIoOUjVMEDCbNiHTIrfEuyq24U3ok2tHc="
|
|
||||||
matrix:
|
|
||||||
# Order: a slower build first, so that we don't occupy an idle travis worker waiting for others to complete.
|
|
||||||
- CI_MODE=e2e
|
|
||||||
- CI_MODE=js
|
|
||||||
- CI_MODE=saucelabs_required
|
|
||||||
# deactivated, see #19768
|
|
||||||
# - CI_MODE=browserstack_required
|
|
||||||
|
|
||||||
# We disable these optional jobs because those acquire tunnel and browser instances which
|
|
||||||
# could lead to rate limit excess while those are failing most of the time and nobody pays
|
|
||||||
# attention anyway.
|
|
||||||
# - CI_MODE=saucelabs_optional
|
|
||||||
# - CI_MODE=browserstack_optional
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
fast_finish: true
|
|
||||||
allow_failures:
|
|
||||||
- env: "CI_MODE=saucelabs_optional"
|
|
||||||
- env: "CI_MODE=browserstack_optional"
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
# source the env.sh script so that the exported variables are available to other scripts later on
|
|
||||||
- source ./scripts/ci/env.sh print
|
|
||||||
|
|
||||||
install:
|
|
||||||
- ./scripts/ci/install.sh
|
|
||||||
|
|
||||||
script:
|
|
||||||
- ./scripts/ci/build.sh
|
|
||||||
- ./scripts/ci/test.sh
|
|
||||||
- ./scripts/ci/angular.sh
|
|
||||||
# all the scripts under this line will not quickly abort in case ${TRAVIS_TEST_RESULT} is 1 (job failure)
|
|
||||||
- ./scripts/ci/cleanup.sh
|
|
||||||
- ./scripts/ci/print-logs.sh
|
|
15
.vscode/settings.json
vendored
Normal file
15
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"files.watcherExclude": {
|
||||||
|
"**/.git/objects/**": true,
|
||||||
|
"**/.git/subtree-cache/**": true,
|
||||||
|
"**/node_modules/**": true,
|
||||||
|
"**/bazel-out/**": true,
|
||||||
|
"**/dist/**": true,
|
||||||
|
},
|
||||||
|
"search.exclude": {
|
||||||
|
"**/node_modules": true,
|
||||||
|
"**/bower_components": true,
|
||||||
|
"**/bazel-out": true,
|
||||||
|
"**/dist": true,
|
||||||
|
},
|
||||||
|
}
|
212
CHANGELOG.md
212
CHANGELOG.md
@ -1,39 +1,167 @@
|
|||||||
<a name="7.2.0"></a>
|
<a name="7.2.7"></a>
|
||||||
# [7.2.0](https://github.com/angular/angular/compare/7.2.0-rc.0...7.2.0) (2019-01-07)
|
## [7.2.7](https://github.com/angular/angular/compare/7.2.6...7.2.7) (2019-02-27)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **bazel:** unable to launch protractor test on windows ([#27850](https://github.com/angular/angular/issues/27850)) ([1e6c9be](https://github.com/angular/angular/commit/1e6c9be))
|
* **bazel:** pin browser repositories using [@npm](https://github.com/npm)_bazel_karma//:browser_repositories.bzl in bazel schematics ([#28896](https://github.com/angular/angular/issues/28896)) ([b686449](https://github.com/angular/angular/commit/b686449))
|
||||||
|
* **core:** traverse and sanitize content of unsafe elements ([#28804](https://github.com/angular/angular/issues/28804)) ([fdcf877](https://github.com/angular/angular/commit/fdcf877)), closes [#25879](https://github.com/angular/angular/issues/25879) [#25879](https://github.com/angular/angular/issues/25879) [#26007](https://github.com/angular/angular/issues/26007) [#28427](https://github.com/angular/angular/issues/28427)
|
||||||
|
* **language-service:** Fix completions for input/output with alias ([#28904](https://github.com/angular/angular/issues/28904)) ([d0018e6](https://github.com/angular/angular/commit/d0018e6)), closes [#27959](https://github.com/angular/angular/issues/27959)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="7.2.6"></a>
|
||||||
|
## [7.2.6](https://github.com/angular/angular/compare/7.2.5...7.2.6) (2019-02-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **compiler-cli:** incorrect bundled metadata for static class member call expressions ([#28762](https://github.com/angular/angular/issues/28762)) ([ab69c31](https://github.com/angular/angular/commit/ab69c31)), closes [/github.com/angular/angular/blob/master/packages/core/src/change_detection/differs/keyvalue_differs.ts#L121](https://github.com//github.com/angular/angular/blob/master/packages/core/src/change_detection/differs/keyvalue_differs.ts/issues/L121) [#28741](https://github.com/angular/angular/issues/28741)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="7.2.5"></a>
|
||||||
|
## [7.2.5](https://github.com/angular/angular/compare/7.2.4...7.2.5) (2019-02-15)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **compiler-cli:** diagnostics should respect "newLine" compiler option ([#28550](https://github.com/angular/angular/issues/28550)) ([ce750e6](https://github.com/angular/angular/commit/ce750e6))
|
||||||
|
* **router:** redirect to root url when returned as UrlTree from guard ([#28271](https://github.com/angular/angular/issues/28271)) ([1e58a21](https://github.com/angular/angular/commit/1e58a21)), closes [#27845](https://github.com/angular/angular/issues/27845)
|
||||||
|
* **router:** set href when routerLink is used on an 'area' element ([#28441](https://github.com/angular/angular/issues/28441)) ([d491a20](https://github.com/angular/angular/commit/d491a20)), closes [#28401](https://github.com/angular/angular/issues/28401)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="7.2.4"></a>
|
||||||
|
## [7.2.4](https://github.com/angular/angular/compare/7.2.3...7.2.4) (2019-02-06)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** Bazel builder resolves with require.resolve() ([#28478](https://github.com/angular/angular/issues/28478)) ([d85d396](https://github.com/angular/angular/commit/d85d396))
|
||||||
|
* **bazel:** fix integration test for bazel-schematics ([#28460](https://github.com/angular/angular/issues/28460)) ([449da8c](https://github.com/angular/angular/commit/449da8c))
|
||||||
|
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* pngcrush all pngs ([#28479](https://github.com/angular/angular/issues/28479)) ([1a25144](https://github.com/angular/angular/commit/1a25144)), closes [#18243](https://github.com/angular/angular/issues/18243)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="7.2.3"></a>
|
||||||
|
## [7.2.3](https://github.com/angular/angular/compare/7.2.2...7.2.3) (2019-01-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** add [@npm](https://github.com/npm)//tslib dep to e2e ts_library target in bazel-workspace schematic ([#28358](https://github.com/angular/angular/issues/28358)) ([8cee56e](https://github.com/angular/angular/commit/8cee56e))
|
||||||
|
* **bazel:** Bazel-workspace schematics should run in ScopedTree ([#28349](https://github.com/angular/angular/issues/28349)) ([260ac20](https://github.com/angular/angular/commit/260ac20))
|
||||||
|
* **bazel:** Builder should invoke local bazel/iblaze ([#28303](https://github.com/angular/angular/issues/28303)) ([12b8a6e](https://github.com/angular/angular/commit/12b8a6e))
|
||||||
|
* **bazel:** ng-new should run yarn install ([#28381](https://github.com/angular/angular/issues/28381)) ([a9d46e4](https://github.com/angular/angular/commit/a9d46e4))
|
||||||
|
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* yarn version upgrade ([#28360](https://github.com/angular/angular/issues/28360)) ([cc1b2a5](https://github.com/angular/angular/commit/cc1b2a5))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="7.2.2"></a>
|
||||||
|
## [7.2.2](https://github.com/angular/angular/compare/7.2.1...7.2.2) (2019-01-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** Fix integration test after v8 bump ([#28194](https://github.com/angular/angular/issues/28194)) ([7b772e9](https://github.com/angular/angular/commit/7b772e9)), closes [#28142](https://github.com/angular/angular/issues/28142)
|
||||||
|
* **router:** `skipLocationChange` with named outlets ([#28301](https://github.com/angular/angular/issues/28301)) ([32737a6](https://github.com/angular/angular/commit/32737a6)), closes [#27680](https://github.com/angular/angular/issues/27680) [#28200](https://github.com/angular/angular/issues/28200)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **bazel:** Add support for SASS ([#28167](https://github.com/angular/angular/issues/28167)) ([a4d9192](https://github.com/angular/angular/commit/a4d9192))
|
||||||
|
* **compiler-cli:** resolve generated Sass/Less files to .css inputs ([#28166](https://github.com/angular/angular/issues/28166)) ([4c00059](https://github.com/angular/angular/commit/4c00059))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="7.2.1"></a>
|
||||||
|
## [7.2.1](https://github.com/angular/angular/compare/7.2.0...7.2.1) (2019-01-16)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** Add [@bazel](https://github.com/bazel)/bazel to dev deps ([#28032](https://github.com/angular/angular/issues/28032)) ([21093b9](https://github.com/angular/angular/commit/21093b9))
|
||||||
|
* **bazel:** Add /bazel-out to .gitignore ([#27874](https://github.com/angular/angular/issues/27874)) ([e4fc8ba](https://github.com/angular/angular/commit/e4fc8ba))
|
||||||
|
* **bazel:** Add ibazel to deps of Bazel project ([#28090](https://github.com/angular/angular/issues/28090)) ([28d34b6](https://github.com/angular/angular/commit/28d34b6))
|
||||||
|
* **bazel:** Bazel schematics should add router package ([#28141](https://github.com/angular/angular/issues/28141)) ([02a852a](https://github.com/angular/angular/commit/02a852a))
|
||||||
|
* **bazel:** flat module misses AMD module name on windows ([#27839](https://github.com/angular/angular/issues/27839)) ([c3d8e28](https://github.com/angular/angular/commit/c3d8e28))
|
||||||
|
* **bazel:** incorrectly always uses ngc-wrapped from "npm" workspace ([#28137](https://github.com/angular/angular/issues/28137)) ([ca3965a](https://github.com/angular/angular/commit/ca3965a))
|
||||||
|
* **bazel:** ng_package creates invalid typings reexport on windows ([#27829](https://github.com/angular/angular/issues/27829)) ([6b394f6](https://github.com/angular/angular/commit/6b394f6))
|
||||||
|
* **bazel:** packager not properly removing amd directives on windows ([#27829](https://github.com/angular/angular/issues/27829)) ([fad4145](https://github.com/angular/angular/commit/fad4145))
|
||||||
|
* **bazel:** protractor rule does not run spec files with underscore ([#28022](https://github.com/angular/angular/issues/28022)) ([f05c5f8](https://github.com/angular/angular/commit/f05c5f8))
|
||||||
|
* **bazel:** protractor utils cannot start server on windows ([#27915](https://github.com/angular/angular/issues/27915)) ([0be8487](https://github.com/angular/angular/commit/0be8487))
|
||||||
|
* **bazel:** replay compilation uses wrong compiler for building esm5 ([#28053](https://github.com/angular/angular/issues/28053)) ([fbbdaaa](https://github.com/angular/angular/commit/fbbdaaa))
|
||||||
|
* **router:** ensure URL is updated after second redirect with UrlUpdateStrategy="eager" ([#27680](https://github.com/angular/angular/issues/27680)) ([6ae7aee](https://github.com/angular/angular/commit/6ae7aee)), closes [#27116](https://github.com/angular/angular/issues/27116)
|
||||||
|
* **service-worker:** navigation urls backwards compatibility ([#27244](https://github.com/angular/angular/issues/27244)) ([585e871](https://github.com/angular/angular/commit/585e871))
|
||||||
|
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* **platform-server:** use shared `DomElementSchemaRegistry` instance ([#28150](https://github.com/angular/angular/issues/28150)) ([#28151](https://github.com/angular/angular/issues/28151)) ([6851581](https://github.com/angular/angular/commit/6851581))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="7.2.0"></a>
|
||||||
|
# [7.2.0](https://github.com/angular/angular/compare/7.1.4...7.2.0) (2019-01-07)
|
||||||
|
|
||||||
|
7.2.0 release also contains all the fixes released in 7.1.4.
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add support for typescript 3.2 ([#27536](https://github.com/angular/angular/issues/27536)) ([17e702b](https://github.com/angular/angular/commit/17e702b))
|
||||||
|
* **bazel:** ng-new schematics with Bazel ([#27277](https://github.com/angular/angular/issues/27277)) ([06d4a0c](https://github.com/angular/angular/commit/06d4a0c))
|
||||||
* **forms:** match getError and hasError to get method signature ([#20211](https://github.com/angular/angular/issues/20211)) ([1b0b36d](https://github.com/angular/angular/commit/1b0b36d))
|
* **forms:** match getError and hasError to get method signature ([#20211](https://github.com/angular/angular/issues/20211)) ([1b0b36d](https://github.com/angular/angular/commit/1b0b36d))
|
||||||
* **upgrade:** allow nesting components from different downgraded modules ([#27217](https://github.com/angular/angular/issues/27217)) ([bc0ee01](https://github.com/angular/angular/commit/bc0ee01))
|
* **router:** add predicate function mode for runGuardsAndResolvers ([#27682](https://github.com/angular/angular/issues/27682)) ([12c3176](https://github.com/angular/angular/commit/12c3176)), closes [#26861](https://github.com/angular/angular/issues/26861) [#18253](https://github.com/angular/angular/issues/18253) [#27464](https://github.com/angular/angular/issues/27464)
|
||||||
* **upgrade:** correctly handle nested downgraded components with `downgradeModule()` ([#27217](https://github.com/angular/angular/issues/27217)) ([326b464](https://github.com/angular/angular/commit/326b464)), closes [#22581](https://github.com/angular/angular/issues/22581) [#22869](https://github.com/angular/angular/issues/22869) [#27083](https://github.com/angular/angular/issues/27083)
|
* **router:** add a Navigation type available during navigation ([#27198](https://github.com/angular/angular/issues/27198)) ([d40af0c](https://github.com/angular/angular/commit/d40af0c))
|
||||||
|
* **router:** add pathParamsOrQueryParamsChange mode for runGuardsAndResolvers ([#27464](https://github.com/angular/angular/issues/27464)) ([d70a7f3](https://github.com/angular/angular/commit/d70a7f3)), closes [#26861](https://github.com/angular/angular/issues/26861) [#18253](https://github.com/angular/angular/issues/18253)
|
||||||
|
* **router:** allow passing `state` to routerLink directives ([#27198](https://github.com/angular/angular/issues/27198)) ([73f6ed9](https://github.com/angular/angular/commit/73f6ed9)), closes [#24617](https://github.com/angular/angular/issues/24617)
|
||||||
<a name="7.2.0-rc.0"></a>
|
* **router:** allow passing state to `NavigationExtras` ([#27198](https://github.com/angular/angular/issues/27198)) ([67f4a5d](https://github.com/angular/angular/commit/67f4a5d))
|
||||||
# [7.2.0-rc.0](https://github.com/angular/angular/compare/7.2.0-beta.2...7.2.0-rc.0) (2018-12-18)
|
* **router:** restore whole object when navigating back to a page managed by Angular router ([#27198](https://github.com/angular/angular/issues/27198)) ([2684249](https://github.com/angular/angular/commit/2684249))
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **animations:** do not truncate decimals for delay ([#24455](https://github.com/angular/angular/issues/24455)) ([f1c9d6a](https://github.com/angular/angular/commit/f1c9d6a))
|
* **animations:** do not truncate decimals for delay ([#24455](https://github.com/angular/angular/issues/24455)) ([f1c9d6a](https://github.com/angular/angular/commit/f1c9d6a))
|
||||||
* **animations:** mark actual descendant node as disabled ([#26180](https://github.com/angular/angular/issues/26180)) ([df123e0](https://github.com/angular/angular/commit/df123e0))
|
* **animations:** mark actual descendant node as disabled ([#26180](https://github.com/angular/angular/issues/26180)) ([df123e0](https://github.com/angular/angular/commit/df123e0))
|
||||||
|
* **bazel:** unable to launch protractor test on windows ([#27850](https://github.com/angular/angular/issues/27850)) ([1e6c9be](https://github.com/angular/angular/commit/1e6c9be))
|
||||||
* **bazel:** devserver entry_module should have underscore name ([#27719](https://github.com/angular/angular/issues/27719)) ([f57916c](https://github.com/angular/angular/commit/f57916c))
|
* **bazel:** devserver entry_module should have underscore name ([#27719](https://github.com/angular/angular/issues/27719)) ([f57916c](https://github.com/angular/angular/commit/f57916c))
|
||||||
* **bazel:** emit full node stack traces when Angular compilation crashes ([#27678](https://github.com/angular/angular/issues/27678)) ([522919a](https://github.com/angular/angular/commit/522919a))
|
* **bazel:** emit full node stack traces when Angular compilation crashes ([#27678](https://github.com/angular/angular/issues/27678)) ([522919a](https://github.com/angular/angular/commit/522919a))
|
||||||
* **bazel:** fix major/minor semver check between [@angular](https://github.com/angular)/bazel npm packager version and angular bazel repo version ([#27635](https://github.com/angular/angular/issues/27635)) ([1cc08b4](https://github.com/angular/angular/commit/1cc08b4))
|
* **bazel:** fix major/minor semver check between [@angular](https://github.com/angular)/bazel npm packager version and angular bazel repo version ([#27635](https://github.com/angular/angular/issues/27635)) ([1cc08b4](https://github.com/angular/angular/commit/1cc08b4))
|
||||||
* **bazel:** Load http_archive and rules_nodejs dependencies ([#27609](https://github.com/angular/angular/issues/27609)) ([8313ffc](https://github.com/angular/angular/commit/8313ffc))
|
* **bazel:** Load http_archive and rules_nodejs dependencies ([#27609](https://github.com/angular/angular/issues/27609)) ([8313ffc](https://github.com/angular/angular/commit/8313ffc))
|
||||||
* **bazel:** ng_package writes unrelevant definitions to bazel out ([#27519](https://github.com/angular/angular/issues/27519)) ([44dfa60](https://github.com/angular/angular/commit/44dfa60)), closes [/github.com/angular/angular/blob/4f9374951d67c75f67a31c110bd61ab72563db7d/packages/bazel/src/ng_package/packager.ts#L105-L124](https://github.com//github.com/angular/angular/blob/4f9374951d67c75f67a31c110bd61ab72563db7d/packages/bazel/src/ng_package/packager.ts/issues/L105-L124)
|
* **bazel:** ng_package writes unrelevant definitions to bazel out ([#27519](https://github.com/angular/angular/issues/27519)) ([44dfa60](https://github.com/angular/angular/commit/44dfa60)), closes [/github.com/angular/angular/blob/4f9374951d67c75f67a31c110bd61ab72563db7d/packages/bazel/src/ng_package/packager.ts#L105-L124](https://github.com//github.com/angular/angular/blob/4f9374951d67c75f67a31c110bd61ab72563db7d/packages/bazel/src/ng_package/packager.ts/issues/L105-L124)
|
||||||
* **bazel:** Set module_name and enable ng test ([#27715](https://github.com/angular/angular/issues/27715)) ([85866de](https://github.com/angular/angular/commit/85866de))
|
* **bazel:** Set module_name and enable ng test ([#27715](https://github.com/angular/angular/issues/27715)) ([85866de](https://github.com/angular/angular/commit/85866de))
|
||||||
|
* **bazel:** fix TS errors in the `schematics/bazel-workspace` files ([#27600](https://github.com/angular/angular/issues/27600)) ([3290fc3](https://github.com/angular/angular/commit/3290fc3))
|
||||||
|
* **bazel:** Read latest versions from latest-versions.ts & use semver check ([#27526](https://github.com/angular/angular/issues/27526)) ([30a3b49](https://github.com/angular/angular/commit/30a3b49))
|
||||||
|
* **bazel:** tsickle dependency not working with typescript 3.1.x ([#27402](https://github.com/angular/angular/issues/27402)) ([f034114](https://github.com/angular/angular/commit/f034114))
|
||||||
|
* **bazel:** do not throw error when writing tsickle externs ([#27200](https://github.com/angular/angular/issues/27200)) ([20a2bae](https://github.com/angular/angular/commit/20a2bae))
|
||||||
|
* **bazel:** do not throw if ts compile action does not create esm5 outputs ([#27401](https://github.com/angular/angular/issues/27401)) ([c61a8b7](https://github.com/angular/angular/commit/c61a8b7))
|
||||||
|
* **bazel:** ng_package cannot be run multiple times without clean ([#27200](https://github.com/angular/angular/issues/27200)) ([4f93749](https://github.com/angular/angular/commit/4f93749))
|
||||||
|
* **bazel:** ng_package not generating UMD bundles on windows ([#27200](https://github.com/angular/angular/issues/27200)) ([7d59880](https://github.com/angular/angular/commit/7d59880))
|
||||||
|
* **bazel:** ng_package should correctly map to source maps in secondary entry-points ([#27313](https://github.com/angular/angular/issues/27313)) ([eb17502](https://github.com/angular/angular/commit/eb17502)), closes [#25510](https://github.com/angular/angular/issues/25510)
|
||||||
|
* **bazel:** Respect existing angular installation ([#27495](https://github.com/angular/angular/issues/27495)) ([4da739a](https://github.com/angular/angular/commit/4da739a))
|
||||||
* **common:** KeyValuePipe should return empty array for empty objects ([#27258](https://github.com/angular/angular/issues/27258)) ([b39efdd](https://github.com/angular/angular/commit/b39efdd))
|
* **common:** KeyValuePipe should return empty array for empty objects ([#27258](https://github.com/angular/angular/issues/27258)) ([b39efdd](https://github.com/angular/angular/commit/b39efdd))
|
||||||
|
* **common:** expose request url in network error ([#27143](https://github.com/angular/angular/issues/27143)) ([1db53da](https://github.com/angular/angular/commit/1db53da)), closes [#27029](https://github.com/angular/angular/issues/27029)
|
||||||
* **compiler-cli:** create LiteralLikeNode for String and Number literal ([#27536](https://github.com/angular/angular/issues/27536)) ([2c9b6c0](https://github.com/angular/angular/commit/2c9b6c0))
|
* **compiler-cli:** create LiteralLikeNode for String and Number literal ([#27536](https://github.com/angular/angular/issues/27536)) ([2c9b6c0](https://github.com/angular/angular/commit/2c9b6c0))
|
||||||
|
* **compiler-cli:** flatModuleIndex files not generated on windows with multiple input files ([#27200](https://github.com/angular/angular/issues/27200)) ([d3c08e7](https://github.com/angular/angular/commit/d3c08e7))
|
||||||
|
* **core:** export a value for InjectFlags ([#27279](https://github.com/angular/angular/issues/27279)) ([23b06af](https://github.com/angular/angular/commit/23b06af)), closes [#27251](https://github.com/angular/angular/issues/27251)
|
||||||
|
* **core:** More precise return type for `InjectableDecorator` ([#27360](https://github.com/angular/angular/issues/27360)) ([4b9948c](https://github.com/angular/angular/commit/4b9948c)), closes [#26942](https://github.com/angular/angular/issues/26942)
|
||||||
|
* **forms:** typed argument for FormBuilder group ([#26985](https://github.com/angular/angular/issues/26985)) ([b0c7561](https://github.com/angular/angular/commit/b0c7561))
|
||||||
|
* **platform-server:** add [@angular](https://github.com/angular)/http to the list of peerDependencies ([#27307](https://github.com/angular/angular/issues/27307)) ([32c5be9](https://github.com/angular/angular/commit/32c5be9)), closes [#26154](https://github.com/angular/angular/issues/26154)
|
||||||
* **router:** ensure URL is updated after second redirect with UrlUpdateStrategy="eager" ([#27523](https://github.com/angular/angular/issues/27523)) ([ad26cd6](https://github.com/angular/angular/commit/ad26cd6)), closes [#27116](https://github.com/angular/angular/issues/27116)
|
* **router:** ensure URL is updated after second redirect with UrlUpdateStrategy="eager" ([#27523](https://github.com/angular/angular/issues/27523)) ([ad26cd6](https://github.com/angular/angular/commit/ad26cd6)), closes [#27116](https://github.com/angular/angular/issues/27116)
|
||||||
|
* **router:** update URL after redirects when urlHandlingStrategy='eager' ([#27356](https://github.com/angular/angular/issues/27356)) ([11a8bd8](https://github.com/angular/angular/commit/11a8bd8)), closes [#27076](https://github.com/angular/angular/issues/27076)
|
||||||
|
* **upgrade:** allow nesting components from different downgraded modules ([#27217](https://github.com/angular/angular/issues/27217)) ([bc0ee01](https://github.com/angular/angular/commit/bc0ee01))
|
||||||
|
* **upgrade:** correctly handle nested downgraded components with `downgradeModule()` ([#27217](https://github.com/angular/angular/issues/27217)) ([326b464](https://github.com/angular/angular/commit/326b464)), closes [#22581](https://github.com/angular/angular/issues/22581) [#22869](https://github.com/angular/angular/issues/22869) [#27083](https://github.com/angular/angular/issues/27083)
|
||||||
* **upgrade:** upgrade Directive facade should not return different instance from constructor ([#27660](https://github.com/angular/angular/issues/27660)) ([c986d3d](https://github.com/angular/angular/commit/c986d3d))
|
* **upgrade:** upgrade Directive facade should not return different instance from constructor ([#27660](https://github.com/angular/angular/issues/27660)) ([c986d3d](https://github.com/angular/angular/commit/c986d3d))
|
||||||
|
* **upgrade:** don't rely upon the runtime to resolve forward refs ([#27132](https://github.com/angular/angular/issues/27132)) ([a4462c2](https://github.com/angular/angular/commit/a4462c2))
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* add support for typescript 3.2 ([#27536](https://github.com/angular/angular/issues/27536)) ([17e702b](https://github.com/angular/angular/commit/17e702b))
|
|
||||||
* **router:** add predicate function mode for runGuardsAndResolvers ([#27682](https://github.com/angular/angular/issues/27682)) ([12c3176](https://github.com/angular/angular/commit/12c3176)), closes [#26861](https://github.com/angular/angular/issues/26861) [#18253](https://github.com/angular/angular/issues/18253) [#27464](https://github.com/angular/angular/issues/27464)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -56,19 +184,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="7.2.0-beta.2"></a>
|
|
||||||
# [7.2.0-beta.2](https://github.com/angular/angular/compare/7.2.0-beta.1...7.2.0-beta.2) (2018-12-11)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **bazel:** fix TS errors in the `schematics/bazel-workspace` files ([#27600](https://github.com/angular/angular/issues/27600)) ([3290fc3](https://github.com/angular/angular/commit/3290fc3))
|
|
||||||
* **bazel:** Read latest versions from latest-versions.ts & use semver check ([#27526](https://github.com/angular/angular/issues/27526)) ([30a3b49](https://github.com/angular/angular/commit/30a3b49))
|
|
||||||
* **bazel:** tsickle dependency not working with typescript 3.1.x ([#27402](https://github.com/angular/angular/issues/27402)) ([f034114](https://github.com/angular/angular/commit/f034114))
|
|
||||||
* **forms:** typed argument for FormBuilder group ([#26985](https://github.com/angular/angular/issues/26985)) ([b0c7561](https://github.com/angular/angular/commit/b0c7561))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="7.1.3"></a>
|
<a name="7.1.3"></a>
|
||||||
## [7.1.3](https://github.com/angular/angular/compare/7.1.2...7.1.3) (2018-12-11)
|
## [7.1.3](https://github.com/angular/angular/compare/7.1.2...7.1.3) (2018-12-11)
|
||||||
|
|
||||||
@ -95,47 +210,6 @@
|
|||||||
* **platform-server:** add [@angular](https://github.com/angular)/http to the list of peerDependencies ([#27307](https://github.com/angular/angular/issues/27307)) ([236ac06](https://github.com/angular/angular/commit/236ac06)), closes [#26154](https://github.com/angular/angular/issues/26154)
|
* **platform-server:** add [@angular](https://github.com/angular)/http to the list of peerDependencies ([#27307](https://github.com/angular/angular/issues/27307)) ([236ac06](https://github.com/angular/angular/commit/236ac06)), closes [#26154](https://github.com/angular/angular/issues/26154)
|
||||||
|
|
||||||
|
|
||||||
<a name="7.2.0-beta.1"></a>
|
|
||||||
# [7.2.0-beta.1](https://github.com/angular/angular/compare/7.1.0...7.2.0-beta.1) (2018-12-06)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **bazel:** do not throw error when writing tsickle externs ([#27200](https://github.com/angular/angular/issues/27200)) ([20a2bae](https://github.com/angular/angular/commit/20a2bae))
|
|
||||||
* **bazel:** do not throw if ts compile action does not create esm5 outputs ([#27401](https://github.com/angular/angular/issues/27401)) ([c61a8b7](https://github.com/angular/angular/commit/c61a8b7))
|
|
||||||
* **bazel:** ng_package cannot be run multiple times without clean ([#27200](https://github.com/angular/angular/issues/27200)) ([4f93749](https://github.com/angular/angular/commit/4f93749))
|
|
||||||
* **bazel:** ng_package not generating UMD bundles on windows ([#27200](https://github.com/angular/angular/issues/27200)) ([7d59880](https://github.com/angular/angular/commit/7d59880))
|
|
||||||
* **bazel:** ng_package should correctly map to source maps in secondary entry-points ([#27313](https://github.com/angular/angular/issues/27313)) ([eb17502](https://github.com/angular/angular/commit/eb17502)), closes [#25510](https://github.com/angular/angular/issues/25510)
|
|
||||||
* **bazel:** Respect existing angular installation ([#27495](https://github.com/angular/angular/issues/27495)) ([4da739a](https://github.com/angular/angular/commit/4da739a))
|
|
||||||
* **common:** expose request url in network error ([#27143](https://github.com/angular/angular/issues/27143)) ([1db53da](https://github.com/angular/angular/commit/1db53da)), closes [#27029](https://github.com/angular/angular/issues/27029)
|
|
||||||
* **compiler-cli:** flatModuleIndex files not generated on windows with multiple input files ([#27200](https://github.com/angular/angular/issues/27200)) ([d3c08e7](https://github.com/angular/angular/commit/d3c08e7))
|
|
||||||
* **core:** export a value for InjectFlags ([#27279](https://github.com/angular/angular/issues/27279)) ([23b06af](https://github.com/angular/angular/commit/23b06af)), closes [#27251](https://github.com/angular/angular/issues/27251)
|
|
||||||
* **core:** More precise return type for `InjectableDecorator` ([#27360](https://github.com/angular/angular/issues/27360)) ([4b9948c](https://github.com/angular/angular/commit/4b9948c)), closes [#26942](https://github.com/angular/angular/issues/26942)
|
|
||||||
* **forms:** apply unicode flag to pattern attribute when supported ([#20819](https://github.com/angular/angular/issues/20819)) ([3c34b8b](https://github.com/angular/angular/commit/3c34b8b))
|
|
||||||
* **platform-server:** add [@angular](https://github.com/angular)/http to the list of peerDependencies ([#27307](https://github.com/angular/angular/issues/27307)) ([32c5be9](https://github.com/angular/angular/commit/32c5be9)), closes [#26154](https://github.com/angular/angular/issues/26154)
|
|
||||||
* **router:** update URL after redirects when urlHandlingStrategy='eager' ([#27356](https://github.com/angular/angular/issues/27356)) ([11a8bd8](https://github.com/angular/angular/commit/11a8bd8)), closes [#27076](https://github.com/angular/angular/issues/27076)
|
|
||||||
* **upgrade:** don't rely upon the runtime to resolve forward refs ([#27132](https://github.com/angular/angular/issues/27132)) ([a4462c2](https://github.com/angular/angular/commit/a4462c2))
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **bazel:** ng-new schematics with Bazel ([#27277](https://github.com/angular/angular/issues/27277)) ([06d4a0c](https://github.com/angular/angular/commit/06d4a0c))
|
|
||||||
* **router:** add a Navigation type available during navigation ([#27198](https://github.com/angular/angular/issues/27198)) ([d40af0c](https://github.com/angular/angular/commit/d40af0c))
|
|
||||||
* **router:** add pathParamsOrQueryParamsChange mode for runGuardsAndResolvers ([#27464](https://github.com/angular/angular/issues/27464)) ([d70a7f3](https://github.com/angular/angular/commit/d70a7f3)), closes [#26861](https://github.com/angular/angular/issues/26861) [#18253](https://github.com/angular/angular/issues/18253)
|
|
||||||
* **router:** allow passing `state` to routerLink directives ([#27198](https://github.com/angular/angular/issues/27198)) ([73f6ed9](https://github.com/angular/angular/commit/73f6ed9)), closes [#24617](https://github.com/angular/angular/issues/24617)
|
|
||||||
* **router:** allow passing state to `NavigationExtras` ([#27198](https://github.com/angular/angular/issues/27198)) ([67f4a5d](https://github.com/angular/angular/commit/67f4a5d))
|
|
||||||
* **router:** restore whole object when navigating back to a page managed by Angular router ([#27198](https://github.com/angular/angular/issues/27198)) ([2684249](https://github.com/angular/angular/commit/2684249))
|
|
||||||
|
|
||||||
<a name="7.2.0-beta.0"></a>
|
|
||||||
# [7.2.0-beta.0](https://github.com/angular/angular/compare/7.1.0...7.2.0-beta.0) (2018-11-28)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **common:** expose request url in network error ([#27143](https://github.com/angular/angular/issues/27143)) ([1db53da](https://github.com/angular/angular/commit/1db53da)), closes [#27029](https://github.com/angular/angular/issues/27029)
|
|
||||||
* **upgrade:** don't rely upon the runtime to resolve forward refs ([#27132](https://github.com/angular/angular/issues/27132)) ([a4462c2](https://github.com/angular/angular/commit/a4462c2))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="7.1.1"></a>
|
<a name="7.1.1"></a>
|
||||||
## [7.1.1](https://github.com/angular/angular/compare/7.1.0...7.1.1) (2018-11-28)
|
## [7.1.1](https://github.com/angular/angular/compare/7.1.0...7.1.1) (2018-11-28)
|
||||||
|
@ -191,7 +191,7 @@ If the commit reverts a previous commit, it should begin with `revert: `, follow
|
|||||||
Must be one of the following:
|
Must be one of the following:
|
||||||
|
|
||||||
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
|
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
|
||||||
* **ci**: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
|
* **ci**: Changes to our CI configuration files and scripts (example scopes: Circle, BrowserStack, SauceLabs)
|
||||||
* **docs**: Documentation only changes
|
* **docs**: Documentation only changes
|
||||||
* **feat**: A new feature
|
* **feat**: A new feature
|
||||||
* **fix**: A bug fix
|
* **fix**: A bug fix
|
||||||
|
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
|||||||
The MIT License
|
The MIT License
|
||||||
|
|
||||||
Copyright (c) 2014-2018 Google, Inc. http://angular.io
|
Copyright (c) 2010-2019 Google LLC. http://angular.io/license
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
[](https://travis-ci.org/angular/angular)
|
|
||||||
[](https://circleci.com/gh/angular/angular/tree/master)
|
[](https://circleci.com/gh/angular/angular/tree/master)
|
||||||
[](https://www.browserstack.com/automate/public-build/LzF3RzBVVGt6VWE2S0hHaC9uYllOZz09LS1BVjNTclBKV0x4eVRlcjA4QVY1M0N3PT0=--eb4ce8c8dc2c1c5b2b5352d473ee12a73ac20e06)
|
[](https://www.browserstack.com/automate/public-build/LzF3RzBVVGt6VWE2S0hHaC9uYllOZz09LS1BVjNTclBKV0x4eVRlcjA4QVY1M0N3PT0=--eb4ce8c8dc2c1c5b2b5352d473ee12a73ac20e06)
|
||||||
[](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
125
WORKSPACE
125
WORKSPACE
@ -1,17 +1,6 @@
|
|||||||
workspace(name = "angular")
|
workspace(name = "angular")
|
||||||
|
|
||||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||||
load(
|
|
||||||
"//packages/bazel:package.bzl",
|
|
||||||
"rules_angular_dependencies",
|
|
||||||
"rules_angular_dev_dependencies",
|
|
||||||
)
|
|
||||||
|
|
||||||
http_archive(
|
|
||||||
name = "io_bazel_rules_go",
|
|
||||||
sha256 = "b7a62250a3a73277ade0ce306d22f122365b513f5402222403e507f2f997d421",
|
|
||||||
url = "https://github.com/bazelbuild/rules_go/releases/download/0.16.3/rules_go-0.16.3.tar.gz",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Uncomment for local bazel rules development
|
# Uncomment for local bazel rules development
|
||||||
#local_repository(
|
#local_repository(
|
||||||
@ -19,51 +8,33 @@ http_archive(
|
|||||||
# path = "../rules_nodejs",
|
# path = "../rules_nodejs",
|
||||||
#)
|
#)
|
||||||
#local_repository(
|
#local_repository(
|
||||||
# name = "build_bazel_rules_typescript",
|
# name = "npm_bazel_typescript",
|
||||||
# path = "../rules_typescript",
|
# path = "../rules_typescript",
|
||||||
#)
|
#)
|
||||||
|
|
||||||
# Angular Bazel users will call this function
|
# Fetch rules_nodejs so we can install our npm dependencies
|
||||||
rules_angular_dependencies()
|
|
||||||
|
|
||||||
# Install transitive deps of rules_nodejs
|
|
||||||
load("@build_bazel_rules_nodejs//:package.bzl", "rules_nodejs_dependencies")
|
|
||||||
|
|
||||||
rules_nodejs_dependencies()
|
|
||||||
|
|
||||||
# These are the dependencies only for us
|
|
||||||
rules_angular_dev_dependencies()
|
|
||||||
|
|
||||||
# Install transitive deps of rules_typescript
|
|
||||||
load("@build_bazel_rules_typescript//:package.bzl", "rules_typescript_dependencies")
|
|
||||||
|
|
||||||
rules_typescript_dependencies()
|
|
||||||
|
|
||||||
#
|
|
||||||
# Point Bazel to WORKSPACEs that live in subdirectories
|
|
||||||
#
|
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "rxjs",
|
name = "build_bazel_rules_nodejs",
|
||||||
sha256 = "72b0b4e517f43358f554c125e40e39f67688cd2738a8998b4a266981ed32f403",
|
sha256 = "1416d03823fed624b49a0abbd9979f7c63bbedfd37890ddecedd2fe25cccebc6",
|
||||||
strip_prefix = "package/src",
|
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.18.6/rules_nodejs-0.18.6.tar.gz"],
|
||||||
url = "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Point to the integration test workspace just so that Bazel doesn't descend into it
|
# Use a mock @npm repository while we are building angular from source
|
||||||
# when expanding the //... pattern
|
# downstream. Angular will get its npm dependencies with in @ngdeps which
|
||||||
|
# is setup in ng_setup_workspace().
|
||||||
|
# TODO(gregmagolan): remove @ngdeps once angular is no longer build from source
|
||||||
|
# downstream and have build use @npm for npm dependencies
|
||||||
local_repository(
|
local_repository(
|
||||||
name = "bazel_integration_test",
|
name = "npm",
|
||||||
path = "integration/bazel",
|
path = "tools/npm_workspace",
|
||||||
)
|
)
|
||||||
|
|
||||||
#
|
# Check the bazel version and download npm dependencies
|
||||||
# Load and install our dependencies downloaded above.
|
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories")
|
||||||
#
|
|
||||||
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories", "yarn_install")
|
|
||||||
|
|
||||||
# Bazel version must be at least v0.21.0 because:
|
# Bazel version must be at least v0.21.0 because:
|
||||||
# - 0.21.0 --experimental_strict_action_env flag turned on by default which fixes cache when
|
# - 0.21.0 Using --incompatible_strict_action_env flag fixes cache when running `yarn bazel`
|
||||||
# running `yarn bazel` (see https://github.com/angular/angular/issues/27514#issuecomment-451438271)
|
# (see https://github.com/angular/angular/issues/27514#issuecomment-451438271)
|
||||||
check_bazel_version("0.21.0", """
|
check_bazel_version("0.21.0", """
|
||||||
You no longer need to install Bazel on your machine.
|
You no longer need to install Bazel on your machine.
|
||||||
Angular has a dependency on the @bazel/bazel package which supplies it.
|
Angular has a dependency on the @bazel/bazel package which supplies it.
|
||||||
@ -72,48 +43,56 @@ Try running `yarn bazel` instead.
|
|||||||
|
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
# Setup the Node.js toolchain
|
||||||
node_repositories(
|
node_repositories(
|
||||||
node_version = "10.9.0",
|
node_version = "10.9.0",
|
||||||
package_json = ["//:package.json"],
|
package_json = ["//:package.json"],
|
||||||
preserve_symlinks = True,
|
preserve_symlinks = True,
|
||||||
yarn_version = "1.12.1",
|
vendored_yarn = "@angular//third_party/github.com/yarnpkg/yarn/releases/download:v1.13.0",
|
||||||
)
|
)
|
||||||
|
|
||||||
local_repository(
|
# Setup the angular toolchain which installs npm dependencies into @ngdeps
|
||||||
name = "npm",
|
load("//tools:ng_setup_workspace.bzl", "ng_setup_workspace")
|
||||||
path = "tools/npm_workspace",
|
|
||||||
)
|
|
||||||
|
|
||||||
load("@io_bazel_rules_go//go:def.bzl", "go_register_toolchains", "go_rules_dependencies")
|
|
||||||
|
|
||||||
go_rules_dependencies()
|
|
||||||
|
|
||||||
go_register_toolchains()
|
|
||||||
|
|
||||||
load("@io_bazel_rules_webtesting//web:repositories.bzl", "browser_repositories", "web_test_repositories")
|
|
||||||
|
|
||||||
web_test_repositories()
|
|
||||||
|
|
||||||
browser_repositories(
|
|
||||||
chromium = True,
|
|
||||||
firefox = True,
|
|
||||||
)
|
|
||||||
|
|
||||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")
|
|
||||||
|
|
||||||
ts_setup_workspace()
|
|
||||||
|
|
||||||
load("@angular//:index.bzl", "ng_setup_workspace")
|
|
||||||
|
|
||||||
ng_setup_workspace()
|
ng_setup_workspace()
|
||||||
|
|
||||||
##################################
|
# Install all bazel dependencies of the @ngdeps npm packages
|
||||||
# Skylark documentation generation
|
load("@ngdeps//:install_bazel_dependencies.bzl", "install_bazel_dependencies")
|
||||||
|
|
||||||
|
install_bazel_dependencies()
|
||||||
|
|
||||||
|
# Load angular dependencies
|
||||||
|
load("//packages/bazel:package.bzl", "rules_angular_dev_dependencies")
|
||||||
|
|
||||||
|
rules_angular_dev_dependencies()
|
||||||
|
|
||||||
|
# Load karma dependencies
|
||||||
|
load("@npm_bazel_karma//:package.bzl", "rules_karma_dependencies")
|
||||||
|
|
||||||
|
rules_karma_dependencies()
|
||||||
|
|
||||||
|
# Setup the rules_webtesting toolchain
|
||||||
|
load("@io_bazel_rules_webtesting//web:repositories.bzl", "web_test_repositories")
|
||||||
|
|
||||||
|
web_test_repositories()
|
||||||
|
|
||||||
|
# Temporary work-around for https://github.com/angular/angular/issues/28681
|
||||||
|
# TODO(gregmagolan): go back to @io_bazel_rules_webtesting browser_repositories
|
||||||
|
load("@npm_bazel_karma//:browser_repositories.bzl", "browser_repositories")
|
||||||
|
|
||||||
|
browser_repositories()
|
||||||
|
|
||||||
|
# Setup the rules_typescript tooolchain
|
||||||
|
load("@npm_bazel_typescript//:defs.bzl", "ts_setup_workspace")
|
||||||
|
|
||||||
|
ts_setup_workspace()
|
||||||
|
|
||||||
|
# Setup the rules_sass toolchain
|
||||||
load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories")
|
load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories")
|
||||||
|
|
||||||
sass_repositories()
|
sass_repositories()
|
||||||
|
|
||||||
|
# Setup the skydoc toolchain
|
||||||
load("@io_bazel_skydoc//skylark:skylark.bzl", "skydoc_repositories")
|
load("@io_bazel_skydoc//skylark:skylark.bzl", "skydoc_repositories")
|
||||||
|
|
||||||
skydoc_repositories()
|
skydoc_repositories()
|
||||||
|
2
aio/.gitignore
vendored
2
aio/.gitignore
vendored
@ -26,11 +26,13 @@
|
|||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
|
|
||||||
# misc
|
# misc
|
||||||
|
/.firebase/
|
||||||
/.sass-cache
|
/.sass-cache
|
||||||
/connect.lock
|
/connect.lock
|
||||||
/coverage
|
/coverage
|
||||||
/libpeerconnection.log
|
/libpeerconnection.log
|
||||||
debug.log
|
debug.log
|
||||||
|
firebase-debug.log
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
testem.log
|
testem.log
|
||||||
/typings
|
/typings
|
||||||
|
@ -26,8 +26,8 @@ ARG AIO_GITHUB_ORGANIZATION=angular
|
|||||||
ARG TEST_AIO_GITHUB_ORGANIZATION=test-org
|
ARG TEST_AIO_GITHUB_ORGANIZATION=test-org
|
||||||
ARG AIO_GITHUB_REPO=angular
|
ARG AIO_GITHUB_REPO=angular
|
||||||
ARG TEST_AIO_GITHUB_REPO=test-repo
|
ARG TEST_AIO_GITHUB_REPO=test-repo
|
||||||
ARG AIO_GITHUB_TEAM_SLUGS=team,aio-contributors
|
ARG AIO_GITHUB_TEAM_SLUGS=aio-contributors
|
||||||
ARG TEST_AIO_GITHUB_TEAM_SLUGS=team,aio-contributors
|
ARG TEST_AIO_GITHUB_TEAM_SLUGS=aio-contributors
|
||||||
ARG AIO_NGINX_HOSTNAME=$AIO_DOMAIN_NAME
|
ARG AIO_NGINX_HOSTNAME=$AIO_DOMAIN_NAME
|
||||||
ARG TEST_AIO_NGINX_HOSTNAME=$TEST_AIO_DOMAIN_NAME
|
ARG TEST_AIO_NGINX_HOSTNAME=$TEST_AIO_DOMAIN_NAME
|
||||||
ARG AIO_NGINX_PORT_HTTP=80
|
ARG AIO_NGINX_PORT_HTTP=80
|
||||||
|
@ -104,6 +104,9 @@
|
|||||||
},
|
},
|
||||||
"archive": {
|
"archive": {
|
||||||
"browserTarget": "site:build:archive"
|
"browserTarget": "site:build:archive"
|
||||||
|
},
|
||||||
|
"ci": {
|
||||||
|
"progress": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -166,6 +169,11 @@
|
|||||||
"options": {
|
"options": {
|
||||||
"protractorConfig": "tests/e2e/protractor.conf.js",
|
"protractorConfig": "tests/e2e/protractor.conf.js",
|
||||||
"devServerTarget": "site:serve"
|
"devServerTarget": "site:serve"
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"ci": {
|
||||||
|
"devServerTarget": "site:serve:ci"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lint": {
|
"lint": {
|
||||||
|
6
aio/content/examples/.gitignore
vendored
6
aio/content/examples/.gitignore
vendored
@ -57,7 +57,9 @@ dist/
|
|||||||
|
|
||||||
# aot
|
# aot
|
||||||
**/*.ngsummary.json
|
**/*.ngsummary.json
|
||||||
|
upgrade-module/tsconfig-aot.json
|
||||||
!rollup-config.js
|
!rollup-config.js
|
||||||
|
upgrade-module/rollup-config.js
|
||||||
aot-compiler/**/*.d.ts
|
aot-compiler/**/*.d.ts
|
||||||
aot-compiler/**/*.factory.d.ts
|
aot-compiler/**/*.factory.d.ts
|
||||||
upgrade-phonecat-2-hybrid/aot/**/*
|
upgrade-phonecat-2-hybrid/aot/**/*
|
||||||
@ -84,5 +86,9 @@ upgrade-phonecat-2-hybrid/aot/**/*
|
|||||||
*stackblitz.no-link.html
|
*stackblitz.no-link.html
|
||||||
|
|
||||||
# ngUpgrade testing
|
# ngUpgrade testing
|
||||||
|
upgrade-phonecat-1-typescript/tsconfig-aot.json
|
||||||
|
upgrade-phonecat-1-typescript/rollup-config.js
|
||||||
|
upgrade-phonecat-3-final/tsconfig-aot.json
|
||||||
|
upgrade-phonecat-3-final/rollup-config.js
|
||||||
!upgrade-phonecat-*/**/karma.conf.js
|
!upgrade-phonecat-*/**/karma.conf.js
|
||||||
!upgrade-phonecat-*/**/karma-test-shim.js
|
!upgrade-phonecat-*/**/karma-test-shim.js
|
||||||
|
@ -20,7 +20,7 @@ export class AppComponent {
|
|||||||
movies: IMovie[] = [];
|
movies: IMovie[] = [];
|
||||||
showImage = true;
|
showImage = true;
|
||||||
title = 'AngularJS to Angular Quick Ref Cookbook';
|
title = 'AngularJS to Angular Quick Ref Cookbook';
|
||||||
toggleImage(event: UIEvent) {
|
toggleImage(event?: UIEvent) {
|
||||||
this.showImage = !this.showImage;
|
this.showImage = !this.showImage;
|
||||||
this.eventType = (event && event.type) || 'not provided';
|
this.eventType = (event && event.type) || 'not provided';
|
||||||
}
|
}
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
import { Injectable, Pipe, PipeTransform } from '@angular/core';
|
|
||||||
import { DatePipe } from '@angular/common';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
// #docregion date-pipe
|
|
||||||
@Pipe({name: 'date', pure: true})
|
|
||||||
export class StringSafeDatePipe extends DatePipe implements PipeTransform {
|
|
||||||
transform(value: any, format: string): string {
|
|
||||||
value = typeof value === 'string' ?
|
|
||||||
Date.parse(value) : value;
|
|
||||||
return super.transform(value, format);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// #enddocregion date-pipe
|
|
@ -19,6 +19,7 @@ import { HeroListAutoCalcPageComponent } from './hero-list-auto-page.component';
|
|||||||
import { HeroListAutoComponent } from './hero-list-auto.component';
|
import { HeroListAutoComponent } from './hero-list-auto.component';
|
||||||
import { HomeComponent } from './home.component';
|
import { HomeComponent } from './home.component';
|
||||||
import { AboutComponent } from './about.component';
|
import { AboutComponent } from './about.component';
|
||||||
|
import { InsertRemoveComponent } from './insert-remove.component';
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
@ -56,6 +57,7 @@ import { AboutComponent } from './about.component';
|
|||||||
HeroListAutoCalcPageComponent,
|
HeroListAutoCalcPageComponent,
|
||||||
HeroListAutoComponent,
|
HeroListAutoComponent,
|
||||||
HomeComponent,
|
HomeComponent,
|
||||||
|
InsertRemoveComponent,
|
||||||
AboutComponent
|
AboutComponent
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<h1>My First Attribute Directive</h1>
|
<h1>My First Attribute Directive</h1>
|
||||||
<!-- #docregion applied -->
|
<!-- #docregion applied -->
|
||||||
<p appHighlight>Highlight me!</p>
|
<p appHighlight>Highlight me!</p>
|
||||||
<!-- #enddocregion applied, -->
|
<!-- #enddocregion applied -->
|
||||||
|
|
||||||
<!-- #docregion color-1 -->
|
<!-- #docregion color-1 -->
|
||||||
<p appHighlight highlightColor="yellow">Highlighted in yellow</p>
|
<p appHighlight highlightColor="yellow">Highlighted in yellow</p>
|
||||||
@ -11,4 +11,4 @@
|
|||||||
|
|
||||||
<!-- #docregion color-2 -->
|
<!-- #docregion color-2 -->
|
||||||
<p appHighlight [highlightColor]="color">Highlighted with parent component's color</p>
|
<p appHighlight [highlightColor]="color">Highlighted with parent component's color</p>
|
||||||
<!-- #enddocregion color-2 -->
|
<!-- #enddocregion color-2 -->
|
@ -0,0 +1,3 @@
|
|||||||
|
<!-- #docregion unsupported -->
|
||||||
|
<p app:Highlight>This is invalid</p>
|
||||||
|
<!-- #enddocregion unsupported -->
|
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"e2e": [
|
||||||
|
{
|
||||||
|
"cmd": "yarn",
|
||||||
|
"args": [
|
||||||
|
"e2e",
|
||||||
|
"--no-webdriver-update"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -19,20 +19,20 @@ const DifferentParent = Parent;
|
|||||||
// #enddocregion provide-the-parent
|
// #enddocregion provide-the-parent
|
||||||
// The `parentType` defaults to `Parent` when omitting the second parameter.
|
// The `parentType` defaults to `Parent` when omitting the second parameter.
|
||||||
// #docregion provide-the-parent
|
// #docregion provide-the-parent
|
||||||
const provideParent =
|
export function provideParent
|
||||||
// #enddocregion provide-parent, provide-the-parent
|
// #enddocregion provide-parent, provide-the-parent
|
||||||
// #docregion provide-parent
|
// #docregion provide-parent
|
||||||
(component: any, parentType?: any) => {
|
(component: any, parentType?: any) {
|
||||||
return { provide: parentType || Parent, useExisting: forwardRef(() => component) };
|
return { provide: parentType || Parent, useExisting: forwardRef(() => component) };
|
||||||
};
|
}
|
||||||
// #enddocregion provide-parent
|
// #enddocregion provide-parent
|
||||||
|
|
||||||
// Simpler syntax version that always provides the component in the name of `Parent`.
|
// Simpler syntax version that always provides the component in the name of `Parent`.
|
||||||
const provideTheParent =
|
export function provideTheParent
|
||||||
// #docregion provide-the-parent
|
// #docregion provide-the-parent
|
||||||
(component: any) => {
|
(component: any) {
|
||||||
return { provide: Parent, useExisting: forwardRef(() => component) };
|
return { provide: Parent, useExisting: forwardRef(() => component) };
|
||||||
};
|
}
|
||||||
// #enddocregion provide-the-parent
|
// #enddocregion provide-the-parent
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"e2e": [
|
||||||
|
{
|
||||||
|
"cmd": "yarn",
|
||||||
|
"args": [
|
||||||
|
"e2e",
|
||||||
|
"--no-webdriver-update"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -28,10 +28,7 @@ let checkLogForMessage = (message: string) => {
|
|||||||
expect(page.logList.getText()).toContain(message);
|
expect(page.logList.getText()).toContain(message);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO(i): temorarily disable these tests because angular-in-memory-web-api is not compatible with rxjs v6 yet
|
describe('Http Tests', function() {
|
||||||
// and we don't have the backwards compatibility package yet.
|
|
||||||
// Reenable after rxjs v6 compatibility package is out or angular-in-memory-web-api is compatible with rxjs v6
|
|
||||||
xdescribe('Http Tests', function() {
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
browser.get('');
|
browser.get('');
|
||||||
});
|
});
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
{
|
{
|
||||||
"projectType": "i18n"
|
"projectType": "i18n",
|
||||||
}
|
"e2e": [
|
||||||
|
{
|
||||||
|
"cmd": "yarn",
|
||||||
|
"args": [
|
||||||
|
"e2e",
|
||||||
|
"--no-webdriver-update"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
47
aio/content/examples/interpolation/e2e/src/app.e2e-spec.ts
Normal file
47
aio/content/examples/interpolation/e2e/src/app.e2e-spec.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
|
describe('Interpolation e2e tests', () => {
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display Interpolation and Template Expressions', function () {
|
||||||
|
expect(element(by.css('h1')).getText()).toEqual('Interpolation and Template Expressions');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display Current customer: Maria', function () {
|
||||||
|
expect(element.all(by.css('h3')).get(0).getText()).toBe(`Current customer: Maria`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display The sum of 1 + 1 is not 4.', function () {
|
||||||
|
expect(element.all(by.css('p:last-child')).get(0).getText()).toBe(`The sum of 1 + 1 is not 4.`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display Expression Context', function () {
|
||||||
|
expect(element.all(by.css('h2')).get(1).getText()).toBe(`Expression Context`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display a list of customers', function () {
|
||||||
|
expect(element.all(by.css('li')).get(0).getText()).toBe(`Maria`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display two pictures', function() {
|
||||||
|
let pottedPlant = element.all(by.css('img')).get(0);
|
||||||
|
let lamp = element.all(by.css('img')).get(1);
|
||||||
|
|
||||||
|
expect(pottedPlant.getAttribute('src')).toContain('pottedPlant');
|
||||||
|
expect(pottedPlant.isDisplayed()).toBe(true);
|
||||||
|
|
||||||
|
expect(lamp.getAttribute('src')).toContain('lamp');
|
||||||
|
expect(lamp.isDisplayed()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support user input', function () {
|
||||||
|
let input = element(by.css('input'));
|
||||||
|
let label = element(by.css('label'));
|
||||||
|
expect(label.getText()).toEqual('Type something:');
|
||||||
|
input.sendKeys('abc');
|
||||||
|
expect(label.getText()).toEqual('Type something: abc');
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,60 @@
|
|||||||
|
|
||||||
|
<div>
|
||||||
|
<h1>Interpolation and Template Expressions</h1>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h2>Interpolation</h2>
|
||||||
|
<!-- #docregion interpolation-example1 -->
|
||||||
|
<h3>Current customer: {{ currentCustomer }}</h3>
|
||||||
|
<!-- #enddocregion interpolation-example1 -->
|
||||||
|
|
||||||
|
<!-- #docregion component-property -->
|
||||||
|
<p>{{title}}</p>
|
||||||
|
<div><img src="{{itemImageUrl}}"></div>
|
||||||
|
<!-- #enddocregion component-property -->
|
||||||
|
|
||||||
|
<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 />
|
||||||
|
<h2>Expression Context</h2>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3>Component context, properties of app.component.ts:</h3>
|
||||||
|
<!-- #docregion component-context -->
|
||||||
|
<h4>{{recommended}}</h4>
|
||||||
|
<img [src]="itemImageUrl2">
|
||||||
|
<!-- #enddocregion component-context -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4>Template context, template input variables (let customer):</h4>
|
||||||
|
<!-- #docregion template-input-variable -->
|
||||||
|
<ul>
|
||||||
|
<li *ngFor="let customer of customers">{{customer.name}}</li>
|
||||||
|
</ul>
|
||||||
|
<!-- #enddocregion template-input-variable -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div (keyup)="0">
|
||||||
|
<h4>Template context: template reference variables (#customerInput):</h4>
|
||||||
|
<!-- #docregion template-reference-variable -->
|
||||||
|
<label>Type something:
|
||||||
|
<input #customerInput>{{customerInput.value}}
|
||||||
|
</label>
|
||||||
|
<!-- #enddocregion template-reference-variable -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
@ -0,0 +1,27 @@
|
|||||||
|
import { TestBed, async } from '@angular/core/testing';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
describe('AppComponent', () => {
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [
|
||||||
|
AppComponent
|
||||||
|
],
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
it('should create the app', async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.debugElement.componentInstance;
|
||||||
|
expect(app).toBeTruthy();
|
||||||
|
}));
|
||||||
|
it(`should have as title 'Featured product:'`, async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.debugElement.componentInstance;
|
||||||
|
expect(app.title).toEqual('Featured product:');
|
||||||
|
}));
|
||||||
|
it('should render title in a p tag', async(() => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
const compiled = fixture.debugElement.nativeElement;
|
||||||
|
expect(compiled.querySelector('p').textContent).toContain('Featured product:');
|
||||||
|
}));
|
||||||
|
});
|
25
aio/content/examples/interpolation/src/app/app.component.ts
Normal file
25
aio/content/examples/interpolation/src/app/app.component.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
import { CUSTOMERS } from './customers';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styleUrls: ['./app.component.css']
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
customers = CUSTOMERS;
|
||||||
|
|
||||||
|
currentCustomer = 'Maria';
|
||||||
|
title = 'Featured product:';
|
||||||
|
itemImageUrl = '../assets/pottedPlant.png';
|
||||||
|
|
||||||
|
recommended = 'You might also like:';
|
||||||
|
itemImageUrl2 = '../assets/lamp.png';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
getVal(): number { return 2; }
|
||||||
|
|
||||||
|
|
||||||
|
}
|
18
aio/content/examples/interpolation/src/app/app.module.ts
Normal file
18
aio/content/examples/interpolation/src/app/app.module.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
|
||||||
|
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
AppComponent
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
BrowserModule
|
||||||
|
],
|
||||||
|
providers: [],
|
||||||
|
bootstrap: [AppComponent]
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
3
aio/content/examples/interpolation/src/app/customer.ts
Normal file
3
aio/content/examples/interpolation/src/app/customer.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export class Customer {
|
||||||
|
name: string;
|
||||||
|
}
|
9
aio/content/examples/interpolation/src/app/customers.ts
Normal file
9
aio/content/examples/interpolation/src/app/customers.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { Customer } from './customer';
|
||||||
|
|
||||||
|
export const CUSTOMERS: Customer[] = [
|
||||||
|
{ name: 'Maria' },
|
||||||
|
{ name: 'Oliver' },
|
||||||
|
{ name: 'Walter' },
|
||||||
|
{ name: 'Lakshmi' },
|
||||||
|
{ name: 'Yasha' }
|
||||||
|
];
|
BIN
aio/content/examples/interpolation/src/assets/lamp.png
Normal file
BIN
aio/content/examples/interpolation/src/assets/lamp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
BIN
aio/content/examples/interpolation/src/assets/potted-plant.png
Normal file
BIN
aio/content/examples/interpolation/src/assets/potted-plant.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
@ -2,7 +2,7 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Demo</title>
|
<title>Interpolation</title>
|
||||||
<base href="/">
|
<base href="/">
|
||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
12
aio/content/examples/interpolation/src/main.ts
Normal file
12
aio/content/examples/interpolation/src/main.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
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)
|
||||||
|
.catch(err => console.log(err));
|
10
aio/content/examples/interpolation/stackblitz.json
Normal file
10
aio/content/examples/interpolation/stackblitz.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"description": "Interpolation",
|
||||||
|
"files": [
|
||||||
|
"!**/*.d.ts",
|
||||||
|
"!**/*.js",
|
||||||
|
"!**/*.[1,2].*"
|
||||||
|
],
|
||||||
|
"file": "src/app/app.component.ts",
|
||||||
|
"tags": ["interpolation"]
|
||||||
|
}
|
@ -13,8 +13,8 @@ import { AppComponent } from './app.component';
|
|||||||
// #enddocregion
|
// #enddocregion
|
||||||
*/
|
*/
|
||||||
// #docregion
|
// #docregion
|
||||||
import { HighlightDirective } from './highlight.directive';
|
import { HighlightDirective } from './highlight.directive.1';
|
||||||
import { TitleComponent } from './title.component';
|
import { TitleComponent } from './title.component.1';
|
||||||
import { UserService } from './user.service';
|
import { UserService } from './user.service';
|
||||||
|
|
||||||
/* Routing Module */
|
/* Routing Module */
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
// #docregion
|
|
||||||
import { Pipe, PipeTransform } from '@angular/core';
|
|
||||||
|
|
||||||
@Pipe({ name: 'awesome' })
|
|
||||||
/** Precede the input string with the word "Awesome " */
|
|
||||||
export class AwesomePipe implements PipeTransform {
|
|
||||||
transform(phrase: string) {
|
|
||||||
return phrase ? 'Awesome ' + phrase : '';
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
// #docplaster
|
|
||||||
// Same directive name and selector as
|
|
||||||
// HighlightDirective in parent AppModule
|
|
||||||
// It selects for both input boxes and 'highlight' attr
|
|
||||||
// and it highlights in blue instead of gold
|
|
||||||
|
|
||||||
// #docregion
|
|
||||||
import { Directive, ElementRef } from '@angular/core';
|
|
||||||
|
|
||||||
// Highlight the host element or any InputElement in blue
|
|
||||||
@Directive({ selector: '[highlight], input' })
|
|
||||||
export class ContactHighlightDirective {
|
|
||||||
constructor(el: ElementRef) {
|
|
||||||
el.nativeElement.style.backgroundColor = 'powderblue';
|
|
||||||
// #enddocregion
|
|
||||||
console.log(`* Contact highlight called for ${el.nativeElement.tagName}`);
|
|
||||||
// #docregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// #enddocregion
|
|
@ -1,14 +0,0 @@
|
|||||||
// #docregion
|
|
||||||
import { Directive, ElementRef } from '@angular/core';
|
|
||||||
|
|
||||||
// Same directive name and selector as
|
|
||||||
// HighlightDirective in parent AppRootModule
|
|
||||||
// It selects for both input boxes and 'highlight' attr
|
|
||||||
// and it highlights in beige instead of yellow
|
|
||||||
@Directive({ selector: '[highlight]' })
|
|
||||||
export class HighlightDirective {
|
|
||||||
constructor(el: ElementRef) {
|
|
||||||
el.nativeElement.style.backgroundColor = 'beige';
|
|
||||||
console.log(`* Hero highlight called for ${el.nativeElement.tagName}`);
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,7 +8,7 @@ import { UserService } from './user.service';
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-title',
|
selector: 'app-title',
|
||||||
templateUrl: './title.component.html'
|
templateUrl: './title.component.1.html'
|
||||||
})
|
})
|
||||||
export class TitleComponent {
|
export class TitleComponent {
|
||||||
title = 'Angular Modules';
|
title = 'Angular Modules';
|
@ -16,7 +16,7 @@ const ITEMS: Item[] = [
|
|||||||
|
|
||||||
const FETCH_LATENCY = 500;
|
const FETCH_LATENCY = 500;
|
||||||
|
|
||||||
/** Simulate a data service that retrieves crises from a server */
|
/** Simulate a data service that retrieves items from a server */
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ItemService implements OnDestroy {
|
export class ItemService implements OnDestroy {
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ export class Routable1Component implements OnInit {
|
|||||||
navStart: Observable<NavigationStart>;
|
navStart: Observable<NavigationStart>;
|
||||||
|
|
||||||
constructor(private router: Router) {
|
constructor(private router: Router) {
|
||||||
// Create a new Observable the publishes only the NavigationStart event
|
// Create a new Observable that publishes only the NavigationStart event
|
||||||
this.navStart = router.events.pipe(
|
this.navStart = router.events.pipe(
|
||||||
filter(evt => evt instanceof NavigationStart)
|
filter(evt => evt instanceof NavigationStart)
|
||||||
) as Observable<NavigationStart>;
|
) as Observable<NavigationStart>;
|
||||||
|
@ -5,10 +5,9 @@ import { retryWhen, map, mergeMap } from 'rxjs/operators';
|
|||||||
|
|
||||||
function backoff(maxTries, ms) {
|
function backoff(maxTries, ms) {
|
||||||
return pipe(
|
return pipe(
|
||||||
retryWhen(attempts => range(1, maxTries)
|
retryWhen(attempts => zip(range(1, maxTries), attempts)
|
||||||
.pipe(
|
.pipe(
|
||||||
zip(attempts, (i) => i),
|
map(([i]) => i * i),
|
||||||
map(i => i * i),
|
|
||||||
mergeMap(i => timer(i * ms))
|
mergeMap(i => timer(i * ms))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styleUrls: ['./app.component.css']
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
itemImageUrl = '../assets/lamp.png';
|
||||||
|
isUnchanged = true;
|
||||||
|
classes = 'special';
|
||||||
|
// #docregion parent-data-type
|
||||||
|
parentItem = 'bananas';
|
||||||
|
// #enddocregion parent-data-type
|
||||||
|
|
||||||
|
// #docregion pass-object
|
||||||
|
currentItem = [{
|
||||||
|
id: 21,
|
||||||
|
name: 'peaches'
|
||||||
|
}];
|
||||||
|
// #enddocregion pass-object
|
||||||
|
|
||||||
|
interpolationTitle = 'Interpolation';
|
||||||
|
propertyTitle = 'Property binding';
|
||||||
|
|
||||||
|
// #docregion malicious-content
|
||||||
|
evilTitle = 'Template <script>alert("evil never sleeps")</script>Syntax';
|
||||||
|
// #enddocregion malicious-content
|
||||||
|
}
|
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"server": {
|
|
||||||
"baseDir": "src",
|
|
||||||
"routes": {
|
|
||||||
"/node_modules": "node_modules"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
// #docregion
|
|
||||||
import { Component } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'my-app',
|
|
||||||
template: `<h1>Hello {{name}}</h1>`
|
|
||||||
})
|
|
||||||
export class AppComponent { name = 'Angular'; }
|
|
@ -1,11 +0,0 @@
|
|||||||
// #docregion
|
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
|
||||||
import { AppComponent } from './app.component';
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [ BrowserModule ],
|
|
||||||
declarations: [ AppComponent ],
|
|
||||||
bootstrap: [ AppComponent ]
|
|
||||||
})
|
|
||||||
export class AppModule { }
|
|
@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Angular Quickstart</title>
|
|
||||||
<base href="/">
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<style>
|
|
||||||
body {color:#369;font-family: Arial,Helvetica,sans-serif;}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<!-- Polyfills -->
|
|
||||||
<!-- #docregion polyfills -->
|
|
||||||
<script src="node_modules/core-js/client/shim.min.js"></script>
|
|
||||||
<!-- #enddocregion polyfills -->
|
|
||||||
|
|
||||||
<script src="node_modules/zone.js/dist/zone.js"></script>
|
|
||||||
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
|
||||||
<script src="systemjs.config.js"></script>
|
|
||||||
<script>
|
|
||||||
System.import('main.js').catch(function(err){ console.error(err); });
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<!-- #docregion my-app-->
|
|
||||||
<my-app>Loading AppComponent content here ...</my-app>
|
|
||||||
<!-- #enddocregion my-app-->
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,5 +0,0 @@
|
|||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
|
||||||
|
|
||||||
import { AppModule } from './app/app.module';
|
|
||||||
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
|
@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "es5",
|
|
||||||
"module": "commonjs",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"sourceMap": true,
|
|
||||||
"emitDecoratorMetadata": true,
|
|
||||||
"experimentalDecorators": true,
|
|
||||||
"lib": [ "es2015", "dom" ],
|
|
||||||
"noImplicitAny": true,
|
|
||||||
"suppressImplicitAnyIndexErrors": true
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"description": "QuickStart",
|
|
||||||
"files": [
|
|
||||||
"src/app/app.component.ts",
|
|
||||||
"src/app/app.module.ts",
|
|
||||||
"src/main.ts",
|
|
||||||
"src/index.html"
|
|
||||||
],
|
|
||||||
"file": "src/app/app.component.ts",
|
|
||||||
"tags": ["quickstart"]
|
|
||||||
}
|
|
@ -4,7 +4,7 @@ import { Component } from '@angular/core';
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-crisis-list',
|
selector: 'app-crisis-list',
|
||||||
templateUrl: './crisis-list.component.html',
|
templateUrl: './crisis-list.component.1.html',
|
||||||
styleUrls: ['./crisis-list.component.css']
|
styleUrls: ['./crisis-list.component.1.css']
|
||||||
})
|
})
|
||||||
export class CrisisListComponent { }
|
export class CrisisListComponent { }
|
@ -4,7 +4,7 @@ import { Component } from '@angular/core';
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-hero-list',
|
selector: 'app-hero-list',
|
||||||
templateUrl: './hero-list.component.html',
|
templateUrl: './hero-list.component.1.html',
|
||||||
styleUrls: ['./hero-list.component.css']
|
styleUrls: ['./hero-list.component.1.css']
|
||||||
})
|
})
|
||||||
export class HeroListComponent { }
|
export class HeroListComponent { }
|
@ -1,10 +1,10 @@
|
|||||||
|
|
||||||
// #docregion promise
|
// #docregion promise
|
||||||
|
|
||||||
import { fromPromise } from 'rxjs';
|
import { from } from 'rxjs';
|
||||||
|
|
||||||
// Create an Observable out of a promise
|
// Create an Observable out of a promise
|
||||||
const data = fromPromise(fetch('/api/endpoint'));
|
const data = from(fetch('/api/endpoint'));
|
||||||
// Subscribe to begin listening for async result
|
// Subscribe to begin listening for async result
|
||||||
data.subscribe({
|
data.subscribe({
|
||||||
next(response) { console.log(response); },
|
next(response) { console.log(response); },
|
||||||
|
@ -34,8 +34,9 @@ describe('sw-example App', () => {
|
|||||||
expect(items[3].getText()).toBe('Angular blog');
|
expect(items[3].getText()).toBe('Angular blog');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// Check for a rejected promise as the service worker is not enabled
|
|
||||||
it('SwUpdate.checkForUpdate() should return a rejected promise', () => {
|
// Check for a rejected promise as the service worker is not enabled
|
||||||
|
it('SwUpdate.checkForUpdate() should return a rejected promise', () => {
|
||||||
const button = element(by.css('button'));
|
const button = element(by.css('button'));
|
||||||
const rejectMessage = element(by.css('p'));
|
const rejectMessage = element(by.css('p'));
|
||||||
button.click();
|
button.click();
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"projectType": "service-worker",
|
||||||
|
"e2e": [
|
||||||
|
{"cmd": "yarn", "args": ["e2e", "--no-webdriver-update"]},
|
||||||
|
{"cmd": "yarn", "args": ["build", "--prod"]},
|
||||||
|
{"cmd": "node", "args": ["--eval", "assert(fs.existsSync('./dist/ngsw.json'), 'ngsw.json is missing')"]},
|
||||||
|
{"cmd": "node", "args": ["--eval", "assert(fs.existsSync('./dist/ngsw-worker.js'), 'ngsw-worker.js is missing')"]},
|
||||||
|
{"cmd": "node", "args": ["--eval", "assert(require('./package.json').dependencies['@angular/service-worker'], '@angular/service-worker is missing')"]}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
@ -12,9 +12,9 @@ export class AppComponent {
|
|||||||
constructor(private update: SwUpdate) {}
|
constructor(private update: SwUpdate) {}
|
||||||
|
|
||||||
updateCheck(): void {
|
updateCheck(): void {
|
||||||
this.update
|
this.update
|
||||||
.checkForUpdate()
|
.checkForUpdate()
|
||||||
.then(() => this.updateCheckText = 'resolved')
|
.then(() => this.updateCheckText = 'resolved')
|
||||||
.catch(err => this.updateCheckText = `rejected: ${err.message}`);
|
.catch(err => this.updateCheckText = `rejected: ${err.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { ApplicationRef, Injectable } from '@angular/core';
|
||||||
import { SwUpdate } from '@angular/service-worker';
|
import { SwUpdate } from '@angular/service-worker';
|
||||||
|
import { concat, interval } from 'rxjs';
|
||||||
|
import { first } from 'rxjs/operators';
|
||||||
// #docregion sw-check-update
|
|
||||||
import { interval } from 'rxjs';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CheckForUpdateService {
|
export class CheckForUpdateService {
|
||||||
|
|
||||||
constructor(updates: SwUpdate) {
|
constructor(appRef: ApplicationRef, updates: SwUpdate) {
|
||||||
interval(6 * 60 * 60).subscribe(() => updates.checkForUpdate());
|
// Allow the app to stabilize first, before starting polling for updates with `interval()`.
|
||||||
|
const appIsStable$ = appRef.isStable.pipe(first(isStable => isStable === true));
|
||||||
|
const everySixHours$ = interval(6 * 60 * 60 * 1000);
|
||||||
|
const everySixHoursOnceAppIsStable$ = concat(appIsStable$, everySixHours$);
|
||||||
|
|
||||||
|
everySixHoursOnceAppIsStable$.subscribe(() => updates.checkForUpdate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #enddocregion sw-check-update
|
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
'use strict'; // necessary for es6 output in node
|
|
||||||
|
|
||||||
import { browser, element, by } from 'protractor';
|
|
||||||
|
|
||||||
describe('QuickStart E2E Tests', function () {
|
|
||||||
|
|
||||||
let expectedMsg = 'Hello Angular';
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
browser.get('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should display: ${expectedMsg}`, function () {
|
|
||||||
expect(element(by.css('h1')).getText()).toEqual(expectedMsg);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
@ -152,7 +152,7 @@
|
|||||||
<div [ngSwitch]="hero?.emotion">
|
<div [ngSwitch]="hero?.emotion">
|
||||||
<app-happy-hero *ngSwitchCase="'happy'" [hero]="hero"></app-happy-hero>
|
<app-happy-hero *ngSwitchCase="'happy'" [hero]="hero"></app-happy-hero>
|
||||||
<app-sad-hero *ngSwitchCase="'sad'" [hero]="hero"></app-sad-hero>
|
<app-sad-hero *ngSwitchCase="'sad'" [hero]="hero"></app-sad-hero>
|
||||||
<app-confused-hero *ngSwitchCase="'app-confused'" [hero]="hero"></app-confused-hero>
|
<app-confused-hero *ngSwitchCase="'confused'" [hero]="hero"></app-confused-hero>
|
||||||
<app-unknown-hero *ngSwitchDefault [hero]="hero"></app-unknown-hero>
|
<app-unknown-hero *ngSwitchDefault [hero]="hero"></app-unknown-hero>
|
||||||
</div>
|
</div>
|
||||||
<!-- #enddocregion built-in, ngswitch -->
|
<!-- #enddocregion built-in, ngswitch -->
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
export * from './spinner.component';
|
|
||||||
export * from './spinner.service';
|
export * from './spinner.service';
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
|
||||||
|
|
||||||
import { SpinnerService } from './spinner.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'toh-spinner',
|
|
||||||
template: '<div>spinner</div>'
|
|
||||||
})
|
|
||||||
|
|
||||||
export class SpinnerComponent implements OnDestroy, OnInit {
|
|
||||||
constructor(private spinnerService: SpinnerService) { }
|
|
||||||
|
|
||||||
ngOnInit() { }
|
|
||||||
|
|
||||||
ngOnDestroy() { }
|
|
||||||
}
|
|
@ -1,3 +1,2 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
export * from './toast.component';
|
|
||||||
export * from './toast.service';
|
export * from './toast.service';
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
|
||||||
|
|
||||||
import { ToastService } from './toast.service';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'toh-toast',
|
|
||||||
template: '<div>toast</div>'
|
|
||||||
})
|
|
||||||
export class ToastComponent implements OnInit {
|
|
||||||
constructor(toastService: ToastService) { }
|
|
||||||
|
|
||||||
ngOnInit() { }
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
|
||||||
|
|
||||||
import { ToastService } from '../../core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'toh-toast',
|
|
||||||
template: '<div>toast</div>'
|
|
||||||
})
|
|
||||||
export class ToastComponent implements OnInit {
|
|
||||||
constructor(toastService: ToastService) { }
|
|
||||||
|
|
||||||
ngOnInit() { }
|
|
||||||
}
|
|
@ -32,8 +32,6 @@
|
|||||||
height: 56px;
|
height: 56px;
|
||||||
padding: 0 16px 0 72px;
|
padding: 0 16px 0 72px;
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
background-color: #673AB7;
|
|
||||||
background: #0033FF;
|
|
||||||
background-color: #222;
|
background-color: #222;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
/*#docregion*/
|
/*#docregion*/
|
||||||
.spinner {
|
.spinner {
|
||||||
position: absolute;
|
|
||||||
left: 7em;
|
left: 7em;
|
||||||
top: 20em;
|
top: 20em;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -32,8 +32,6 @@
|
|||||||
height: 56px;
|
height: 56px;
|
||||||
padding: 0 16px 0 72px;
|
padding: 0 16px 0 72px;
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
background-color: #673AB7;
|
|
||||||
background: #0033FF;
|
|
||||||
background-color: #222;
|
background-color: #222;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,4 +4,7 @@ import { Component } from '@angular/core';
|
|||||||
selector: 'sg-app',
|
selector: 'sg-app',
|
||||||
templateUrl: './app.component.html'
|
templateUrl: './app.component.html'
|
||||||
})
|
})
|
||||||
export class AppComponent { }
|
export class AppComponent {
|
||||||
|
|
||||||
|
doSomething() {}
|
||||||
|
}
|
||||||
|
@ -4,4 +4,7 @@ import { Component } from '@angular/core';
|
|||||||
selector: 'sg-app',
|
selector: 'sg-app',
|
||||||
templateUrl: './app.component.html'
|
templateUrl: './app.component.html'
|
||||||
})
|
})
|
||||||
export class AppComponent { }
|
export class AppComponent {
|
||||||
|
|
||||||
|
onSavedTheDay(event$: any) { }
|
||||||
|
}
|
||||||
|
@ -66,7 +66,7 @@ export class AppComponent implements AfterViewInit, OnInit {
|
|||||||
|
|
||||||
currentHero: Hero;
|
currentHero: Hero;
|
||||||
|
|
||||||
deleteHero(hero: Hero) {
|
deleteHero(hero?: Hero) {
|
||||||
this.alert(`Delete ${hero ? hero.name : 'the hero'}.`);
|
this.alert(`Delete ${hero ? hero.name : 'the hero'}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,18 +105,18 @@ export class AppComponent implements AfterViewInit, OnInit {
|
|||||||
|
|
||||||
get nullHero(): Hero { return null; }
|
get nullHero(): Hero { return null; }
|
||||||
|
|
||||||
onClickMe(event: KeyboardEvent) {
|
onClickMe(event?: KeyboardEvent) {
|
||||||
let evtMsg = event ? ' Event target class is ' + (<HTMLElement>event.target).className : '';
|
let evtMsg = event ? ' Event target class is ' + (<HTMLElement>event.target).className : '';
|
||||||
this.alert('Click me.' + evtMsg);
|
this.alert('Click me.' + evtMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
onSave(event: KeyboardEvent) {
|
onSave(event?: KeyboardEvent) {
|
||||||
let evtMsg = event ? ' Event target is ' + (<HTMLElement>event.target).textContent : '';
|
let evtMsg = event ? ' Event target is ' + (<HTMLElement>event.target).textContent : '';
|
||||||
this.alert('Saved.' + evtMsg);
|
this.alert('Saved.' + evtMsg);
|
||||||
if (event) { event.stopPropagation(); }
|
if (event) { event.stopPropagation(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit() {/* referenced but not used */}
|
onSubmit(data: any) {/* referenced but not used */}
|
||||||
|
|
||||||
product = {
|
product = {
|
||||||
name: 'frimfram',
|
name: 'frimfram',
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Directive, Input } from '@angular/core';
|
import { Directive, Input, HostListener } from '@angular/core';
|
||||||
|
|
||||||
// export for convenience.
|
// export for convenience.
|
||||||
export { RouterLink} from '@angular/router';
|
export { RouterLink} from '@angular/router';
|
||||||
@ -6,13 +6,13 @@ export { RouterLink} from '@angular/router';
|
|||||||
/* tslint:disable:directive-class-suffix */
|
/* tslint:disable:directive-class-suffix */
|
||||||
// #docregion router-link
|
// #docregion router-link
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: '[routerLink]',
|
selector: '[routerLink]'
|
||||||
host: { '(click)': 'onClick()' }
|
|
||||||
})
|
})
|
||||||
export class RouterLinkDirectiveStub {
|
export class RouterLinkDirectiveStub {
|
||||||
@Input('routerLink') linkParams: any;
|
@Input('routerLink') linkParams: any;
|
||||||
navigatedTo: any = null;
|
navigatedTo: any = null;
|
||||||
|
|
||||||
|
@HostListener('click')
|
||||||
onClick() {
|
onClick() {
|
||||||
this.navigatedTo = this.linkParams;
|
this.navigatedTo = this.linkParams;
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ export class HeroService {
|
|||||||
/** POST: add a new hero to the server */
|
/** POST: add a new hero to the server */
|
||||||
addHero (hero: Hero): Observable<Hero> {
|
addHero (hero: Hero): Observable<Hero> {
|
||||||
return this.http.post<Hero>(this.heroesUrl, hero, httpOptions).pipe(
|
return this.http.post<Hero>(this.heroesUrl, hero, httpOptions).pipe(
|
||||||
tap((hero: Hero) => this.log(`added hero w/ id=${hero.id}`)),
|
tap((newHero: Hero) => this.log(`added hero w/ id=${newHero.id}`)),
|
||||||
catchError(this.handleError<Hero>('addHero'))
|
catchError(this.handleError<Hero>('addHero'))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -23,15 +23,6 @@ module.exports = function(config) {
|
|||||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||||
},
|
},
|
||||||
|
|
||||||
customLaunchers: {
|
|
||||||
// From the CLI. Not used here but interesting
|
|
||||||
// chrome setup for travis CI using chromium
|
|
||||||
Chrome_travis_ci: {
|
|
||||||
base: 'Chrome',
|
|
||||||
flags: ['--no-sandbox']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
files: [
|
files: [
|
||||||
// System.js for module loading
|
// System.js for module loading
|
||||||
'node_modules/systemjs/dist/system.src.js',
|
'node_modules/systemjs/dist/system.src.js',
|
||||||
|
@ -23,15 +23,6 @@ module.exports = function(config) {
|
|||||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||||
},
|
},
|
||||||
|
|
||||||
customLaunchers: {
|
|
||||||
// From the CLI. Not used here but interesting
|
|
||||||
// chrome setup for travis CI using chromium
|
|
||||||
Chrome_travis_ci: {
|
|
||||||
base: 'Chrome',
|
|
||||||
flags: ['--no-sandbox']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
files: [
|
files: [
|
||||||
// System.js for module loading
|
// System.js for module loading
|
||||||
'node_modules/systemjs/dist/system.src.js',
|
'node_modules/systemjs/dist/system.src.js',
|
||||||
|
@ -1508,7 +1508,7 @@ done manually.
|
|||||||
|
|
||||||
When `true`, this option tells the compiler not to check the TypeScript version.
|
When `true`, this option tells the compiler not to check the TypeScript version.
|
||||||
The compiler will skip checking and will not error out when an unsupported version of TypeScript is used.
|
The compiler will skip checking and will not error out when an unsupported version of TypeScript is used.
|
||||||
Setting this option to `true` is not recommended because unsupported versions of TypeScript might have undefined behaviour.
|
Setting this option to `true` is not recommended because unsupported versions of TypeScript might have undefined behavior.
|
||||||
|
|
||||||
This option is `false` by default.
|
This option is `false` by default.
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Introduction to modules
|
# Introduction to modules
|
||||||
|
|
||||||
Angular apps are modular and Angular has its own modularity system called *NgModules*.
|
Angular apps are modular and Angular has its own modularity system called *NgModules*.
|
||||||
NgModules are containers for a cohesive block of code dedicated to an application domain, a workflow, or a closely related set of capabilities. They can contain components, service providers, and other code files whose scope is defined by the containing NgModule. They can import functionality that is exported from other NgModules, and export selected functionality for use by other NgModules.
|
NgModules are containers for a cohesive block of code dedicated to an application domain, a workflow, or a closely related set of capabilities. They can contain components, service providers, and other code files whose scope is defined by the containing NgModule. They can import functionality that is exported from other NgModules, and export selected functionality for use by other NgModules.
|
||||||
|
|
||||||
Every Angular app has at least one NgModule class, [the *root module*](guide/bootstrapping), which is conventionally named `AppModule` and resides in a file named `app.module.ts`. You launch your app by *bootstrapping* the root NgModule.
|
Every Angular app has at least one NgModule class, [the *root module*](guide/bootstrapping), which is conventionally named `AppModule` and resides in a file named `app.module.ts`. You launch your app by *bootstrapping* the root NgModule.
|
||||||
@ -27,7 +27,7 @@ Here's a simple root NgModule definition.
|
|||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
The `export` property of `AppComponent` is included here for illustration; it isn't actually necessary in this example. A root NgModule has no reason to *export* anything because other modules don't need to *import* the root NgModule.
|
`AppComponent` is included in the `exports` list here for illustration; it isn't actually necessary in this example. A root NgModule has no reason to *export* anything because other modules don't need to *import* the root NgModule.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ For example, import Angular's `Component` decorator from the `@angular/core` lib
|
|||||||
|
|
||||||
<code-example path="architecture/src/app/app.component.ts" region="import" linenums="false"></code-example>
|
<code-example path="architecture/src/app/app.component.ts" region="import" linenums="false"></code-example>
|
||||||
|
|
||||||
You also import NgModules from Angular *libraries* using JavaScript import statements.
|
You also import NgModules from Angular *libraries* using JavaScript import statements.
|
||||||
For example, the following code imports the `BrowserModule` NgModule from the `platform-browser` library.
|
For example, the following code imports the `BrowserModule` NgModule from the `platform-browser` library.
|
||||||
|
|
||||||
<code-example path="architecture/src/app/mini-app.ts" region="import-browser-module" linenums="false"></code-example>
|
<code-example path="architecture/src/app/mini-app.ts" region="import-browser-module" linenums="false"></code-example>
|
||||||
|
@ -41,6 +41,10 @@ when the user hovers over that element. You can apply it like this:
|
|||||||
|
|
||||||
{@a write-directive}
|
{@a write-directive}
|
||||||
|
|
||||||
|
Please note that directives _do not_ support namespaces.
|
||||||
|
|
||||||
|
<code-example path="attribute-directives/src/app/app.component.avoid.html" linenums="false" header="src/app/app.component.avoid.html (unsupported)" region="unsupported"></code-example>
|
||||||
|
|
||||||
### Write the directive code
|
### Write the directive code
|
||||||
|
|
||||||
Create the directive class file in a terminal window with the CLI command [`ng generate directive`](cli/generate).
|
Create the directive class file in a terminal window with the CLI command [`ng generate directive`](cli/generate).
|
||||||
|
@ -372,6 +372,27 @@ Here are the features which may require additional polyfills:
|
|||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr style="vertical-align: top">
|
||||||
|
|
||||||
|
<td>
|
||||||
|
|
||||||
|
[Router](guide/router)
|
||||||
|
|
||||||
|
when using [hash-based routing](guide/router#appendix-locationstrategy-and-browser-url-styles)
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
|
||||||
|
[ES7/array](guide/browser-support#core-es7-array)
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
IE 11
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
@ -402,7 +423,7 @@ Below are the polyfills which are used to test the framework itself. They are a
|
|||||||
|
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
<a id='core-es7-reflect' href="https://github.com/zloirock/core-js/blob/master/es7/reflect.js">ES7/reflect</a>
|
<a id='core-es7-reflect' href="https://github.com/zloirock/core-js/tree/v2/fn/reflect">ES7/reflect</a>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
@ -416,6 +437,24 @@ Below are the polyfills which are used to test the framework itself. They are a
|
|||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
|
||||||
|
<a id='core-es7-array' href="https://github.com/zloirock/core-js/tree/v2/fn/array">ES7/array</a>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
MIT
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
0.1KB
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
|
@ -273,8 +273,8 @@ The CLI uses [Autoprefixer](https://github.com/postcss/autoprefixer) to ensure c
|
|||||||
You may find it necessary to target specific browsers or exclude certain browser versions from your build.
|
You may find it necessary to target specific browsers or exclude certain browser versions from your build.
|
||||||
|
|
||||||
Internally, Autoprefixer relies on a library called [Browserslist](https://github.com/browserslist/browserslist) to figure out which browsers to support with prefixing.
|
Internally, Autoprefixer relies on a library called [Browserslist](https://github.com/browserslist/browserslist) to figure out which browsers to support with prefixing.
|
||||||
Browserlist looks for configuration options in a `browserlist` property of the package configuration file, or in a configuration file named `.browserslistrc`.
|
Browserlist looks for configuration options in a `browserslist` property of the package configuration file, or in a configuration file named `.browserslistrc`.
|
||||||
Autoprefixer looks for the Browserlist configuration when it prefixes your CSS.
|
Autoprefixer looks for the `browserslist` configuration when it prefixes your CSS.
|
||||||
|
|
||||||
* You can tell Autoprefixer what browsers to target by adding a browserslist property to the package configuration file, `package.json`:
|
* You can tell Autoprefixer what browsers to target by adding a browserslist property to the package configuration file, `package.json`:
|
||||||
```
|
```
|
||||||
|
189
aio/content/guide/creating-libraries.md
Normal file
189
aio/content/guide/creating-libraries.md
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
# Creating Libraries
|
||||||
|
|
||||||
|
You can create and publish new libraries to extend Angular functionality. If you find that you need to solve the same problem in more than one app (or want to share your solution with other developers), you have a candidate for a library.
|
||||||
|
|
||||||
|
An simple example might be a button that sends users to your company website, that would be included in all apps that your company builds.
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
|
Use the Angular CLI to generate a new library skeleton with the following command:
|
||||||
|
|
||||||
|
<code-example format="." language="bash">
|
||||||
|
ng generate library my-lib
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
This creates the `projects/my-lib` folder in your workspace, which contains a component and a service inside an NgModule.
|
||||||
|
The workspace configuration file, `angular.json`, is updated with a project of type 'library'.
|
||||||
|
|
||||||
|
<code-example format="json">
|
||||||
|
"projects": {
|
||||||
|
...
|
||||||
|
"my-lib": {
|
||||||
|
"root": "projects/my-lib",
|
||||||
|
"sourceRoot": "projects/my-lib/src",
|
||||||
|
"projectType": "library",
|
||||||
|
"prefix": "lib",
|
||||||
|
"architect": {
|
||||||
|
"build": {
|
||||||
|
"builder": "@angular-devkit/build-ng-packagr:build",
|
||||||
|
...
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
You can build, test, and lint the project with CLI commands:
|
||||||
|
|
||||||
|
<code-example format="." language="bash">
|
||||||
|
ng build my-lib
|
||||||
|
ng test my-lib
|
||||||
|
ng lint my-lib
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
Notice that the configured builder for the project is different from the default builder for app projects.
|
||||||
|
This builder, among other things, ensures that the library is always built with the [AoT compiler](guide/aot-compiler), without the need to specify the `--prod` flag.
|
||||||
|
|
||||||
|
To make library code reusable you must define a public API for it. This "user layer" defines what is available to consumers of your library. A user of your library should be able to access public functionality (such as NgModules, service providers and general utility functions) through a single import path.
|
||||||
|
|
||||||
|
The public API for your library is maintained in the `index.ts` file of your library folder.
|
||||||
|
Anything exported from this file is made public when your library is imported into an application.
|
||||||
|
Use an NgModule to expose services and components.
|
||||||
|
|
||||||
|
Your library should supply documentation (typically a README file) for installation and maintenance.
|
||||||
|
|
||||||
|
## Refactoring parts of an app into a library
|
||||||
|
|
||||||
|
To make your solution reusable, you need to adjust it so that it does not depend on app-specific code.
|
||||||
|
Here are some things to consider in migrating application functionality to a library.
|
||||||
|
|
||||||
|
* Declarations such as components and pipes should be designed as stateless, meaning they don’t rely on or alter external variables. If you do rely on state, you need to evaluate every case and decide whether it is application state or state that the library would manage.
|
||||||
|
|
||||||
|
* Any observables that the components subscribe to internally should be cleaned up and disposed of during the lifecycle of those components.
|
||||||
|
|
||||||
|
* Components should expose their interactions through inputs for providing context, and outputs for communicating events to other components.
|
||||||
|
|
||||||
|
* Services should declare their own providers (rather than declaring providers in the NgModule or a component), so that they are *tree-shakable*. This allows the compiler to leave the service out of the bundle if it never gets injected into the application that imports the library. For more about this, see [Tree-shakable providers](guide/dependency-injection-providers#tree-shakable-providers).
|
||||||
|
|
||||||
|
* If you register global service providers or share providers across multiple NgModules, use the [`forRoot()` and `forChild()` patterns](guide/singleton-services) provided by the [RouterModule](api/router/RouterModule).
|
||||||
|
|
||||||
|
* Check all internal dependencies.
|
||||||
|
* For custom classes or interfaces used in components or service, check whether they depend on additional classes or interfaces that also need to be migrated.
|
||||||
|
* Similarly, if your library code depends on a service, that service needs to be migrated.
|
||||||
|
* If your library code or its templates depend on other libraries (such a Angular Material, for instance), you must configure your library with those dependencies.
|
||||||
|
|
||||||
|
## Reusable code and schematics
|
||||||
|
|
||||||
|
A library typically includes *reusable code* that defines components, services, and other Angular artifacts (pipes, directives, and so on) that you simply import into a project.
|
||||||
|
A library is packaged into an npm package for publishing and sharing, and this package can also include [schematics](guide/glossary#schematic) that provide instructions for generating or transforming code directly in your project, in the same way that the CLI creates a generic skeleton app with `ng generate component`.
|
||||||
|
A schematic that is combined with a library can, for example, provide the Angular CLI with the information it needs to generate a particular component defined in that library.
|
||||||
|
|
||||||
|
What you include in your library is determined by the kind of task you are trying to accomplish.
|
||||||
|
For example, if you want a dropdown with some canned data to show how to add it to your app, your library could define a schematic to create it.
|
||||||
|
For a component like a dropdown that would contain different passed-in values each time, you could provide it as a component in a shared library.
|
||||||
|
|
||||||
|
Suppose you want to read a configuration file and then generate a form based on that configuration.
|
||||||
|
If that form will need additional customization by the user, it might work best as a schematic.
|
||||||
|
However, if the forms will always be the same and not need much customization by developers, then you could create a dynamic component that takes the configuration and generates the form.
|
||||||
|
In general, the more complex the customization, the more useful the schematic approach.
|
||||||
|
|
||||||
|
## Integrating with the CLI
|
||||||
|
|
||||||
|
A library can include [schematics](guide/glossary#schematic) that allow it to integrate with the Angular CLI.
|
||||||
|
|
||||||
|
* Include an installation schematic so that `ng add` can add your library to a project.
|
||||||
|
|
||||||
|
* Include generation schematics in your library so that `ng generate` can scaffold your defined artifacts (components, services, tests, and so on) in a project.
|
||||||
|
|
||||||
|
* Include an update schematic so that `ng update` can update your library’s dependencies and provide migrations for breaking changes in new releases.
|
||||||
|
|
||||||
|
To learn more, see [Schematics — An Introduction](https://blog.angular.io/schematics-an-introduction-dc1dfbc2a2b2).
|
||||||
|
|
||||||
|
## Publishing your library
|
||||||
|
|
||||||
|
Use the Angular CLI and the npm package manager to build and publish your library as an npm package.
|
||||||
|
Libraries are built in [AoT mode](guide/aot-compiler) by default, so you do not need to specify the `-prod` flag when building for publication.
|
||||||
|
|
||||||
|
<code-example format="." language="bash">
|
||||||
|
ng build my-lib
|
||||||
|
cd dist/my-lib
|
||||||
|
npm publish
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
If you've never published a package in npm before, you must create a user account. Read more in [Publishing npm Packages](https://docs.npmjs.com/getting-started/publishing-npm-packages).
|
||||||
|
|
||||||
|
## Linked libraries
|
||||||
|
|
||||||
|
While working on a published library, you can use [npm link](https://docs.npmjs.com/cli/link) to avoid reinstalling the library on every build.
|
||||||
|
|
||||||
|
The library must be rebuilt on every change.
|
||||||
|
When linking a library, make sure that the build step runs in watch mode, and that the library's `package.json` configuration points at the correct entry points.
|
||||||
|
For example, `main` should point at a JavaScript file, not a TypeScript file.
|
||||||
|
|
||||||
|
## Use TypeScript path mapping for peer dependencies
|
||||||
|
|
||||||
|
Angular libraries should list all `@angular/*` dependencies as peer dependencies.
|
||||||
|
This insures that when modules ask for Angular, they all get the exact same module.
|
||||||
|
If a library lists `@angular/core` in `dependencies` instead of `peerDependencies`, it might get a different Angular module instead, which would cause your application to break.
|
||||||
|
|
||||||
|
While developing a library, you must install all peer dependencies through `devDependencies` to ensure that the library compiles properly.
|
||||||
|
A linked library will then have its own set of Angular libraries that it uses for building, located in its `node_modules` folder.
|
||||||
|
However, this can cause problems while building or running your application.
|
||||||
|
|
||||||
|
To get around this problem you can use TypeScript path mapping to tell TypeScript that it should load some modules from a specific location.
|
||||||
|
List all the peer dependencies that your library uses in the TypeScript configuration file `./tsconfig.json`, and point them at the local copy in the app's `node_modules` folder.
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
// ...
|
||||||
|
// paths are relative to `baseUrl` path.
|
||||||
|
"paths": {
|
||||||
|
"@angular/*": [
|
||||||
|
"../node_modules/@angular/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This mapping ensures that your library always loads the local copies of the modules it needs.
|
||||||
|
|
||||||
|
## Using your own library in apps
|
||||||
|
|
||||||
|
You don't have to publish your library to the npm package manager in order to use it in your own apps, but you do have to build it first.
|
||||||
|
|
||||||
|
To use your own library in an app:
|
||||||
|
|
||||||
|
* Build the library. You cannot use a library before it is built.
|
||||||
|
<code-example format="." language="bash">
|
||||||
|
ng build my-lib
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
* In your apps, import from the library by name:
|
||||||
|
```
|
||||||
|
import { my-export } from 'my-lib';
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building and rebuilding your library
|
||||||
|
|
||||||
|
The build step is important if you haven't published your library as an npm package and then installed the package back into your app from npm.
|
||||||
|
For instance, if you clone your git repository and run `npm install`, your editor will show the `my-lib` imports as missing if you haven't yet built your library.
|
||||||
|
|
||||||
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
|
When you import something from a library in an Angular app, Angular looks for a mapping between the library name and a location on disk.
|
||||||
|
When you install a library package, the mapping is in the `node_modules` folder. When you build your own library, it has to find the mapping in your `tsconfig` paths.
|
||||||
|
|
||||||
|
Generating a library with the Angular CLI automatically adds its path to the `tsconfig` file.
|
||||||
|
The Angular CLI uses the `tsconfig` paths to tell the build system where to find the library.
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
If you find that changes to your library are not reflected in your app, your app is probably using an old build of the library.
|
||||||
|
|
||||||
|
You can rebuild your library whenever you make changes to it, but this extra step takes time.
|
||||||
|
*Incremental builds* functionality improves the library-development experience.
|
||||||
|
Every time a file is changed a partial build is performed that emits the amended files.
|
||||||
|
|
||||||
|
Incremental builds can be run as a backround process in your dev environment. To take advantage of this feature add the `--watch` flag to the build command:
|
||||||
|
|
||||||
|
<code-example format="." language="bash">
|
||||||
|
ng build my-lib --watch
|
||||||
|
</code-example>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user