Compare commits
449 Commits
8.0.0-beta
...
g3
Author | SHA1 | Date | |
---|---|---|---|
c34c223122 | |||
26a8c5961e | |||
41225289d7 | |||
3612ddb433 | |||
09fab58109 | |||
b3102b9de1 | |||
cfe6581fc8 | |||
bef5043a5a | |||
b5295ad277 | |||
769d960db1 | |||
21be0fb926 | |||
9bcc1e8dce | |||
a06f0340d2 | |||
66b72bfa58 | |||
00075647be | |||
ce789b75a4 | |||
7baf45fe88 | |||
f3e0cc89ed | |||
cfa6e8e008 | |||
02debebcff | |||
ed8d60d060 | |||
9ea0d64d8b | |||
dfcf759e33 | |||
21835af70c | |||
2790352d04 | |||
bb6a3632f6 | |||
2d859a8c3a | |||
70fffba054 | |||
e185d3a4ad | |||
6f3052b799 | |||
c18fa7b5bd | |||
693b350567 | |||
0b27c09b51 | |||
861d6f1523 | |||
dc10355d61 | |||
6cd3743b44 | |||
a24f4b51b3 | |||
84baa0bb08 | |||
e721c08c7f | |||
37a154e4e6 | |||
415de9a291 | |||
b3dda0ebc1 | |||
41737bb4d3 | |||
afe3e72601 | |||
5e3bbf79a6 | |||
d2b64cc008 | |||
9eb8274991 | |||
17b3f11e07 | |||
10734ac607 | |||
68a9fe817c | |||
64e5628897 | |||
849b327986 | |||
a827bc2e3a | |||
083fb99033 | |||
55ea8da6eb | |||
7ea0d1bd3a | |||
bdcbd9ed4b | |||
b48d6e1b13 | |||
68f9d705f8 | |||
229f035969 | |||
c9f7cdaafd | |||
7b55ba58b9 | |||
cd449021c1 | |||
4bb0259bc0 | |||
66239b9d09 | |||
a770aa231d | |||
cf4718c366 | |||
07aeafa75c | |||
7a67f8935d | |||
bc88816c10 | |||
0d0445063a | |||
ddfdf3cd26 | |||
d6d081e120 | |||
38c778e371 | |||
3249020466 | |||
d6e27a41ed | |||
1a4d4a0e13 | |||
3121409957 | |||
fd122b0739 | |||
9a364a82fb | |||
a530ed11e8 | |||
2d7435daae | |||
b460b26308 | |||
ea90435a6b | |||
ea0e832e5f | |||
7c4afb0da7 | |||
603df13b14 | |||
f9b7b6d2f1 | |||
dafbbf8b64 | |||
d59f02d902 | |||
20bf4ca382 | |||
aae6f7b40b | |||
5f50562be5 | |||
efcd6af17d | |||
56c345baec | |||
19ff32036e | |||
37cc514f0f | |||
067657c1e9 | |||
8714daf276 | |||
d5e3f2c64b | |||
bc99b774ba | |||
a3ec058f6b | |||
4605df83e1 | |||
c0ad9e104d | |||
a9020a028f | |||
e769f9cfe4 | |||
4a665ca50b | |||
e9fab63385 | |||
5454227057 | |||
0244a2433e | |||
86aba1e8f3 | |||
ae4a86e3b5 | |||
ce4da3f8e5 | |||
e79f57a6b8 | |||
c439e14d39 | |||
a8d84660e5 | |||
4525619a73 | |||
4742385e95 | |||
d87b035ebb | |||
b759d63389 | |||
fe759ee0cf | |||
105cfaf5e4 | |||
2ab194c999 | |||
7b5d326d77 | |||
8e70ca39cc | |||
9d090cb3db | |||
3d5b98631a | |||
e8df000e97 | |||
604f37b679 | |||
4d912b6b12 | |||
bf2db12fc9 | |||
dfb220ea6b | |||
04b5ea089c | |||
7561698675 | |||
8ef690c342 | |||
3facdebd07 | |||
1db8bf312e | |||
f7738ad8d6 | |||
fc8048ddaf | |||
b2aadffbbc | |||
8ed13a37f0 | |||
1877e6c3f8 | |||
1a9ab2727e | |||
bf0704d685 | |||
1fb670e06c | |||
f50928f5b7 | |||
fe448e8222 | |||
7c297e05f3 | |||
487d4157ac | |||
90df7de54d | |||
8ef46f38f4 | |||
7b70760c8d | |||
6ab8c0b371 | |||
80379697e2 | |||
a5c747f46d | |||
410ccacf38 | |||
e76cf8c775 | |||
9be4ab51ea | |||
4990b935b4 | |||
08231f0bfa | |||
a3e105487d | |||
2064508876 | |||
0c59342cd0 | |||
018477e2c4 | |||
1f0eadfab6 | |||
f2dc32e5c7 | |||
019e65abfb | |||
0ffa2f2e73 | |||
a5a35ff54a | |||
7b20cec986 | |||
eb00a37eb8 | |||
75748d6044 | |||
9a7f5601fa | |||
955e4e704e | |||
73da2792c9 | |||
1625d86178 | |||
c4c34fe60e | |||
29fae6de08 | |||
ccb70e1c64 | |||
940fbf796c | |||
ec01594e97 | |||
ac0553e802 | |||
fe76494759 | |||
9d4b7d7d41 | |||
fa8669ac00 | |||
3f32c0e674 | |||
b7c17ff207 | |||
c5daaa91cf | |||
360730ce59 | |||
fca1724ebf | |||
3c53713616 | |||
c09d0ed627 | |||
af52536419 | |||
1c251e59d7 | |||
ec8b74da56 | |||
6085f335e8 | |||
7315a68ac6 | |||
e6117a3a49 | |||
a8b432d55d | |||
37b9f06f1e | |||
9d1423df7e | |||
df354d1b34 | |||
4227126305 | |||
e20a29a153 | |||
76119b84dc | |||
defc30c7ab | |||
869e1cdcec | |||
ed4675e5a1 | |||
4b39bdf7e5 | |||
146256a4e0 | |||
1d88c2bb81 | |||
99aa9674b2 | |||
6b6fdffc12 | |||
a29ce57732 | |||
4b9eb6185f | |||
ca20f571b8 | |||
a5b8420234 | |||
49dccf4bfc | |||
3a6ba00286 | |||
c37ec8b255 | |||
fc305305e1 | |||
b012ab210b | |||
b3ffdf92c5 | |||
7b0e9eddd1 | |||
a746b5b1ea | |||
b6f6b1178f | |||
37c5a26421 | |||
142ac41cac | |||
d4728c40d9 | |||
a68b1a1894 | |||
014841dfef | |||
63d18064fe | |||
fd5cd100a3 | |||
aa6db0d191 | |||
b14df413eb | |||
22c71b69ce | |||
d95e059480 | |||
ad9415af1d | |||
4f2773eaef | |||
f4f20daee3 | |||
36a1550e00 | |||
5ad2097be8 | |||
809452b921 | |||
f535f31d78 | |||
e3a401d20c | |||
423ac01dcf | |||
c7e4931f32 | |||
b73e02005b | |||
9a1959269f | |||
f71dae8f63 | |||
941c99ad7f | |||
3ef2002bd8 | |||
479ae51d1f | |||
eccbc785b3 | |||
29f57e315e | |||
c866c11bf8 | |||
15e84950ec | |||
7060d9038b | |||
14ce8a9c31 | |||
f856a6597b | |||
887faffa25 | |||
0bd4261f23 | |||
f96efd1c98 | |||
22ddbf4b02 | |||
268c3fe816 | |||
dc6192c8e5 | |||
7102ea80a9 | |||
6b98b534c8 | |||
c5d9035bab | |||
d5a8be76f2 | |||
9c1ced102e | |||
54286b8c27 | |||
84406e4d6d | |||
c29d2a4f16 | |||
84f3dfbca4 | |||
3bee0f684d | |||
881807dc36 | |||
20a9dbef8e | |||
25166d4f41 | |||
6215799055 | |||
ff9550542c | |||
69265b7b5d | |||
b446095c4d | |||
1efad3772e | |||
e8bb8f4912 | |||
4486dabf01 | |||
01577b0bed | |||
7c57293bee | |||
3063547975 | |||
72ecc45363 | |||
7d174969c2 | |||
79e2ca0c0e | |||
586234bb01 | |||
5fded9fcc8 | |||
866d500324 | |||
04cf4ef0c7 | |||
aa57bdbf90 | |||
78adcfe0ee | |||
48214e2a05 | |||
95989a12dd | |||
c5f1d08a43 | |||
3403027698 | |||
c875851bb4 | |||
d2f015f57e | |||
05a9090ded | |||
bfc40da6aa | |||
43ce6ec84a | |||
842d615928 | |||
a352b73962 | |||
fa82d2d6f1 | |||
83ba587c18 | |||
dcafddefb8 | |||
c0757d1d44 | |||
a06824aef6 | |||
ba602dbaec | |||
b1df9a30f4 | |||
3e5c1bcb9f | |||
b50283ed67 | |||
a23a0bc3a4 | |||
7ac58bec8a | |||
ff8e4dddb2 | |||
f01d1c4c8d | |||
b5629d98d8 | |||
ac76e5d8dd | |||
0bc26fc4e8 | |||
c532646f5b | |||
9fe522f3e2 | |||
4a1640bdd5 | |||
8cd72441f1 | |||
ea09430039 | |||
cd83a43462 | |||
1d4dde2adc | |||
58198075f2 | |||
2e43e15e12 | |||
5874247494 | |||
d207c4894a | |||
5fdf24e843 | |||
03d2e5cb1d | |||
2b974d4012 | |||
3a6e443e19 | |||
cb20b3b40a | |||
f7c867ebc2 | |||
76979e12c9 | |||
772b24ccc3 | |||
91a161aa13 | |||
efa10e33a9 | |||
daf8251998 | |||
a6ae759b46 | |||
827e89cfc4 | |||
40833ba54b | |||
34bdebcdd2 | |||
034de06ab1 | |||
2dd44d712d | |||
f16fca41d6 | |||
b8d87490f5 | |||
d127d05dc3 | |||
7b944c46d3 | |||
c4c3c1231b | |||
41de05e1ae | |||
dad5a258b8 | |||
ce68b4d839 | |||
dc335194ab | |||
f380263393 | |||
5a4c402663 | |||
262ba67525 | |||
dc9f0af080 | |||
8f8f9a6e61 | |||
25a2fef303 | |||
dbd9ecfd4c | |||
f01247f0a4 | |||
846c431eb7 | |||
edb6c2d814 | |||
3cb497c6ac | |||
bd65f58784 | |||
1930e8a072 | |||
7a11242388 | |||
65de0d6d0e | |||
ef1b9e6d71 | |||
65d3ddabf3 | |||
0b8aad2ca0 | |||
0071048cf9 | |||
9f7a9c607e | |||
22880eae16 | |||
3d48cde3b1 | |||
61495a138d | |||
319ed5168a | |||
f79cd5963e | |||
350802b207 | |||
10ba91b1d3 | |||
f75acbd99b | |||
395fb186a4 | |||
f0989b786b | |||
c64b13e593 | |||
7bae49b419 | |||
929fe029c2 | |||
ba6aa93aa3 | |||
f0f81f482e | |||
3144bf4d73 | |||
bb050a8ae0 | |||
75357ecb32 | |||
c1392ce618 | |||
15c065f9a0 | |||
fafabc0b92 | |||
ad4a9bf03f | |||
43181ea568 | |||
9dac04ff50 | |||
7f3e3a8c45 | |||
6ccf743627 | |||
230a941c3f | |||
7c20bf8845 | |||
82820b0b2c | |||
1778bd3470 | |||
33f71e8ce3 | |||
cbfc1f238e | |||
c7fe3a92de | |||
9ca356559b | |||
7c1b9ff5ec | |||
599e2e22bc | |||
2df2168c0a | |||
8043db570f | |||
de036d29e3 | |||
94223a09e5 | |||
65d839da03 | |||
32ae84da28 | |||
93a7836f7a | |||
9defc00b14 | |||
1145bdb478 | |||
f4d652568d | |||
3cc9ba24c6 | |||
3f2b51b837 | |||
d8704a3069 | |||
64e6aaa4f1 | |||
e1aaa7ec48 | |||
0ea216b993 | |||
ebffde7143 | |||
9ae14db343 | |||
95d9aa22ef | |||
df627e65df | |||
72d043f669 | |||
be121bba85 | |||
58436fd81a | |||
3336de0970 | |||
d0b6622b9a | |||
13b96ac91d | |||
623fd3fb5e | |||
bcdd4b5729 | |||
05c25ccca7 | |||
cfb2d176f8 | |||
d0e81eb593 |
@ -1,5 +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
|
integration/bazel
|
||||||
|
26
.bazelrc
26
.bazelrc
@ -1,5 +1,3 @@
|
|||||||
# Load any settings specific to the current user
|
|
||||||
try-import .bazelrc.user
|
|
||||||
################################
|
################################
|
||||||
# Settings for Angular team members only
|
# Settings for Angular team members only
|
||||||
################################
|
################################
|
||||||
@ -12,8 +10,10 @@ build:angular-team --remote_http_cache=https://storage.googleapis.com/angular-te
|
|||||||
|
|
||||||
# Make compilation fast, by keeping a few copies of the compilers
|
# Make compilation fast, by keeping a few copies of the compilers
|
||||||
# running as daemons, and cache SourceFile AST's to reduce parse time.
|
# running as daemons, and cache SourceFile AST's to reduce parse time.
|
||||||
build --strategy=TypeScriptCompile=worker
|
|
||||||
build --strategy=AngularTemplateCompile=worker
|
build --strategy=AngularTemplateCompile=worker
|
||||||
|
# TODO(alexeagle): re-enable after fixing worker instability with rxjs typings
|
||||||
|
# build --strategy=TypeScriptCompile=worker
|
||||||
|
build --strategy=TypeScriptCompile=standalone
|
||||||
|
|
||||||
# Enable debugging tests with --config=debug
|
# Enable debugging tests with --config=debug
|
||||||
test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test_strategy=exclusive --test_timeout=9999 --nocache_test_results
|
test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test_strategy=exclusive --test_timeout=9999 --nocache_test_results
|
||||||
@ -52,6 +52,22 @@ build --incompatible_strict_action_env
|
|||||||
run --incompatible_strict_action_env
|
run --incompatible_strict_action_env
|
||||||
test --incompatible_strict_action_env
|
test --incompatible_strict_action_env
|
||||||
|
|
||||||
|
###############################
|
||||||
|
# Saucelabs support #
|
||||||
|
# Turn on these settings with #
|
||||||
|
# --config=saucelabs #
|
||||||
|
###############################
|
||||||
|
|
||||||
|
# Expose SauceLabs environment to actions
|
||||||
|
# These environment variables are needed by
|
||||||
|
# web_test_karma to run on Saucelabs
|
||||||
|
test:saucelabs --action_env=SAUCE_USERNAME
|
||||||
|
test:saucelabs --action_env=SAUCE_ACCESS_KEY
|
||||||
|
test:saucelabs --action_env=SAUCE_READY_FILE
|
||||||
|
test:saucelabs --action_env=SAUCE_PID_FILE
|
||||||
|
test:saucelabs --action_env=SAUCE_TUNNEL_IDENTIFIER
|
||||||
|
test:saucelabs --define=KARMA_WEB_TEST_MODE=SL_REQUIRED
|
||||||
|
|
||||||
###############################
|
###############################
|
||||||
# Release support #
|
# Release support #
|
||||||
# Turn on these settings with #
|
# Turn on these settings with #
|
||||||
@ -119,3 +135,7 @@ build:remote --remote_instance_name=projects/internal-200822/instances/default_i
|
|||||||
# Do not accept remote cache.
|
# Do not accept remote cache.
|
||||||
# We need to understand the security risks of using prior build artifacts.
|
# We need to understand the security risks of using prior build artifacts.
|
||||||
build:remote --remote_accept_cached=false
|
build:remote --remote_accept_cached=false
|
||||||
|
|
||||||
|
# Load any settings specific to the current user. Needs to be last statement in this
|
||||||
|
# config, as the user configuration should be able to overwrite flags from this file.
|
||||||
|
try-import .bazelrc.user
|
||||||
|
@ -26,18 +26,29 @@ var_2: &browsers_docker_image circleci/node:10.12-browsers
|
|||||||
# **NOTE 1 **: If you change the cache key prefix, also sync the restore_cache fallback to match.
|
# **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.
|
# **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.
|
# See https://circleci.com/docs/2.0/caching/#restoring-cache for how prefixes work in CircleCI.
|
||||||
var_3: &cache_key v2-angular-node-10.12-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}
|
var_3: &cache_key v3-angular-node-10.12-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }}
|
||||||
|
|
||||||
# Initializes the CI environment by setting up common environment variables.
|
# Initializes the CI environment by setting up common environment variables.
|
||||||
var_4: &init_environment
|
var_4: &init_environment
|
||||||
run:
|
run:
|
||||||
name: Initializing environment (setting up variables, removing Yarn)
|
name: Initializing environment (setting up variables, overwriting Yarn)
|
||||||
# Remove the yarn installed in the docker container; we want our own version
|
# Overwrite the yarn installed in the docker container with our own version.
|
||||||
command: |
|
command: |
|
||||||
sudo rm /usr/local/bin/yarn
|
./.circleci/env.sh
|
||||||
source ./.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)"
|
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:
|
||||||
name: "Setup bazel RBE remote execution"
|
name: "Setup bazel RBE remote execution"
|
||||||
@ -52,11 +63,20 @@ var_6: &job_defaults
|
|||||||
docker:
|
docker:
|
||||||
- image: *default_docker_image
|
- image: *default_docker_image
|
||||||
|
|
||||||
# After checkout, rebase on top of master.
|
# After checkout, rebase on top of target branch.
|
||||||
# Similar to travis behavior, but not quite the same.
|
|
||||||
# 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: Rebase PR on target branch
|
||||||
|
command: >
|
||||||
|
if [[ -n "${CIRCLE_PR_NUMBER}" ]]; then
|
||||||
|
# User is required for rebase.
|
||||||
|
git config user.name "angular-ci"
|
||||||
|
git config user.email "angular-ci"
|
||||||
|
# Rebase PR on top of target branch.
|
||||||
|
node tools/rebase-pr.js angular/angular ${CIRCLE_PR_NUMBER}
|
||||||
|
else
|
||||||
|
echo "This build is not over a PR, nothing to do."
|
||||||
|
fi
|
||||||
|
|
||||||
var_8: &yarn_install
|
var_8: &yarn_install
|
||||||
run:
|
run:
|
||||||
@ -79,18 +99,58 @@ var_10: &restore_cache
|
|||||||
keys:
|
keys:
|
||||||
- *cache_key
|
- *cache_key
|
||||||
# This fallback should be the cache_key without variables.
|
# This fallback should be the cache_key without variables.
|
||||||
- v2-angular-node-10.12-
|
- 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:
|
||||||
lint:
|
setup:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- checkout
|
||||||
<<: *post_checkout
|
- *post_checkout
|
||||||
|
# This cache is saved in the build-npm-packages so that Bazel cache is also included.
|
||||||
- *restore_cache
|
- *restore_cache
|
||||||
- *init_environment
|
- *init_environment
|
||||||
- *yarn_install
|
- *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:
|
||||||
|
<<: *job_defaults
|
||||||
|
steps:
|
||||||
|
- *attach_workspace
|
||||||
|
- *init_environment
|
||||||
|
|
||||||
- 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)'
|
||||||
@ -98,19 +158,14 @@ 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)'
|
||||||
|
|
||||||
# Use `yarn gulp ...` (instead of `node_modules/.bin/gulp ...`) to ensure that yarn
|
|
||||||
# (which is an exported bash function) will be available to processes spawned by gulp.
|
|
||||||
- run: yarn 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
|
|
||||||
- *restore_cache
|
|
||||||
- *init_environment
|
- *init_environment
|
||||||
- *yarn_install
|
|
||||||
- *setup_circleci_bazel_config
|
- *setup_circleci_bazel_config
|
||||||
|
|
||||||
# Setup remote execution and run RBE-compatible tests.
|
# Setup remote execution and run RBE-compatible tests.
|
||||||
@ -125,11 +180,8 @@ jobs:
|
|||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
resource_class: xlarge
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
|
||||||
- *restore_cache
|
|
||||||
- *init_environment
|
- *init_environment
|
||||||
- *yarn_install
|
|
||||||
- *setup_circleci_bazel_config
|
- *setup_circleci_bazel_config
|
||||||
- *setup_bazel_remote_execution
|
- *setup_bazel_remote_execution
|
||||||
|
|
||||||
@ -157,15 +209,42 @@ jobs:
|
|||||||
path: dist/bin/packages/core/test/bundling/todo/bundle.min.js.br
|
path: dist/bin/packages/core/test/bundling/todo/bundle.min.js.br
|
||||||
destination: core/todo/bundle.br
|
destination: core/todo/bundle.br
|
||||||
|
|
||||||
|
test_saucelabs_bazel:
|
||||||
|
<<: *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
|
||||||
|
- *setup_circleci_bazel_config
|
||||||
|
- run:
|
||||||
|
name: Preparing environment for running tests on Saucelabs.
|
||||||
|
command: setSecretVar SAUCE_ACCESS_KEY $(echo $SAUCE_ACCESS_KEY | rev)
|
||||||
|
- run:
|
||||||
|
name: Starting Saucelabs tunnel
|
||||||
|
command: ./scripts/saucelabs/start-tunnel.sh
|
||||||
|
background: true
|
||||||
|
# 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
|
||||||
|
# All web tests are contained within a single //:test_web_all target for Saucelabs
|
||||||
|
# as running each set of tests as a separate target will attempt to acquire too
|
||||||
|
# many browsers on Saucelabs (7 per target currently) and some tests will always
|
||||||
|
# fail to acquire browsers. For example:
|
||||||
|
# 14 02 2019 19:52:33.170:WARN [launcher]: chrome beta on SauceLabs have not captured in 180000 ms, killing.
|
||||||
|
# //packages/forms/test:web_test_sauce TIMEOUT in 315.0s
|
||||||
|
- run: yarn bazel test --config=saucelabs //:test_web_all
|
||||||
|
- run: ./scripts/saucelabs/stop-tunnel.sh
|
||||||
|
|
||||||
test_aio:
|
test_aio:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
docker:
|
docker:
|
||||||
# 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
|
|
||||||
- *restore_cache
|
|
||||||
- *init_environment
|
- *init_environment
|
||||||
# Build aio
|
# Build aio
|
||||||
- run: yarn --cwd aio build --progress=false
|
- run: yarn --cwd aio build --progress=false
|
||||||
@ -190,9 +269,7 @@ 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
|
|
||||||
- *restore_cache
|
|
||||||
- *init_environment
|
- *init_environment
|
||||||
# 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/')"
|
||||||
@ -204,11 +281,7 @@ 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
|
|
||||||
- *restore_cache
|
|
||||||
- attach_workspace:
|
|
||||||
at: dist
|
|
||||||
- *init_environment
|
- *init_environment
|
||||||
# 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
|
||||||
@ -223,23 +296,21 @@ jobs:
|
|||||||
test_aio_local_ivy:
|
test_aio_local_ivy:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
|
||||||
- *restore_cache
|
|
||||||
- attach_workspace:
|
|
||||||
at: dist
|
|
||||||
- *init_environment
|
- *init_environment
|
||||||
|
# Rename the Ivy packages dist folder to "dist/packages-dist" as the AIO
|
||||||
|
# package installer picks up the locally built packages from that location.
|
||||||
|
# *Note*: We could also adjust the packages installer, but given we won't have
|
||||||
|
# two different folders of Angular distributions in the future, it's likely not
|
||||||
|
# worth the efforts to change the AIO packages installer.
|
||||||
|
- run: mv dist/packages-dist-ivy-aot dist/packages-dist
|
||||||
# Build aio with Ivy (using local Angular packages)
|
# Build aio with Ivy (using local Angular packages)
|
||||||
- run: yarn --cwd aio build-with-ivy --progress=false
|
- 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
|
|
||||||
- *restore_cache
|
|
||||||
- attach_workspace:
|
|
||||||
at: dist
|
|
||||||
- *init_environment
|
- *init_environment
|
||||||
# Install
|
# Install
|
||||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||||
@ -253,40 +324,43 @@ jobs:
|
|||||||
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
|
parallelism: 4
|
||||||
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
|
||||||
- *restore_cache
|
|
||||||
- attach_workspace:
|
|
||||||
at: dist
|
|
||||||
- *init_environment
|
- *init_environment
|
||||||
# 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. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
# Run examples tests. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
||||||
# Since the parallelism is set to "3", there will be three parallel CircleCI containers
|
# 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.
|
# 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}
|
- run: yarn --cwd aio example-e2e --setup --local --cliSpecsConcurrency=5 --shard=${CIRCLE_NODE_INDEX}/${CIRCLE_NODE_TOTAL}
|
||||||
|
|
||||||
test_docs_examples_ivy:
|
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
|
resource_class: xlarge
|
||||||
|
# We increase the parallelism here to five while the "test_docs_examples" job runs with
|
||||||
|
# a parallelism of four. This is necessary because this job also need to run NGCC which
|
||||||
|
# takes up more time and we don't want these jobs to impact the overall CI turnaround.
|
||||||
|
parallelism: 5
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
|
||||||
- *restore_cache
|
|
||||||
- attach_workspace:
|
|
||||||
at: dist
|
|
||||||
- *init_environment
|
- *init_environment
|
||||||
# Install aio
|
# Install aio
|
||||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||||
|
# Rename the Ivy packages dist folder to "dist/packages-dist" as the AIO
|
||||||
|
# package installer picks up the locally built packages from that location.
|
||||||
|
# *Note*: We could also adjust the packages installer, but given we won't have
|
||||||
|
# two different folders of Angular distributions in the future, we should keep
|
||||||
|
# the packages installer unchanged.
|
||||||
|
- run: mv dist/packages-dist-ivy-aot dist/packages-dist
|
||||||
# Run examples tests with ivy. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
# Run examples tests with ivy. The "CIRCLE_NODE_INDEX" will be set if "parallelism" is enabled.
|
||||||
# Since the parallelism is set to "3", there will be three parallel CircleCI containers
|
# 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.
|
# 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}
|
- run: yarn --cwd aio example-e2e --setup --local --ivy --cliSpecsConcurrency=5 --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:
|
||||||
@ -294,9 +368,7 @@ 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
|
|
||||||
- *restore_cache
|
|
||||||
- *init_environment
|
- *init_environment
|
||||||
- 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:
|
||||||
@ -313,9 +385,7 @@ 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
|
|
||||||
- *restore_cache
|
|
||||||
- *init_environment
|
- *init_environment
|
||||||
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
- run: yarn --cwd aio install --frozen-lockfile --non-interactive
|
||||||
- run:
|
- run:
|
||||||
@ -335,51 +405,44 @@ jobs:
|
|||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
resource_class: xlarge
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
|
||||||
- *restore_cache
|
|
||||||
- *init_environment
|
- *init_environment
|
||||||
- *yarn_install
|
|
||||||
- *setup_circleci_bazel_config
|
- *setup_circleci_bazel_config
|
||||||
- *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
|
||||||
|
|
||||||
|
# Save dependencies and bazel repository cache to use on subsequent runs.
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: *cache_key
|
key: *cache_key
|
||||||
paths:
|
paths:
|
||||||
- "node_modules"
|
- "node_modules"
|
||||||
|
- "aio/node_modules"
|
||||||
- "~/bazel_repository_cache"
|
- "~/bazel_repository_cache"
|
||||||
|
|
||||||
|
|
||||||
# Build the ivy npm packages.
|
# Build the ivy npm packages.
|
||||||
build-ivy-npm-packages:
|
build-ivy-npm-packages:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
resource_class: xlarge
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
|
||||||
- *restore_cache
|
|
||||||
- *init_environment
|
- *init_environment
|
||||||
- *yarn_install
|
|
||||||
- *setup_circleci_bazel_config
|
- *setup_circleci_bazel_config
|
||||||
- *setup_bazel_remote_execution
|
- *setup_bazel_remote_execution
|
||||||
|
|
||||||
- run: scripts/build-ivy-npm-packages.sh
|
- run: scripts/build-ivy-npm-packages.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-ivy-aot
|
- 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.
|
||||||
@ -398,14 +461,9 @@ 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
|
|
||||||
- *restore_cache
|
|
||||||
- attach_workspace:
|
|
||||||
at: dist
|
|
||||||
- *init_environment
|
- *init_environment
|
||||||
# Some integration tests get their dependencies from the root `node_modules/`.
|
- run: uname -r
|
||||||
- *yarn_install
|
|
||||||
# Runs the integration tests in parallel across multiple CircleCI container instances. The
|
# Runs the integration tests in parallel across multiple CircleCI container instances. The
|
||||||
# amount of container nodes for this job is controlled by the "parallelism" option.
|
# amount of container nodes for this job is controlled by the "parallelism" option.
|
||||||
- run: ./integration/run_tests.sh ${CIRCLE_NODE_INDEX} ${CIRCLE_NODE_TOTAL}
|
- run: ./integration/run_tests.sh ${CIRCLE_NODE_INDEX} ${CIRCLE_NODE_TOTAL}
|
||||||
@ -415,21 +473,20 @@ jobs:
|
|||||||
publish_snapshot:
|
publish_snapshot:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
|
||||||
<<: *post_checkout
|
|
||||||
- *init_environment
|
|
||||||
# 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:
|
||||||
name: Skip this job for Pull Requests and Fork builds
|
name: Skip this job for Pull Requests and Fork builds
|
||||||
# Note, `|| true` on the end makes this step always exit 0
|
# Note: Using `CIRCLE_*` env variables (instead of those defined in `env.sh` so that this
|
||||||
command: '[[
|
# step can be run before `init_environment`.
|
||||||
"$CI_PULL_REQUEST" != "false"
|
command: >
|
||||||
|| "$CI_REPO_OWNER" != "angular"
|
if [[ -n "${CIRCLE_PR_NUMBER}" ]] ||
|
||||||
|| "$CI_REPO_NAME" != "angular"
|
[[ "$CIRCLE_PROJECT_USERNAME" != "angular" ]] ||
|
||||||
]] && circleci step halt || true'
|
[[ "$CIRCLE_PROJECT_REPONAME" != "angular" ]]; then
|
||||||
- attach_workspace:
|
circleci step halt
|
||||||
at: dist
|
fi
|
||||||
|
- *attach_workspace
|
||||||
|
- *init_environment
|
||||||
# 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
|
||||||
@ -446,8 +503,8 @@ 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:
|
- checkout
|
||||||
<<: *post_checkout
|
- *post_checkout
|
||||||
- *restore_cache
|
- *restore_cache
|
||||||
- *init_environment
|
- *init_environment
|
||||||
- run:
|
- run:
|
||||||
@ -460,20 +517,6 @@ jobs:
|
|||||||
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'
|
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-local:
|
|
||||||
<<: *job_defaults
|
|
||||||
docker:
|
|
||||||
- image: *browsers_docker_image
|
|
||||||
steps:
|
|
||||||
- checkout:
|
|
||||||
<<: *post_checkout
|
|
||||||
- *restore_cache
|
|
||||||
- *init_environment
|
|
||||||
- *yarn_install
|
|
||||||
- run: yarn tsc -p packages
|
|
||||||
- run: yarn tsc -p modules
|
|
||||||
- run: yarn karma start ./karma-js.conf.js --single-run --browsers=ChromeNoSandbox
|
|
||||||
|
|
||||||
legacy-unit-tests-saucelabs:
|
legacy-unit-tests-saucelabs:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
# In order to avoid the bottleneck of having a slow host machine, we acquire a better
|
||||||
@ -481,11 +524,8 @@ jobs:
|
|||||||
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
# and therefore the tunnel and Karma need to process a lot of file requests and tests.
|
||||||
resource_class: xlarge
|
resource_class: xlarge
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
|
||||||
- *restore_cache
|
|
||||||
- *init_environment
|
- *init_environment
|
||||||
- *yarn_install
|
|
||||||
- run:
|
- run:
|
||||||
name: Preparing environment for running tests on Saucelabs.
|
name: Preparing environment for running tests on Saucelabs.
|
||||||
command: |
|
command: |
|
||||||
@ -506,13 +546,8 @@ jobs:
|
|||||||
legacy-misc-tests:
|
legacy-misc-tests:
|
||||||
<<: *job_defaults
|
<<: *job_defaults
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
|
||||||
- *restore_cache
|
|
||||||
- *init_environment
|
- *init_environment
|
||||||
- *yarn_install
|
|
||||||
- attach_workspace:
|
|
||||||
at: dist
|
|
||||||
- run: yarn gulp check-cycle
|
- run: yarn gulp check-cycle
|
||||||
# TODO: disabled because the Bazel packages-dist does not seem to have map files for
|
# 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
|
# the ESM5/ES2015 output. See: https://github.com/angular/angular/issues/27966
|
||||||
@ -525,26 +560,70 @@ jobs:
|
|||||||
resource_class: xlarge
|
resource_class: xlarge
|
||||||
docker:
|
docker:
|
||||||
- image: *browsers_docker_image
|
- image: *browsers_docker_image
|
||||||
|
# The Material unit tests support splitting the browsers across multiple CircleCI
|
||||||
|
# instances. Since by default this job launches two browsers, we run each browser
|
||||||
|
# in its own container instance.
|
||||||
|
# https://github.com/angular/material2/blob/7baeaa797b19da2d2998f0d26f6fede3c8a13714/test/karma.conf.js#L107-L110
|
||||||
|
parallelism: 2
|
||||||
|
environment:
|
||||||
|
# The Material unit tests also support launching the same browser multiple times by
|
||||||
|
# sharding individual specs across the defined multiple instances.
|
||||||
|
# See: https://github.com/angular/material2/blob/7baeaa797b19da2d2998f0d26f6fede3c8a13714/test/karma.conf.js#L113-L116
|
||||||
|
KARMA_PARALLEL_BROWSERS: 3
|
||||||
steps:
|
steps:
|
||||||
- checkout:
|
- *attach_workspace
|
||||||
<<: *post_checkout
|
|
||||||
- *init_environment
|
- *init_environment
|
||||||
- attach_workspace:
|
- run:
|
||||||
at: dist
|
name: "Cloning Material repository"
|
||||||
- run: ./scripts/ci/run_angular_material_unit_tests.sh
|
command: ./scripts/ci/clone_angular_material_repo.sh
|
||||||
|
- restore_cache:
|
||||||
|
# Material directory must be kept in sync with the `$MATERIAL_REPO_TMP_DIR` env variable.
|
||||||
|
# It needs to be hardcoded here, because env variables interpolation is not supported.
|
||||||
|
keys:
|
||||||
|
- v2-angular-material-{{ checksum "/tmp/material2/yarn.lock" }}
|
||||||
|
- v2-angular-material-
|
||||||
|
- run:
|
||||||
|
name: Installing Material dependencies.
|
||||||
|
command: yarn --cwd ${MATERIAL_REPO_TMP_DIR} install --frozen-lockfile --non-interactive
|
||||||
|
# Save the cache before we run the Material unit tests script. This is necessary
|
||||||
|
# because we don't want to cache the node modules which have been modified to contain
|
||||||
|
# the attached Ivy package output.
|
||||||
|
- save_cache:
|
||||||
|
# Material directory must be kept in sync with the `$MATERIAL_REPO_TMP_DIR` env variable.
|
||||||
|
# It needs to be hardcoded here, because env variables interpolation is not supported.
|
||||||
|
key: v2-angular-material-{{ checksum "/tmp/material2/yarn.lock" }}
|
||||||
|
paths:
|
||||||
|
- "/tmp/material2/node_modules"
|
||||||
|
- run:
|
||||||
|
name: "Running Material unit tests"
|
||||||
|
command: ./scripts/ci/run_angular_material_unit_tests.sh
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
version: 2
|
version: 2
|
||||||
default_workflow:
|
default_workflow:
|
||||||
jobs:
|
jobs:
|
||||||
- lint
|
- setup
|
||||||
- test
|
- lint:
|
||||||
- test_ivy_aot
|
requires:
|
||||||
- build-npm-packages
|
- setup
|
||||||
- build-ivy-npm-packages
|
- test:
|
||||||
- test_aio
|
requires:
|
||||||
- legacy-unit-tests-local
|
- setup
|
||||||
- legacy-unit-tests-saucelabs
|
- test_ivy_aot:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
|
- build-npm-packages:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
|
- build-ivy-npm-packages:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
|
- test_aio:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
|
- legacy-unit-tests-saucelabs:
|
||||||
|
requires:
|
||||||
|
- setup
|
||||||
- deploy_aio:
|
- deploy_aio:
|
||||||
requires:
|
requires:
|
||||||
- test_aio
|
- test_aio
|
||||||
@ -556,7 +635,7 @@ workflows:
|
|||||||
- build-npm-packages
|
- build-npm-packages
|
||||||
- test_aio_local_ivy:
|
- test_aio_local_ivy:
|
||||||
requires:
|
requires:
|
||||||
- build-npm-packages
|
- build-ivy-npm-packages
|
||||||
- test_aio_tools:
|
- test_aio_tools:
|
||||||
requires:
|
requires:
|
||||||
- build-npm-packages
|
- build-npm-packages
|
||||||
@ -565,8 +644,10 @@ workflows:
|
|||||||
- build-npm-packages
|
- build-npm-packages
|
||||||
- test_docs_examples_ivy:
|
- test_docs_examples_ivy:
|
||||||
requires:
|
requires:
|
||||||
- build-npm-packages
|
- build-ivy-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:
|
||||||
@ -596,19 +677,34 @@ workflows:
|
|||||||
# since the publishing script expects the legacy outputs layout.
|
# since the publishing script expects the legacy outputs layout.
|
||||||
- build-npm-packages
|
- build-npm-packages
|
||||||
- build-ivy-npm-packages
|
- build-ivy-npm-packages
|
||||||
- legacy-misc-tests
|
|
||||||
- legacy-unit-tests-local
|
|
||||||
- legacy-unit-tests-saucelabs
|
- legacy-unit-tests-saucelabs
|
||||||
|
- legacy-misc-tests
|
||||||
- material-unit-tests:
|
- material-unit-tests:
|
||||||
requires:
|
requires:
|
||||||
- build-ivy-npm-packages
|
- build-ivy-npm-packages
|
||||||
|
|
||||||
|
saucelabs_tests:
|
||||||
|
jobs:
|
||||||
|
- setup
|
||||||
|
- test_saucelabs_bazel:
|
||||||
|
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:
|
||||||
|
@ -54,6 +54,7 @@ else
|
|||||||
setPublicVar SAUCE_USERNAME "angular-ci";
|
setPublicVar SAUCE_USERNAME "angular-ci";
|
||||||
setSecretVar SAUCE_ACCESS_KEY "9b988f434ff8-fbca-8aa4-4ae3-35442987";
|
setSecretVar SAUCE_ACCESS_KEY "9b988f434ff8-fbca-8aa4-4ae3-35442987";
|
||||||
fi
|
fi
|
||||||
|
setPublicVar SAUCE_LOG_FILE /tmp/angular/sauce-connect.log
|
||||||
setPublicVar SAUCE_READY_FILE /tmp/angular/sauce-connect-ready-file.lock
|
setPublicVar SAUCE_READY_FILE /tmp/angular/sauce-connect-ready-file.lock
|
||||||
setPublicVar SAUCE_PID_FILE /tmp/angular/sauce-connect-pid-file.lock
|
setPublicVar SAUCE_PID_FILE /tmp/angular/sauce-connect-pid-file.lock
|
||||||
setPublicVar SAUCE_TUNNEL_IDENTIFIER "angular-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_INDEX}"
|
setPublicVar SAUCE_TUNNEL_IDENTIFIER "angular-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_INDEX}"
|
||||||
@ -61,13 +62,15 @@ setPublicVar SAUCE_TUNNEL_IDENTIFIER "angular-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_
|
|||||||
# acquire CircleCI instances for too long if sauceconnect failed, we need a connect timeout.
|
# acquire CircleCI instances for too long if sauceconnect failed, we need a connect timeout.
|
||||||
setPublicVar SAUCE_READY_FILE_TIMEOUT 120
|
setPublicVar SAUCE_READY_FILE_TIMEOUT 120
|
||||||
|
|
||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
# Define our own yarn command for CircleCI.
|
# Define environment variables for the Angular Material unit tests job.
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
echo "function yarn () { /usr/bin/env node $projectDir/third_party/github.com/yarnpkg/yarn/releases/download/v1.13.0/bin/yarn.js \"\$@\"; }" >> $BASH_ENV;
|
# We specifically use a directory within "/tmp" here because we want the cloned repo to be
|
||||||
echo "export -f yarn;" >> $BASH_ENV;
|
# completely isolated from angular/angular in order to avoid any bad interactions between
|
||||||
|
# their separate build setups.
|
||||||
|
setPublicVar MATERIAL_REPO_TMP_DIR "/tmp/material2"
|
||||||
|
setPublicVar MATERIAL_REPO_URL "https://github.com/angular/material2.git"
|
||||||
|
setPublicVar MATERIAL_REPO_BRANCH "ivy-2019"
|
||||||
|
|
||||||
# Source `$BASH_ENV` to make the variables available immediately.
|
# Source `$BASH_ENV` to make the variables available immediately.
|
||||||
source $BASH_ENV;
|
source $BASH_ENV;
|
||||||
|
103
.codefresh/Dockerfile.win-1809
Normal file
103
.codefresh/Dockerfile.win-1809
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
ARG core=mcr.microsoft.com/windows/servercore:1809
|
||||||
|
ARG target=mcr.microsoft.com/powershell:windowsservercore-1809
|
||||||
|
|
||||||
|
FROM $core as download
|
||||||
|
|
||||||
|
ARG node_version=10.13.0
|
||||||
|
ARG yarn_version=1.13.0
|
||||||
|
|
||||||
|
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
||||||
|
|
||||||
|
ENV GPG_VERSION 2.3.4
|
||||||
|
|
||||||
|
RUN Invoke-WebRequest $('https://files.gpg4win.org/gpg4win-vanilla-{0}.exe' -f $env:GPG_VERSION) -OutFile 'gpg4win.exe' -UseBasicParsing ; \
|
||||||
|
Start-Process .\gpg4win.exe -ArgumentList '/S' -NoNewWindow -Wait
|
||||||
|
|
||||||
|
RUN @( \
|
||||||
|
'94AE36675C464D64BAFA68DD7434390BDBE9B9C5', \
|
||||||
|
'FD3A5288F042B6850C66B31F09FE44734EB7990E', \
|
||||||
|
'71DCFD284A79C3B38668286BC97EC7A07EDE3FC1', \
|
||||||
|
'DD8F2338BAE7501E3DD5AC78C273792F7D83545D', \
|
||||||
|
'C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8', \
|
||||||
|
'B9AE9905FFD7803F25714661B63B535A4C206CA9', \
|
||||||
|
'77984A986EBC2AA786BC0F66B01FBB92821C587A', \
|
||||||
|
'8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600', \
|
||||||
|
'4ED778F539E3634C779C87C6D7062848A1AB005C', \
|
||||||
|
'A48C2BEE680E841632CD4E44F07496B3EB3C1762', \
|
||||||
|
'B9E2F5981AA6E0CD28160D9FF13993A75599653C' \
|
||||||
|
) | foreach { \
|
||||||
|
gpg --keyserver ha.pool.sks-keyservers.net --recv-keys $_ ; \
|
||||||
|
}
|
||||||
|
|
||||||
|
ENV NODE_VERSION=$node_version
|
||||||
|
|
||||||
|
RUN Invoke-WebRequest $('https://nodejs.org/dist/v{0}/SHASUMS256.txt.asc' -f $env:NODE_VERSION) -OutFile 'SHASUMS256.txt.asc' -UseBasicParsing ; \
|
||||||
|
gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc
|
||||||
|
|
||||||
|
RUN Invoke-WebRequest $('https://nodejs.org/dist/v{0}/node-v{0}-win-x64.zip' -f $env:NODE_VERSION) -OutFile 'node.zip' -UseBasicParsing ; \
|
||||||
|
$sum = $(cat SHASUMS256.txt.asc | sls $(' node-v{0}-win-x64.zip' -f $env:NODE_VERSION)) -Split ' ' ; \
|
||||||
|
if ((Get-FileHash node.zip -Algorithm sha256).Hash -ne $sum[0]) { Write-Error 'SHA256 mismatch' } ; \
|
||||||
|
Expand-Archive node.zip -DestinationPath C:\ ; \
|
||||||
|
Rename-Item -Path $('C:\node-v{0}-win-x64' -f $env:NODE_VERSION) -NewName 'C:\nodejs'
|
||||||
|
|
||||||
|
ENV YARN_VERSION=$yarn_version
|
||||||
|
|
||||||
|
RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ; \
|
||||||
|
Invoke-WebRequest $('https://yarnpkg.com/downloads/{0}/yarn-{0}.msi' -f $env:YARN_VERSION) -OutFile yarn.msi -UseBasicParsing ; \
|
||||||
|
$sig = Get-AuthenticodeSignature yarn.msi ; \
|
||||||
|
if ($sig.Status -ne 'Valid') { Write-Error 'Authenticode signature is not valid' } ; \
|
||||||
|
Write-Output $sig.SignerCertificate.Thumbprint ; \
|
||||||
|
if (@( \
|
||||||
|
'7E253367F8A102A91D04829E37F3410F14B68A5F', \
|
||||||
|
'AF764E1EA56C762617BDC757C8B0F3780A0CF5F9' \
|
||||||
|
) -notcontains $sig.SignerCertificate.Thumbprint) { Write-Error 'Unknown signer certificate' } ; \
|
||||||
|
Start-Process msiexec.exe -ArgumentList '/i', 'yarn.msi', '/quiet', '/norestart' -NoNewWindow -Wait
|
||||||
|
|
||||||
|
ENV GIT_VERSION 2.20.1
|
||||||
|
ENV GIT_DOWNLOAD_URL https://github.com/git-for-windows/git/releases/download/v${GIT_VERSION}.windows.1/MinGit-${GIT_VERSION}-busybox-64-bit.zip
|
||||||
|
ENV GIT_SHA256 9817ab455d9cbd0b09d8664b4afbe4bbf78d18b556b3541d09238501a749486c
|
||||||
|
|
||||||
|
RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ; \
|
||||||
|
Invoke-WebRequest -UseBasicParsing $env:GIT_DOWNLOAD_URL -OutFile git.zip; \
|
||||||
|
if ((Get-FileHash git.zip -Algorithm sha256).Hash -ne $env:GIT_SHA256) {exit 1} ; \
|
||||||
|
Expand-Archive git.zip -DestinationPath C:\git; \
|
||||||
|
Remove-Item git.zip
|
||||||
|
|
||||||
|
FROM $target as baseimage
|
||||||
|
|
||||||
|
ENV NPM_CONFIG_LOGLEVEL info
|
||||||
|
|
||||||
|
COPY --from=download /nodejs /nodejs
|
||||||
|
COPY --from=download [ "/Program Files (x86)/yarn", "/yarn" ]
|
||||||
|
COPY --from=download /git /git
|
||||||
|
|
||||||
|
ARG SETX=/M
|
||||||
|
RUN setx %SETX% PATH "%PATH%;C:\nodejs;C:\yarn\bin;C:\git\cmd;C:\git\mingw64\bin;C:\git\usr\bin"
|
||||||
|
|
||||||
|
CMD [ "node.exe" ]
|
||||||
|
|
||||||
|
FROM baseimage
|
||||||
|
|
||||||
|
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
||||||
|
|
||||||
|
RUN Invoke-WebRequest -UseBasicParsing 'https://www.7-zip.org/a/7z1805-x64.exe' -OutFile 7z.exe; \
|
||||||
|
Start-Process -FilePath 'C:\\7z.exe' -ArgumentList '/S', '/D=C:\\7zip0' -NoNewWindow -Wait; \
|
||||||
|
Invoke-WebRequest -UseBasicParsing 'http://repo.msys2.org/distrib/x86_64/msys2-base-x86_64-20180531.tar.xz' -OutFile msys2.tar.xz; \
|
||||||
|
Start-Process -FilePath 'C:\\7zip\\7z' -ArgumentList 'e', 'msys2.tar.xz' -Wait; \
|
||||||
|
Start-Process -FilePath 'C:\\7zip\\7z' -ArgumentList 'x', 'msys2.tar', '-oC:\\' -Wait; \
|
||||||
|
Remove-Item msys2.tar.xz; \
|
||||||
|
Remove-Item msys2.tar; \
|
||||||
|
Remove-Item 7z.exe; \
|
||||||
|
Remove-Item -Recurse 7zip; \
|
||||||
|
[Environment]::SetEnvironmentVariable('Path', $env:Path + ';C:\msys64\usr\bin', [System.EnvironmentVariableTarget]::Machine); \
|
||||||
|
[Environment]::SetEnvironmentVariable('BAZEL_SH', 'C:\msys64\usr\bin\bash.exe', [System.EnvironmentVariableTarget]::Machine); \
|
||||||
|
Invoke-WebRequest -UseBasicParsing 'https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe' -OutFile vc_redist.x64.exe; \
|
||||||
|
Start-Process 'c:\\vc_redist.x64.exe' -ArgumentList '/Install', '/Passive', '/NoRestart' -NoNewWindow -Wait; \
|
||||||
|
Remove-Item vc_redist.x64.exe
|
||||||
|
|
||||||
|
# Add a fix for https://github.com/docker/for-win/issues/2920 as entry point to the container.
|
||||||
|
SHELL ["cmd", "/c"]
|
||||||
|
COPY "fix-msys64.cmd" "C:\\fix-msys64.cmd"
|
||||||
|
ENTRYPOINT cmd /C C:\\fix-msys64.cmd && cmd /c
|
||||||
|
|
||||||
|
CMD ["cmd.exe"]
|
33
.codefresh/README.md
Normal file
33
.codefresh/README.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# CodeFresh configuration
|
||||||
|
|
||||||
|
[](https://g.codefresh.io/public/accounts/angular/pipelines/angular/angular/angular)
|
||||||
|
|
||||||
|
This folder contains configuration for the [CodeFresh](<https://codefresh.io/>) based CI checks for this repository.
|
||||||
|
|
||||||
|
## The build pipeline
|
||||||
|
|
||||||
|
CodeFresh uses a several pipeline for each repository. The `codefresh.yml` file defines pipeline [build steps](https://codefresh.io/docs/docs/configure-ci-cd-pipeline/introduction-to-codefresh-pipelines/) for this repository.
|
||||||
|
|
||||||
|
Run results can be seen in the GitHub checks interface and in the [public pipeline](https://g.codefresh.io/public/accounts/angular/pipelines/angular/angular/angular)
|
||||||
|
|
||||||
|
Although most configuration is done via `pipeline.yml`, some options are only available in the online [pipeline settings](https://g.codefresh.io/pipelines/angular/services?repoOwner=angular&repoName=angular&project=angular%2Fangular&context=github&serviceName=angular%2Fangular), which needs a login to access.
|
||||||
|
|
||||||
|
|
||||||
|
## Caretaker
|
||||||
|
|
||||||
|
CodeFresh status can be found at <http://status.codefresh.io/>.
|
||||||
|
|
||||||
|
Issues related to the CodeFresh setup should be escalated to the Tools Team via the current caretaker, followed by Alex Eagle and Filipe Silva.
|
||||||
|
|
||||||
|
## Rollout strategy
|
||||||
|
|
||||||
|
Currently it is only used for tests on Windows platforms, on the master branch, and without pushing user-facing reports. It's only possible to see current builds in the [public pipeline dashboard](https://g.codefresh.io/public/accounts/angular/pipelines/angular/angular/angular).
|
||||||
|
|
||||||
|
After a week or two of running like this, we should reassess how stable and reliable it is.
|
||||||
|
|
||||||
|
Next steps include:
|
||||||
|
- building PRs
|
||||||
|
- showing build status publicly
|
||||||
|
- blocking PRs that break the build
|
||||||
|
- expanding the test suite
|
||||||
|
|
40
.codefresh/bazel.rc
Normal file
40
.codefresh/bazel.rc
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# These options are enabled when running on CI
|
||||||
|
# We do this by copying this file to /etc/bazel.bazelrc at the start of the build.
|
||||||
|
# See documentation in /docs/BAZEL.md
|
||||||
|
|
||||||
|
# Save downloaded repositories in a location that can be cached by CodeFresh. This helps us
|
||||||
|
# speeding up the analysis time significantly with Bazel managed node dependencies on the CI.
|
||||||
|
# build --repository_cache=C:/codefresh/volume/bazel_repository_cache
|
||||||
|
|
||||||
|
# Don't be spammy in the logs
|
||||||
|
# TODO(gmagolan): Hide progress again once build performance improves
|
||||||
|
# Presently, CircleCI can timeout during bazel test ... with the following
|
||||||
|
# error: Too long with no output (exceeded 10m0s)
|
||||||
|
# build --noshow_progress
|
||||||
|
|
||||||
|
# Print all the options that apply to the build.
|
||||||
|
# This helps us diagnose which options override others
|
||||||
|
# (e.g. /etc/bazel.bazelrc vs. tools/bazel.rc)
|
||||||
|
build --announce_rc
|
||||||
|
|
||||||
|
# Workaround https://github.com/bazelbuild/bazel/issues/3645
|
||||||
|
# Bazel doesn't calculate the memory ceiling correctly when running under Docker.
|
||||||
|
# Limit Bazel to consuming resources that fit in CodeFresh VMs
|
||||||
|
# TODO(filipesilva): determine the correct memory limit
|
||||||
|
build --local_resources=8000,8.0,1.0
|
||||||
|
|
||||||
|
# Retry in the event of flakes, eg. https://circleci.com/gh/angular/angular/31309
|
||||||
|
test --flaky_test_attempts=2
|
||||||
|
|
||||||
|
# More details on failures
|
||||||
|
build --verbose_failures=true
|
||||||
|
|
||||||
|
# Include PATH in Windows build/tests
|
||||||
|
# https://github.com/bazelbuild/rules_typescript/pull/356
|
||||||
|
build --action_env=PATH
|
||||||
|
test --action_env=PATH --test_env=PATH
|
||||||
|
|
||||||
|
# Exclude tests known to not work on Windows.
|
||||||
|
|
||||||
|
# Chrome web tests are currently broken.
|
||||||
|
test --test_tag_filters=-browser:chromium-local
|
26
.codefresh/codefresh.yml
Normal file
26
.codefresh/codefresh.yml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
version: '1.0'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
BuildImage:
|
||||||
|
type: build
|
||||||
|
image_name: node-bazel-windows
|
||||||
|
working_directory: ./.codefresh
|
||||||
|
no_cf_cache: true
|
||||||
|
build_arguments:
|
||||||
|
- node_version=10.13.0
|
||||||
|
- yarn_version=1.13.0
|
||||||
|
dockerfile: ./Dockerfile.win-1809
|
||||||
|
|
||||||
|
RunTests:
|
||||||
|
title: Run Example
|
||||||
|
image: ${{BuildImage}}
|
||||||
|
commands:
|
||||||
|
# Install dependencies
|
||||||
|
- yarn install --frozen-lockfile --non-interactive --network-timeout 100000 --no-progress
|
||||||
|
# Create symlinks needed for Windows.
|
||||||
|
- scripts\windows\create-symlinks.cmd
|
||||||
|
# Add Bazel CI config
|
||||||
|
- copy .codefresh\bazel.rc %ProgramData%\bazel.bazelrc
|
||||||
|
# Run tests
|
||||||
|
- yarn bazel test //tools/ts-api-guardian:all
|
||||||
|
- yarn test-ivy-aot //packages/animations/test //packages/common/test //packages/forms/test //packages/http/test //packages/platform-browser/test //packages/platform-browser-dynamic/test //packages/router/test
|
6
.codefresh/fix-msys64.cmd
Normal file
6
.codefresh/fix-msys64.cmd
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
@echo off
|
||||||
|
REM Fix for https://github.com/docker/for-win/issues/2920
|
||||||
|
REM echo "Fixing msys64 folder..."
|
||||||
|
REM Touch all .dll files inside C:\msys64\
|
||||||
|
forfiles /p C:\msys64\ /s /m *.dll /c "cmd /c Copy /B @path+,, >NUL"
|
||||||
|
REM echo "Fixed msys64 folder."
|
128
.github/CODEOWNERS
vendored
128
.github/CODEOWNERS
vendored
@ -39,12 +39,14 @@
|
|||||||
# (just to make this file easier to understand)
|
# (just to make this file easier to understand)
|
||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
|
# alan-agius4 - Alan Agius
|
||||||
# alexeagle - Alex Eagle
|
# alexeagle - Alex Eagle
|
||||||
# alxhub - Alex Rickabaugh
|
# alxhub - Alex Rickabaugh
|
||||||
# AndrewKushnir - Andrew Kushnir
|
# AndrewKushnir - Andrew Kushnir
|
||||||
# andrewseguin - Andrew Seguin
|
# andrewseguin - Andrew Seguin
|
||||||
# benlesh - Ben Lesh
|
# benlesh - Ben Lesh
|
||||||
# brandonroberts - Brandon Roberts
|
# brandonroberts - Brandon Roberts
|
||||||
|
# devversion - Paul Gschwendtner
|
||||||
# filipesilva - Filipe Silva
|
# filipesilva - Filipe Silva
|
||||||
# gkalpak - George Kalpakas
|
# gkalpak - George Kalpakas
|
||||||
# hansl - Hans Larsen
|
# hansl - Hans Larsen
|
||||||
@ -86,6 +88,7 @@
|
|||||||
# - IgorMinar
|
# - IgorMinar
|
||||||
# - kara
|
# - kara
|
||||||
# - mhevery
|
# - mhevery
|
||||||
|
# - alexeagle
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -293,6 +296,17 @@
|
|||||||
# - IgorMinar
|
# - IgorMinar
|
||||||
|
|
||||||
|
|
||||||
|
# ===========================================================
|
||||||
|
# @angular/tools-docs-libraries
|
||||||
|
# ===========================================================
|
||||||
|
#
|
||||||
|
# - alan-agius4
|
||||||
|
# - alexeagle
|
||||||
|
# - hansl
|
||||||
|
# - IgorMinar
|
||||||
|
# - mgechev
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
# @angular/fw-docs-marketing
|
# @angular/fw-docs-marketing
|
||||||
# ===========================================================
|
# ===========================================================
|
||||||
@ -313,6 +327,7 @@
|
|||||||
# ===========================================================
|
# ===========================================================
|
||||||
#
|
#
|
||||||
# - alexeagle
|
# - alexeagle
|
||||||
|
# - devversion
|
||||||
# - filipesilva
|
# - filipesilva
|
||||||
# - gkalpak
|
# - gkalpak
|
||||||
# - IgorMinar
|
# - IgorMinar
|
||||||
@ -349,10 +364,19 @@
|
|||||||
|
|
||||||
/packages/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/packages/platform-browser/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/platform-browser/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
/aio/content/guide/animations.md @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/animations.md @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/animations/** @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
/aio/content/guide/complex-animation-sequences.md @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
/aio/content/guide/reusable-animations.md @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
/aio/content/guide/route-animations.md @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
/aio/content/guide/transition-and-triggers.md @angular/fw-animations @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
@ -383,12 +407,13 @@
|
|||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
# @angular/compiler-cli/ngtools
|
# Framework/cli integration
|
||||||
#
|
#
|
||||||
# a rule to control API changes between @angular/compiler-cli and @angular/cli
|
# a rule to control API changes between @angular/compiler-cli and @angular/cli
|
||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/packages/compiler-cli/src/ngtools/** @angular/tools-cli @angular/framework-global-approvers
|
/packages/compiler-cli/src/ngtools/** @angular/tools-cli @angular/framework-global-approvers
|
||||||
|
/aio/content/guide/ivy.md @angular/tools-cli @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -408,6 +433,14 @@
|
|||||||
/packages/platform-webworker/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/platform-webworker/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/packages/platform-webworker-dynamic/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/packages/platform-webworker-dynamic/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
/aio/content/guide/architecture-components.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/guide/architecture-modules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/guide/architecture-next-steps.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/guide/architecture-services.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/guide/architecture.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/architecture/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/images/guide/architecture/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
/aio/content/guide/attribute-directives.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/attribute-directives.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/attribute-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/attribute-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/attribute-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/attribute-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -415,6 +448,8 @@
|
|||||||
/aio/content/guide/bootstrapping.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/bootstrapping.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/bootstrapping/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/bootstrapping/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
/aio/content/guide/cheatsheet.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
/aio/content/guide/component-interaction.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/component-interaction.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/component-interaction/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/component-interaction/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/component-interaction/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/component-interaction/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -430,7 +465,13 @@
|
|||||||
/aio/content/examples/dependency-injection-in-action/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/dependency-injection-in-action/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/dependency-injection-in-action/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/dependency-injection-in-action/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
/aio/content/guide/dependency-injection-pattern.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/dependency-injection-navtree.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
/aio/content/guide/dependency-injection-providers.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
/aio/content/guide/displaying-data.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/displaying-data/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/images/guide/displaying-data/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
/aio/content/guide/dynamic-component-loader.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/dynamic-component-loader.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/dynamic-component-loader/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/dynamic-component-loader/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
@ -457,12 +498,9 @@
|
|||||||
/aio/content/images/guide/lifecycle-hooks/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/lifecycle-hooks/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
/aio/content/examples/ngcontainer/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/ngcontainer/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/ngcontainer/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
|
|
||||||
/aio/content/guide/ngmodules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/ngmodules.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/ngmodules/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/ngmodules/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/ngmodule/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/images/guide/ngmodule/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
|
|
||||||
/aio/content/guide/ngmodule-api.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/ngmodule-api.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
@ -474,6 +512,8 @@
|
|||||||
/aio/content/guide/module-types.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/module-types.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
/aio/content/guide/template-syntax.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/template-syntax.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/event-binding/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/interpolation/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/template-syntax/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/template-syntax/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/template-syntax/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/template-syntax/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
@ -496,6 +536,10 @@
|
|||||||
/aio/content/examples/structural-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/structural-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/images/guide/structural-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/images/guide/structural-directives/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
/aio/content/guide/user-input.md @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/user-input/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/images/guide/user-input/** @angular/fw-core @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
@ -521,6 +565,7 @@
|
|||||||
/aio/content/guide/elements.md @angular/fw-elements @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/elements.md @angular/fw-elements @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
# @angular/forms
|
# @angular/forms
|
||||||
# ================================================
|
# ================================================
|
||||||
@ -651,6 +696,7 @@ testing/** @angular/fw-test
|
|||||||
/packages/platform-browser/src/security/** @angular/fw-security
|
/packages/platform-browser/src/security/** @angular/fw-security
|
||||||
/aio/content/guide/security.md @angular/fw-security @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/security.md @angular/fw-security @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/security/** @angular/fw-security @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/security/** @angular/fw-security @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/images/guide/security/** @angular/fw-security @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -681,6 +727,14 @@ testing/** @angular/fw-test
|
|||||||
/aio/tests/** @angular/docs-infra @angular/framework-global-approvers
|
/aio/tests/** @angular/docs-infra @angular/framework-global-approvers
|
||||||
/aio/tools/** @angular/docs-infra @angular/framework-global-approvers
|
/aio/tools/** @angular/docs-infra @angular/framework-global-approvers
|
||||||
|
|
||||||
|
# Hidden docs
|
||||||
|
/aio/content/guide/change-log.md @angular/docs-infra @angular/framework-global-approvers
|
||||||
|
/aio/content/guide/docs-style-guide.md @angular/docs-infra @angular/framework-global-approvers
|
||||||
|
/aio/content/examples/docs-style-guide/** @angular/docs-infra @angular/framework-global-approvers
|
||||||
|
/aio/content/images/guide/docs-style-guide/** @angular/docs-infra @angular/framework-global-approvers
|
||||||
|
/aio/content/guide/visual-studio-2015.md @angular/docs-infra @angular/framework-global-approvers
|
||||||
|
/aio/content/examples/visual-studio-2015/** @angular/docs-infra @angular/framework-global-approvers
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
@ -688,7 +742,17 @@ testing/** @angular/fw-test
|
|||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/aio/content/guide/quickstart.md @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/quickstart.md @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/cli-quickstart/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/images/guide/cli-quickstart/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/tutorial/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/tutorial/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/images/guide/toh/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/toh-pt0/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/toh-pt1/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/toh-pt2/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/toh-pt3/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/toh-pt4/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/toh-pt5/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/toh-pt6/** @angular/fw-docs-intro @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -696,17 +760,15 @@ testing/** @angular/fw-test
|
|||||||
# Docs: observables
|
# Docs: observables
|
||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/aio/content/examples/observables/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/images/guide/observables/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/guide/observables.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/observables.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/observables/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/comparing-observables.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/comparing-observables.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/observables-in-angular/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/images/guide/observables-in-angular/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
|
||||||
/aio/content/guide/observables-in-angular.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/observables-in-angular.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/practical-observable-usage/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/observables-in-angular/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/practical-observable-usage.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/practical-observable-usage.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/rx-library/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/practical-observable-usage/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/rx-library.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/rx-library.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/examples/rx-library/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -717,12 +779,26 @@ testing/** @angular/fw-test
|
|||||||
/aio/content/guide/npm-packages.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/npm-packages.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/browser-support.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/browser-support.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/typescript-configuration.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/typescript-configuration.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/setup-systemjs-anatomy.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/quickstart/** @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/setup.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/setup.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/examples/setup/** @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/examples/setup/** @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/guide/build.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/images/guide/build/** @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/deployment.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/deployment.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/guide/file-structure.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/releases.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/releases.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
/aio/content/guide/updating.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
/aio/content/guide/updating.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/guide/workspace-config.md @angular/fw-docs-packaging @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ================================================
|
||||||
|
# Docs: libraries
|
||||||
|
# ================================================
|
||||||
|
|
||||||
|
/aio/content/guide/creating-libraries.md @angular/tools-docs-libraries @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/guide/libraries.md @angular/tools-docs-libraries @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
/aio/content/guide/using-libraries.md @angular/tools-docs-libraries @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -745,19 +821,39 @@ testing/** @angular/fw-test
|
|||||||
/* @angular/fw-dev-infra
|
/* @angular/fw-dev-infra
|
||||||
/.buildkite/** @angular/fw-dev-infra
|
/.buildkite/** @angular/fw-dev-infra
|
||||||
/.circleci/** @angular/fw-dev-infra
|
/.circleci/** @angular/fw-dev-infra
|
||||||
|
/.codefresh/** @angular/fw-dev-infra
|
||||||
/.github/** @angular/fw-dev-infra
|
/.github/** @angular/fw-dev-infra
|
||||||
|
/.vscode/** @angular/fw-dev-infra
|
||||||
/docs/BAZEL.md @angular/fw-dev-infra
|
/docs/BAZEL.md @angular/fw-dev-infra
|
||||||
/packages/* @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/build/** @angular/fw-dev-infra
|
||||||
|
/tools/cjs-jasmine/** @angular/fw-dev-infra
|
||||||
|
/tools/gulp-tasks/** @angular/fw-dev-infra
|
||||||
|
/tools/ngcontainer/** @angular/fw-dev-infra
|
||||||
|
/tools/npm/** @angular/fw-dev-infra
|
||||||
|
/tools/npm_workspace/** @angular/fw-dev-infra
|
||||||
|
/tools/public_api_guard/** @angular/fw-dev-infra
|
||||||
|
/tools/rxjs/** @angular/fw-dev-infra
|
||||||
|
/tools/source-map-test/** @angular/fw-dev-infra
|
||||||
|
/tools/symbol-extractor/** @angular/fw-dev-infra
|
||||||
|
/tools/testing/** @angular/fw-dev-infra
|
||||||
|
/tools/ts-api-guardian/** @angular/fw-dev-infra
|
||||||
|
/tools/tslint/** @angular/fw-dev-infra
|
||||||
|
/tools/validate-commit-message/** @angular/fw-dev-infra
|
||||||
|
/tools/yarn/** @angular/fw-dev-infra
|
||||||
|
/tools/*
|
||||||
*.bzl @angular/fw-dev-infra
|
*.bzl @angular/fw-dev-infra
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
# Material CI
|
# Material CI
|
||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/tools/material-ci/** @angular/fw-core @angular/fw-dev-infra
|
/tools/material-ci/** @angular/fw-core @angular/framework-global-approvers
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ================================================
|
# ================================================
|
||||||
@ -765,6 +861,10 @@ testing/** @angular/fw-test
|
|||||||
# ================================================
|
# ================================================
|
||||||
|
|
||||||
/tools/public_api_guard/** @angular/fw-public-api
|
/tools/public_api_guard/** @angular/fw-public-api
|
||||||
|
/aio/content/guide/glossary.md @angular/fw-public-api
|
||||||
|
/aio/content/guide/styleguide.md @angular/fw-public-api
|
||||||
|
/aio/content/examples/styleguide/** @angular/fw-public-api
|
||||||
|
/aio/content/images/guide/styleguide/** @angular/fw-public-api
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
4
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
4
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
@ -37,7 +37,9 @@ Please create and share minimal reproduction of the issue starting with this tem
|
|||||||
<!-- ✍️--> https://stackblitz.com/...
|
<!-- ✍️--> https://stackblitz.com/...
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
If StackBlitz is not suitable for reproduction of your issue, please create a minimal GitHub repository with the reproduction of the issue. Share the link to the repo below along with step-by-step instructions to reproduce the problem, as well as expected and actual behavior.
|
If StackBlitz is not suitable for reproduction of your issue, please create a minimal GitHub repository with the reproduction of the issue.
|
||||||
|
A good way to make a minimal reproduction is to create a new app via `ng new repro-app` and add the minimum possible code to show the problem.
|
||||||
|
Share the link to the repo below along with step-by-step instructions to reproduce the problem, as well as expected and actual behavior.
|
||||||
|
|
||||||
Issues that don't have enough info and can't be reproduced will be closed.
|
Issues that don't have enough info and can't be reproduced will be closed.
|
||||||
|
|
||||||
|
12
.vscode/extensions.json
vendored
Normal file
12
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
// See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||||
|
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||||
|
|
||||||
|
// List of extensions which should be recommended for users of this workspace.
|
||||||
|
"recommendations": [
|
||||||
|
"devondcarew.bazel-code",
|
||||||
|
"gkalpak.aio-docs-utils",
|
||||||
|
"ms-vscode.vscode-typescript-tslint-plugin",
|
||||||
|
"xaver.clang-format",
|
||||||
|
],
|
||||||
|
}
|
14
.vscode/settings.json
vendored
14
.vscode/settings.json
vendored
@ -1,6 +1,12 @@
|
|||||||
{
|
{
|
||||||
"editor.formatOnSave": true,
|
"[javascript]": {
|
||||||
// Please install http://clang.llvm.org/docs/ClangFormat.html in VSCode to take advantage of clang-format
|
"editor.formatOnSave": true,
|
||||||
|
},
|
||||||
|
"[typescript]": {
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
},
|
||||||
|
// Please install https://marketplace.visualstudio.com/items?itemName=xaver.clang-format to take advantage of `clang-format` in VSCode.
|
||||||
|
// (See https://clang.llvm.org/docs/ClangFormat.html for more info `clang-format`.)
|
||||||
"clang-format.executable": "${workspaceRoot}/node_modules/.bin/clang-format",
|
"clang-format.executable": "${workspaceRoot}/node_modules/.bin/clang-format",
|
||||||
"files.watcherExclude": {
|
"files.watcherExclude": {
|
||||||
"**/.git/objects/**": true,
|
"**/.git/objects/**": true,
|
||||||
@ -8,12 +14,14 @@
|
|||||||
"**/node_modules/**": true,
|
"**/node_modules/**": true,
|
||||||
"**/bazel-out/**": true,
|
"**/bazel-out/**": true,
|
||||||
"**/dist/**": true,
|
"**/dist/**": true,
|
||||||
|
"**/aio/src/generated/**": true,
|
||||||
},
|
},
|
||||||
"search.exclude": {
|
"search.exclude": {
|
||||||
"**/node_modules": true,
|
"**/node_modules": true,
|
||||||
"**/bower_components": true,
|
"**/bower_components": true,
|
||||||
"**/bazel-out": true,
|
"**/bazel-out": true,
|
||||||
"**/dist": true,
|
"**/dist": true,
|
||||||
|
"**/aio/src/generated": true,
|
||||||
},
|
},
|
||||||
"git.ignoreLimitWarning": true,
|
"git.ignoreLimitWarning": true,
|
||||||
}
|
}
|
||||||
|
96
BUILD.bazel
96
BUILD.bazel
@ -1,24 +1,30 @@
|
|||||||
|
load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary")
|
||||||
|
|
||||||
package(default_visibility = ["//visibility:public"])
|
package(default_visibility = ["//visibility:public"])
|
||||||
|
|
||||||
load("@build_bazel_rules_nodejs//:defs.bzl", "node_modules_filegroup")
|
load("//tools:defaults.bzl", "karma_web_test")
|
||||||
|
|
||||||
exports_files([
|
exports_files([
|
||||||
"tsconfig.json",
|
"tsconfig.json",
|
||||||
"LICENSE",
|
"LICENSE",
|
||||||
"protractor-perf.conf.js",
|
"protractor-perf.conf.js",
|
||||||
# Copied into the @angular/bazel package
|
"karma-js.conf.js",
|
||||||
"browser_repositories.bzl",
|
"browser-providers.conf.js",
|
||||||
])
|
])
|
||||||
|
|
||||||
filegroup(
|
filegroup(
|
||||||
name = "web_test_bootstrap_scripts",
|
name = "web_test_bootstrap_scripts",
|
||||||
# do not sort
|
# do not sort
|
||||||
srcs = [
|
srcs = [
|
||||||
"@ngdeps//node_modules/reflect-metadata:Reflect.js",
|
"@npm//node_modules/core-js:client/core.js",
|
||||||
"@ngdeps//node_modules/zone.js:dist/zone.js",
|
"@npm//node_modules/zone.js:dist/zone.js",
|
||||||
"@ngdeps//node_modules/zone.js:dist/zone-testing.js",
|
"@npm//node_modules/zone.js:dist/zone-testing.js",
|
||||||
"@ngdeps//node_modules/zone.js:dist/task-tracking.js",
|
"@npm//node_modules/zone.js:dist/task-tracking.js",
|
||||||
"//:test-events.js",
|
"//:test-events.js",
|
||||||
|
"//:shims_for_IE.js",
|
||||||
|
# Including systemjs because it defines `__eval`, which produces correct stack traces.
|
||||||
|
"@npm//node_modules/systemjs:dist/system.src.js",
|
||||||
|
"@npm//node_modules/reflect-metadata:Reflect.js",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,32 +33,58 @@ filegroup(
|
|||||||
srcs = [
|
srcs = [
|
||||||
# We also declare the unminfied AngularJS files since these can be used for
|
# We also declare the unminfied AngularJS files since these can be used for
|
||||||
# local debugging (e.g. see: packages/upgrade/test/common/test_helpers.ts)
|
# local debugging (e.g. see: packages/upgrade/test/common/test_helpers.ts)
|
||||||
"@ngdeps//node_modules/angular:angular.js",
|
"@npm//node_modules/angular:angular.js",
|
||||||
"@ngdeps//node_modules/angular:angular.min.js",
|
"@npm//node_modules/angular:angular.min.js",
|
||||||
"@ngdeps//node_modules/angular-1.5:angular.js",
|
"@npm//node_modules/angular-1.5:angular.js",
|
||||||
"@ngdeps//node_modules/angular-1.5:angular.min.js",
|
"@npm//node_modules/angular-1.5:angular.min.js",
|
||||||
"@ngdeps//node_modules/angular-1.6:angular.js",
|
"@npm//node_modules/angular-1.6:angular.js",
|
||||||
"@ngdeps//node_modules/angular-1.6:angular.min.js",
|
"@npm//node_modules/angular-1.6:angular.min.js",
|
||||||
"@ngdeps//node_modules/angular-mocks:angular-mocks.js",
|
"@npm//node_modules/angular-mocks:angular-mocks.js",
|
||||||
"@ngdeps//node_modules/angular-mocks-1.5:angular-mocks.js",
|
"@npm//node_modules/angular-mocks-1.5:angular-mocks.js",
|
||||||
"@ngdeps//node_modules/angular-mocks-1.6:angular-mocks.js",
|
"@npm//node_modules/angular-mocks-1.6:angular-mocks.js",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
load("@build_bazel_rules_nodejs//:defs.bzl", "nodejs_binary")
|
# To run a karma_web_test target locally on SauceLabs:
|
||||||
|
# 1) have SAUCE_USERNAME, SAUCE_ACCESS_KEY (and optionally a SAUCE_TUNNEL_IDENTIFIER) set in your environment
|
||||||
# A nodejs_binary for @angular/bazel/ngc-wrapped to use by default in
|
# 2) open a sauce connection with `./scripts/saucelabs/start-tunnel.sh`
|
||||||
# ng_module that depends on @npm//@angular/bazel instead of the
|
# NOTE: start-tunnel.sh uses `node_modules/sauce-connect` which is current linux specific:
|
||||||
# output of the //packages/bazel/src/ngc-wrapped ts_library rule. This
|
# "sauce-connect": "https://saucelabs.com/downloads/sc-4.5.3-linux.tar.gz".
|
||||||
# default is for downstream users that depend on the @angular/bazel npm
|
# On OSX or Windows you'll need to use the appropriate sauce-connect binary.
|
||||||
# package. The generated @npm//@angular/bazel/ngc-wrapped target
|
# 3) run target with `yarn bazel test --config=saucelabs <target>`
|
||||||
# does not work because it does not have the node `--expose-gc` flag
|
# NOTE: --config=saucelabs is required as it makes the SAUCE_XXX environment variables available to
|
||||||
# set which is required to support the call to `global.gc()`.
|
# the action. See /.bazelrc.
|
||||||
nodejs_binary(
|
karma_web_test(
|
||||||
name = "@angular/bazel/ngc-wrapped",
|
name = "test_web_all",
|
||||||
configuration_env_vars = ["compile"],
|
tags = [
|
||||||
data = ["@npm//@angular/bazel"],
|
"local",
|
||||||
entry_point = "@angular/bazel/src/ngc-wrapped/index.js",
|
"manual",
|
||||||
install_source_map_support = False,
|
"saucelabs",
|
||||||
templated_args = ["--node_options=--expose-gc"],
|
],
|
||||||
|
deps = [
|
||||||
|
# We combine all tests into a single karma_web_test target
|
||||||
|
# as running them as seperate targets in parallel leads to too many
|
||||||
|
# browsers being acquired at once in SauceLabs and the tests flake out
|
||||||
|
# TODO: this is an example subset of tests below, add all remaining angular tests
|
||||||
|
"//packages/common/http/test:test_lib",
|
||||||
|
"//packages/common/http/testing/test:test_lib",
|
||||||
|
"//packages/common/test:test_lib",
|
||||||
|
"//packages/core/test:test_lib",
|
||||||
|
"//packages/forms/test:test_lib",
|
||||||
|
"//packages/http/test:test_lib",
|
||||||
|
# "//packages/router/test:test_lib",
|
||||||
|
# //packages/router/test:test_lib fails with:
|
||||||
|
# IE 11.0.0 (Windows 8.1.0.0) bootstrap should restore the scrolling position FAILED
|
||||||
|
# Expected undefined to equal 5000.
|
||||||
|
# at stack (eval code:2338:11)
|
||||||
|
# at buildExpectationResult (eval code:2305:5)
|
||||||
|
# at expectationResultFactory (eval code:858:11)
|
||||||
|
# at Spec.prototype.addExpectationResult (eval code:487:5)
|
||||||
|
# at addExpectationResult (eval code:802:9)
|
||||||
|
# at Anonymous function (eval code:2252:7)
|
||||||
|
# at Anonymous function (eval code:339:25)
|
||||||
|
# at step (eval code:133:17)
|
||||||
|
# at Anonymous function (eval code:114:50)
|
||||||
|
# at fulfilled (eval code:104:47)
|
||||||
|
],
|
||||||
)
|
)
|
||||||
|
152
CHANGELOG.md
152
CHANGELOG.md
@ -1,3 +1,155 @@
|
|||||||
|
<a name="8.0.0-beta.9"></a>
|
||||||
|
# [8.0.0-beta.9](https://github.com/angular/angular/compare/8.0.0-beta.8...8.0.0-beta.9) (2019-03-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** correct regexp test for self-references in metadata ([#29346](https://github.com/angular/angular/issues/29346)) ([9d090cb](https://github.com/angular/angular/commit/9d090cb))
|
||||||
|
* **bazel:** don't produce self-references in metadata ([#29317](https://github.com/angular/angular/issues/29317)) ([3facdeb](https://github.com/angular/angular/commit/3facdeb)), closes [#29315](https://github.com/angular/angular/issues/29315)
|
||||||
|
* **bazel:** fix strict null checks compile error in packages/bazel/src/schematics/ng-add/index.ts ([#29282](https://github.com/angular/angular/issues/29282)) ([9a7f560](https://github.com/angular/angular/commit/9a7f560))
|
||||||
|
* **bazel:** Remove [@angular](https://github.com/angular)/upgrade from dev dependencies ([#29319](https://github.com/angular/angular/issues/29319)) ([1db8bf3](https://github.com/angular/angular/commit/1db8bf3))
|
||||||
|
* **bazel:** Support new e2e project layout ([#29318](https://github.com/angular/angular/issues/29318)) ([8ef690c](https://github.com/angular/angular/commit/8ef690c))
|
||||||
|
* **bazel:** turn off pure call tree shaking for ng_package ([#29210](https://github.com/angular/angular/issues/29210)) ([4990b93](https://github.com/angular/angular/commit/4990b93))
|
||||||
|
* **compiler-cli:** incorrect metadata bundle for multiple unnamed re-exports ([#29360](https://github.com/angular/angular/issues/29360)) ([105cfaf](https://github.com/angular/angular/commit/105cfaf)), closes [/github.com/angular/material2/blob/master/tools/package-tools/build-release.ts#L78-L85](https://github.com//github.com/angular/material2/blob/master/tools/package-tools/build-release.ts/issues/L78-L85)
|
||||||
|
* **core:** don't wrap `<tr>` and `<col>` elements into a required parent ([#29219](https://github.com/angular/angular/issues/29219)) ([f2dc32e](https://github.com/angular/angular/commit/f2dc32e))
|
||||||
|
* **core:** parse incorrect ML open tag as text ([#29328](https://github.com/angular/angular/issues/29328)) ([4605df8](https://github.com/angular/angular/commit/4605df8)), closes [#29231](https://github.com/angular/angular/issues/29231)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add support for TypeScript 3.3 (and drop older versions) ([#29004](https://github.com/angular/angular/issues/29004)) ([75748d6](https://github.com/angular/angular/commit/75748d6))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* **core:** Certain elements (like `<tr>` or `<col>`) require parent elements to be of a certain type by the HTML specification
|
||||||
|
(ex. `<tr>` can only be inside `<tbody>` / `<thead>`). Before this change Angular template parser was auto-correcting
|
||||||
|
"invalid" HTML using the following rules:
|
||||||
|
- `<tr>` would be wrapped in `<tbody>` if not inside `<tbody>`, `<tfoot>` or `<thead>`;
|
||||||
|
- `<col>` would be wrapped in `<colgroup>` if not inside `<colgroup>`.
|
||||||
|
|
||||||
|
This meachanism of automatic wrapping / auto-correcting was problematic for several reasons:
|
||||||
|
- it is non-obvious and arbitrary (ex. there are more HTML elements that has rules for parent type);
|
||||||
|
- it is incorrect for cases where `<tr>` / `<col>` are at the root of a component's content, ex.:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<projecting-tr-inside-tbody>
|
||||||
|
<tr>...</tr>
|
||||||
|
</projecting-tr-inside-tbody>
|
||||||
|
```
|
||||||
|
|
||||||
|
In the above example the `<projecting-tr-inside-tbody>` component could be "surprised" to see additional
|
||||||
|
`<tbody>` elements inserted by Angular HTML parser.
|
||||||
|
|
||||||
|
|
||||||
|
* TypeScript 3.1 and 3.2 are no longer supported.
|
||||||
|
|
||||||
|
Please update your TypeScript version to 3.3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="7.2.10"></a>
|
||||||
|
## [7.2.10](https://github.com/angular/angular/compare/7.2.9...7.2.10) (2019-03-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **compiler-cli:** incorrect metadata bundle for multiple unnamed re-exports ([#29360](https://github.com/angular/angular/issues/29360)) ([cf8d934](https://github.com/angular/angular/commit/cf8d934)), closes [/github.com/angular/material2/blob/master/tools/package-tools/build-release.ts#L78-L85](https://github.com//github.com/angular/material2/blob/master/tools/package-tools/build-release.ts/issues/L78-L85)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.0.0-beta.8"></a>
|
||||||
|
# [8.0.0-beta.8](https://github.com/angular/angular/compare/8.0.0-beta.7...8.0.0-beta.8) (2019-03-12)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** add missing binary path for api-extractor ([#29202](https://github.com/angular/angular/issues/29202)) ([df354d1](https://github.com/angular/angular/commit/df354d1))
|
||||||
|
* **bazel:** ng build should produce prod bundle ([#29136](https://github.com/angular/angular/issues/29136)) ([14ce8a9](https://github.com/angular/angular/commit/14ce8a9))
|
||||||
|
* **compiler:** ensure template is updated if an output is transformed ([#29041](https://github.com/angular/angular/issues/29041)) ([c7e4931](https://github.com/angular/angular/commit/c7e4931))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **bazel:** Eject Bazel ([#29167](https://github.com/angular/angular/issues/29167)) ([36a1550](https://github.com/angular/angular/commit/36a1550))
|
||||||
|
* **bazel:** Hide Bazel files in Bazel builder ([#29110](https://github.com/angular/angular/issues/29110)) ([7060d90](https://github.com/angular/angular/commit/7060d90))
|
||||||
|
* **forms:** clear (remove all) components from a FormArray ([#28918](https://github.com/angular/angular/issues/28918)) ([a68b1a1](https://github.com/angular/angular/commit/a68b1a1)), closes [#18531](https://github.com/angular/angular/issues/18531)
|
||||||
|
* **platform-server:** wait on returned BEFORE_APP_SERIALIZED promises ([#29120](https://github.com/angular/angular/issues/29120)) ([7102ea8](https://github.com/angular/angular/commit/7102ea8))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="7.2.9"></a>
|
||||||
|
## [7.2.9](https://github.com/angular/angular/compare/7.2.8...7.2.9) (2019-03-12)
|
||||||
|
|
||||||
|
This release contains various API docs improvements.
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.0.0-beta.7"></a>
|
||||||
|
# [8.0.0-beta.7](https://github.com/angular/angular/compare/8.0.0-beta.6...8.0.0-beta.7) (2019-03-06)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **animations:** ensure `position` and `display` styles are handled outside of keyframes/web-animations ([#28911](https://github.com/angular/angular/issues/28911)) ([a6ae759](https://github.com/angular/angular/commit/a6ae759)), closes [#24923](https://github.com/angular/angular/issues/24923) [#25635](https://github.com/angular/angular/issues/25635)
|
||||||
|
* **bazel:** add favicon to web package ([#29017](https://github.com/angular/angular/issues/29017)) ([5fdf24e](https://github.com/angular/angular/commit/5fdf24e))
|
||||||
|
* **bazel:** Add SHA256 for rules_sass ([#28994](https://github.com/angular/angular/issues/28994)) ([dc33519](https://github.com/angular/angular/commit/dc33519))
|
||||||
|
* **bazel:** api extractor don't generate tsdoc metadata ([#29023](https://github.com/angular/angular/issues/29023)) ([b5629d9](https://github.com/angular/angular/commit/b5629d9))
|
||||||
|
* **bazel:** ng serve should always watch ([#29032](https://github.com/angular/angular/issues/29032)) ([c532646](https://github.com/angular/angular/commit/c532646))
|
||||||
|
* **platform-server:** update minimum domino version to latest released ([#28893](https://github.com/angular/angular/issues/28893)) ([79e2ca0](https://github.com/angular/angular/commit/79e2ca0))
|
||||||
|
* **router:** removed obsolete TODO comment ([#29085](https://github.com/angular/angular/issues/29085)) ([72ecc45](https://github.com/angular/angular/commit/72ecc45))
|
||||||
|
* **service-worker:** detect new version even if files are identical to an old one ([#26006](https://github.com/angular/angular/issues/26006)) ([586234b](https://github.com/angular/angular/commit/586234b)), closes [#24338](https://github.com/angular/angular/issues/24338)
|
||||||
|
* **service-worker:** ignore passive mixed content requests ([#25994](https://github.com/angular/angular/issues/25994)) ([48214e2](https://github.com/angular/angular/commit/48214e2)), closes [/github.com/angular/angular/issues/23012#issuecomment-376430187](https://github.com//github.com/angular/angular/issues/23012/issues/issuecomment-376430187) [#23012](https://github.com/angular/angular/issues/23012)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **core:** update schematic to migrate to explicit query timing ([#28983](https://github.com/angular/angular/issues/28983)) ([6215799](https://github.com/angular/angular/commit/6215799))
|
||||||
|
* **service-worker:** add JSON schema for service worker config ([#27859](https://github.com/angular/angular/issues/27859)) ([3bee0f6](https://github.com/angular/angular/commit/3bee0f6)), closes [#19847](https://github.com/angular/angular/issues/19847)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="7.2.8"></a>
|
||||||
|
## [7.2.8](https://github.com/angular/angular/compare/7.2.7...7.2.8) (2019-03-06)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **animations:** ensure `position` and `display` styles are handled outside of keyframes/web-animations ([#28911](https://github.com/angular/angular/issues/28911)) ([86981b3](https://github.com/angular/angular/commit/86981b3)), closes [#24923](https://github.com/angular/angular/issues/24923) [#25635](https://github.com/angular/angular/issues/25635)
|
||||||
|
* **router:** removed obsolete TODO comment ([#29085](https://github.com/angular/angular/issues/29085)) ([2a25ac2](https://github.com/angular/angular/commit/2a25ac2))
|
||||||
|
* **service-worker:** detect new version even if files are identical to an old one ([#26006](https://github.com/angular/angular/issues/26006)) ([5669333](https://github.com/angular/angular/commit/5669333)), closes [#24338](https://github.com/angular/angular/issues/24338)
|
||||||
|
* **service-worker:** ignore passive mixed content requests ([#25994](https://github.com/angular/angular/issues/25994)) ([b598e88](https://github.com/angular/angular/commit/b598e88)), closes [/github.com/angular/angular/issues/23012#issuecomment-376430187](https://github.com//github.com/angular/angular/issues/23012/issues/issuecomment-376430187) [#23012](https://github.com/angular/angular/issues/23012)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="8.0.0-beta.6"></a>
|
||||||
|
# [8.0.0-beta.6](https://github.com/angular/angular/compare/8.0.0-beta.5...8.0.0-beta.6) (2019-02-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **bazel:** Pin browsers for schematics ([#28913](https://github.com/angular/angular/issues/28913)) ([1145bdb](https://github.com/angular/angular/commit/1145bdb))
|
||||||
|
* **bazel:** rxjs_umd_modules should always be present ([#28881](https://github.com/angular/angular/issues/28881)) ([9ae14db](https://github.com/angular/angular/commit/9ae14db))
|
||||||
|
* **compiler:** use correct variable in invalid function ([#28656](https://github.com/angular/angular/issues/28656)) ([f75acbd](https://github.com/angular/angular/commit/f75acbd))
|
||||||
|
* **core:** traverse and sanitize content of unsafe elements ([#28804](https://github.com/angular/angular/issues/28804)) ([262ba67](https://github.com/angular/angular/commit/262ba67)), 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)) ([ad4a9bf](https://github.com/angular/angular/commit/ad4a9bf)), closes [#27959](https://github.com/angular/angular/issues/27959)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **bazel:** add ts_config extending support for ng_module ([#21883](https://github.com/angular/angular/issues/21883)) ([edb6c2d](https://github.com/angular/angular/commit/edb6c2d))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="7.2.7"></a>
|
||||||
|
## [7.2.7](https://github.com/angular/angular/compare/7.2.6...7.2.7) (2019-02-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **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="8.0.0-beta.5"></a>
|
<a name="8.0.0-beta.5"></a>
|
||||||
# [8.0.0-beta.5](https://github.com/angular/angular/compare/8.0.0-beta.4...8.0.0-beta.5) (2019-02-20)
|
# [8.0.0-beta.5](https://github.com/angular/angular/compare/8.0.0-beta.4...8.0.0-beta.5) (2019-02-20)
|
||||||
|
|
||||||
|
73
WORKSPACE
73
WORKSPACE
@ -8,56 +8,79 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "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",
|
||||||
#)
|
#)
|
||||||
|
|
||||||
# Fetch rules_nodejs so we can install our npm dependencies
|
# Fetch rules_nodejs so we can install our npm dependencies
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "build_bazel_rules_nodejs",
|
name = "build_bazel_rules_nodejs",
|
||||||
sha256 = "1416d03823fed624b49a0abbd9979f7c63bbedfd37890ddecedd2fe25cccebc6",
|
sha256 = "fb87ed5965cef93188af9a7287511639403f4b0da418961ce6defb9dcf658f51",
|
||||||
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.18.6/rules_nodejs-0.18.6.tar.gz"],
|
urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/0.27.7/rules_nodejs-0.27.7.tar.gz"],
|
||||||
)
|
|
||||||
|
|
||||||
# Use a mock @npm repository while we are building angular from source
|
|
||||||
# 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(
|
|
||||||
name = "npm",
|
|
||||||
path = "tools/npm_workspace",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Check the bazel version and download npm dependencies
|
# Check the bazel version and download npm dependencies
|
||||||
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories")
|
load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "check_rules_nodejs_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 Using --incompatible_strict_action_env flag fixes cache when running `yarn bazel`
|
# - 0.21.0 Using --incompatible_strict_action_env flag fixes cache when 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(
|
||||||
|
message = """
|
||||||
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.
|
||||||
Try running `yarn bazel` instead.
|
Try running `yarn bazel` instead.
|
||||||
(If you did run that, check that you've got a fresh `yarn install`)
|
(If you did run that, check that you've got a fresh `yarn install`)
|
||||||
|
|
||||||
""")
|
""",
|
||||||
|
minimum_bazel_version = "0.21.0",
|
||||||
|
)
|
||||||
|
|
||||||
|
# The NodeJS rules version must be at least v0.15.3 because:
|
||||||
|
# - 0.15.2 Re-introduced the prod_only attribute on yarn_install
|
||||||
|
# - 0.15.3 Includes a fix for the `jasmine_node_test` rule ignoring target tags
|
||||||
|
# - 0.16.8 Supports npm installed bazel workspaces
|
||||||
|
# - 0.26.0 Fix for data files in yarn_install and npm_install
|
||||||
|
check_rules_nodejs_version("0.26.0")
|
||||||
|
|
||||||
# Setup the Node.js toolchain
|
# 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,
|
||||||
vendored_yarn = "@angular//third_party/github.com/yarnpkg/yarn/releases/download:v1.13.0",
|
# yarn 1.13.0 under Bazel has a regression on Windows that causes build errors on rebuilds:
|
||||||
|
# ```
|
||||||
|
# ERROR: Source forest creation failed: C:/.../fyuc5c3n/execroot/angular/external (Directory not empty)
|
||||||
|
# ```
|
||||||
|
# See https://github.com/angular/angular/pull/29431 for more information.
|
||||||
|
# It possible that versions of yarn past 1.13.0 do not have this issue, however, before
|
||||||
|
# advancing this version we need to test manually on Windows that the above error does not
|
||||||
|
# happen as the issue is not caught by CI.
|
||||||
|
yarn_version = "1.12.1",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Setup the angular toolchain which installs npm dependencies into @ngdeps
|
yarn_install(
|
||||||
load("//tools:ng_setup_workspace.bzl", "ng_setup_workspace")
|
name = "npm",
|
||||||
|
data = [
|
||||||
|
"//:tools/npm/@angular_bazel/index.js",
|
||||||
|
"//:tools/npm/@angular_bazel/package.json",
|
||||||
|
"//:tools/postinstall-patches.js",
|
||||||
|
"//:tools/yarn/check-yarn.js",
|
||||||
|
],
|
||||||
|
package_json = "//:package.json",
|
||||||
|
# Don't install devDependencies, they are large and not used under Bazel
|
||||||
|
prod_only = True,
|
||||||
|
yarn_lock = "//:yarn.lock",
|
||||||
|
)
|
||||||
|
|
||||||
ng_setup_workspace()
|
yarn_install(
|
||||||
|
name = "ts-api-guardian_deps",
|
||||||
|
package_json = "@angular//tools/ts-api-guardian:package.json",
|
||||||
|
yarn_lock = "@angular//tools/ts-api-guardian:yarn.lock",
|
||||||
|
)
|
||||||
|
|
||||||
# Install all bazel dependencies of the @ngdeps npm packages
|
# Install all bazel dependencies of the @npm npm packages
|
||||||
load("@ngdeps//:install_bazel_dependencies.bzl", "install_bazel_dependencies")
|
load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies")
|
||||||
|
|
||||||
install_bazel_dependencies()
|
install_bazel_dependencies()
|
||||||
|
|
||||||
@ -67,7 +90,7 @@ load("//packages/bazel:package.bzl", "rules_angular_dev_dependencies")
|
|||||||
rules_angular_dev_dependencies()
|
rules_angular_dev_dependencies()
|
||||||
|
|
||||||
# Load karma dependencies
|
# Load karma dependencies
|
||||||
load("@build_bazel_rules_karma//:package.bzl", "rules_karma_dependencies")
|
load("@npm_bazel_karma//:package.bzl", "rules_karma_dependencies")
|
||||||
|
|
||||||
rules_karma_dependencies()
|
rules_karma_dependencies()
|
||||||
|
|
||||||
@ -78,12 +101,12 @@ web_test_repositories()
|
|||||||
|
|
||||||
# Temporary work-around for https://github.com/angular/angular/issues/28681
|
# Temporary work-around for https://github.com/angular/angular/issues/28681
|
||||||
# TODO(gregmagolan): go back to @io_bazel_rules_webtesting browser_repositories
|
# TODO(gregmagolan): go back to @io_bazel_rules_webtesting browser_repositories
|
||||||
load("@angular//:browser_repositories.bzl", "browser_repositories")
|
load("@npm_bazel_karma//:browser_repositories.bzl", "browser_repositories")
|
||||||
|
|
||||||
browser_repositories()
|
browser_repositories()
|
||||||
|
|
||||||
# Setup the rules_typescript tooolchain
|
# Setup the rules_typescript tooolchain
|
||||||
load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace")
|
load("@npm_bazel_typescript//:index.bzl", "ts_setup_workspace")
|
||||||
|
|
||||||
ts_setup_workspace()
|
ts_setup_workspace()
|
||||||
|
|
||||||
|
@ -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=aio-contributors
|
ARG AIO_GITHUB_TEAM_SLUGS=aio-auto-previews,aio-contributors
|
||||||
ARG TEST_AIO_GITHUB_TEAM_SLUGS=aio-contributors
|
ARG TEST_AIO_GITHUB_TEAM_SLUGS=test-team-1,test-team-2
|
||||||
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
|
||||||
|
38
aio/content/cli/usage-analytics-gathering.md
Normal file
38
aio/content/cli/usage-analytics-gathering.md
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# Gathering Usage Analytics
|
||||||
|
Administrators can configure their instances of Angular CLI to share usage analytics with
|
||||||
|
third parties. This sharing is separate from and in addition to usage analytics shared
|
||||||
|
with Google. It is disabled by default and cannot be enabled at the project level for
|
||||||
|
all users. It must be set at the global configuration level for each user to allow
|
||||||
|
managed users to opt in and share usage analytics.
|
||||||
|
|
||||||
|
To configure usage analytics sharing, use the `ng config` command to add both the user ID
|
||||||
|
and the third-party ID to the user's global Angular CLI configuration.
|
||||||
|
|
||||||
|
- The third-party ID is the tracking identifier of the third-party Google Analytics
|
||||||
|
account. This ID is a string that looks like `UA-123456-12`.
|
||||||
|
- You can choose a user ID, or be assigned a random user ID when you run the CLI command.
|
||||||
|
|
||||||
|
Once you have the third-party tracking ID, add it to your global configuration using the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
ng config --global cli.analyticsSharing.tracking UA-123456-12
|
||||||
|
```
|
||||||
|
|
||||||
|
To add a custom user ID to the global configuration using the following command. This
|
||||||
|
should be unique per users to identify unique usage of commands and flags.
|
||||||
|
|
||||||
|
```
|
||||||
|
ng config --global cli.analyticsSharing.user SOME_USER_NAME
|
||||||
|
```
|
||||||
|
|
||||||
|
To generate a new random user ID, run the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
ng config --global cli.analyticsSharing.user ""
|
||||||
|
```
|
||||||
|
|
||||||
|
To turn off this feature, run the following command:
|
||||||
|
|
||||||
|
```
|
||||||
|
ng config --global --remove cli.analyticsSharing
|
||||||
|
```
|
3
aio/content/examples/.gitignore
vendored
3
aio/content/examples/.gitignore
vendored
@ -92,3 +92,6 @@ upgrade-phonecat-3-final/tsconfig-aot.json
|
|||||||
upgrade-phonecat-3-final/rollup-config.js
|
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
|
||||||
|
|
||||||
|
# schematics
|
||||||
|
!schematics-for-libraries/projects/my-lib/package.json
|
@ -0,0 +1,20 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
|
describe('Built Template Functions Example', function () {
|
||||||
|
beforeAll(function () {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have title Built-in Template Functions', function () {
|
||||||
|
let title = element.all(by.css('h1')).get(0);
|
||||||
|
expect(title.getText()).toEqual('Built-in Template Functions');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display $any( ) in h2', function () {
|
||||||
|
let header = element(by.css('h2'));
|
||||||
|
expect(header.getText()).toContain('$any( )');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,15 @@
|
|||||||
|
<h1>{{title}}</h1>
|
||||||
|
|
||||||
|
<h2><code>$any( )</code> type cast function and an undeclared member</h2>
|
||||||
|
|
||||||
|
<p>There is no such member as <code>bestByDate</code> in the following two examples, so nothing renders:</p>
|
||||||
|
<!-- #docregion any-type-cast-function-1 -->
|
||||||
|
<p>The item's undeclared best by date is: {{$any(item).bestByDate}}</p>
|
||||||
|
<!-- #enddocregion any-type-cast-function-1 -->
|
||||||
|
|
||||||
|
<h2>using <code>this</code></h2>
|
||||||
|
<!-- #docregion any-type-cast-function-2 -->
|
||||||
|
<p>The item's undeclared best by date is: {{$any(this).bestByDate}}</p>
|
||||||
|
<!-- #enddocregion any-type-cast-function-2 -->
|
||||||
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
|||||||
|
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();
|
||||||
|
}));
|
||||||
|
});
|
@ -0,0 +1,16 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styleUrls: ['./app.component.css']
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
title = 'Built-in Template Functions';
|
||||||
|
|
||||||
|
item = {
|
||||||
|
name : 'Telephone',
|
||||||
|
origin : 'Sweden',
|
||||||
|
price: 98
|
||||||
|
};
|
||||||
|
}
|
@ -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 { }
|
@ -0,0 +1,14 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Built-in Template Functions Example</title>
|
||||||
|
<base href="/">
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<app-root>Loading...</app-root>
|
||||||
|
</body>
|
||||||
|
</html>
|
11
aio/content/examples/built-in-template-functions/src/main.ts
Normal file
11
aio/content/examples/built-in-template-functions/src/main.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
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);
|
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"description": "Built-in Template Functions",
|
||||||
|
"files": [
|
||||||
|
"!**/*.d.ts",
|
||||||
|
"!**/*.js",
|
||||||
|
"!**/*.[1,2].*"
|
||||||
|
],
|
||||||
|
"file": "src/app/app.component.ts",
|
||||||
|
"tags": ["Built-in Template Functions"]
|
||||||
|
}
|
@ -4,7 +4,8 @@
|
|||||||
"cmd": "yarn",
|
"cmd": "yarn",
|
||||||
"args": [
|
"args": [
|
||||||
"e2e",
|
"e2e",
|
||||||
"--no-webdriver-update"
|
"--no-webdriver-update",
|
||||||
|
"--port={PORT}"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
"cmd": "yarn",
|
"cmd": "yarn",
|
||||||
"args": [
|
"args": [
|
||||||
"e2e",
|
"e2e",
|
||||||
"--no-webdriver-update"
|
"--no-webdriver-update",
|
||||||
|
"--port={PORT}"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
'@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
|
'@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
|
||||||
'@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
|
'@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
|
||||||
'@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
|
'@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
|
||||||
'@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
|
|
||||||
'@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
|
'@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
|
||||||
'@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js',
|
'@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js',
|
||||||
},
|
},
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
"cmd": "yarn",
|
"cmd": "yarn",
|
||||||
"args": [
|
"args": [
|
||||||
"e2e",
|
"e2e",
|
||||||
"--no-webdriver-update"
|
"--no-webdriver-update",
|
||||||
|
"--port={PORT}"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -13,15 +13,4 @@ describe('AppComponent', () => {
|
|||||||
const app = fixture.debugElement.componentInstance;
|
const app = fixture.debugElement.componentInstance;
|
||||||
expect(app).toBeTruthy();
|
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:');
|
|
||||||
}));
|
|
||||||
});
|
});
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -31,6 +31,7 @@ describe('Router', () => {
|
|||||||
heroDetailTitle: heroDetail.element(by.xpath('*[2]')),
|
heroDetailTitle: heroDetail.element(by.xpath('*[2]')),
|
||||||
|
|
||||||
adminHref: hrefEles.get(2),
|
adminHref: hrefEles.get(2),
|
||||||
|
adminPage: element(by.css('app-root > div > app-admin')),
|
||||||
adminPreloadList: element.all(by.css('app-root > div > app-admin > app-admin-dashboard > ul > li')),
|
adminPreloadList: element.all(by.css('app-root > div > app-admin > app-admin-dashboard > ul > li')),
|
||||||
|
|
||||||
loginHref: hrefEles.get(3),
|
loginHref: hrefEles.get(3),
|
||||||
@ -138,6 +139,31 @@ describe('Router', () => {
|
|||||||
expect(page.secondaryOutlet.count()).toBe(1, 'secondary outlet');
|
expect(page.secondaryOutlet.count()).toBe(1, 'secondary outlet');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should redirect with secondary route', async () => {
|
||||||
|
const page = getPageStruct();
|
||||||
|
|
||||||
|
// go to login page and login
|
||||||
|
await browser.get('');
|
||||||
|
await page.loginHref.click();
|
||||||
|
await page.loginButton.click();
|
||||||
|
|
||||||
|
// open secondary outlet
|
||||||
|
await page.contactHref.click();
|
||||||
|
|
||||||
|
// go to login page and logout
|
||||||
|
await page.loginHref.click();
|
||||||
|
await page.loginButton.click();
|
||||||
|
|
||||||
|
// attempt to go to admin page, redirects to login with secondary outlet open
|
||||||
|
await page.adminHref.click();
|
||||||
|
|
||||||
|
// login, get redirected back to admin with outlet still open
|
||||||
|
await page.loginButton.click();
|
||||||
|
|
||||||
|
expect(await page.adminPage.isDisplayed()).toBeTruthy();
|
||||||
|
expect(page.secondaryOutlet.count()).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
async function crisisCenterEdit(index: number, save: boolean) {
|
async function crisisCenterEdit(index: number, save: boolean) {
|
||||||
const page = getPageStruct();
|
const page = getPageStruct();
|
||||||
await page.crisisHref.click();
|
await page.crisisHref.click();
|
||||||
|
@ -27,10 +27,10 @@ export class LoginComponent {
|
|||||||
if (this.authService.isLoggedIn) {
|
if (this.authService.isLoggedIn) {
|
||||||
// Get the redirect URL from our auth service
|
// Get the redirect URL from our auth service
|
||||||
// If no redirect has been set, use the default
|
// If no redirect has been set, use the default
|
||||||
let redirect = this.authService.redirectUrl ? this.authService.redirectUrl : '/crisis-center/admin';
|
let redirect = this.authService.redirectUrl ? this.router.parseUrl(this.authService.redirectUrl) : '/admin';
|
||||||
|
|
||||||
// Redirect the user
|
// Redirect the user
|
||||||
this.router.navigate([redirect]);
|
this.router.navigateByUrl(redirect);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ export class LoginComponent {
|
|||||||
if (this.authService.isLoggedIn) {
|
if (this.authService.isLoggedIn) {
|
||||||
// Get the redirect URL from our auth service
|
// Get the redirect URL from our auth service
|
||||||
// If no redirect has been set, use the default
|
// If no redirect has been set, use the default
|
||||||
let redirect = this.authService.redirectUrl ? this.authService.redirectUrl : '/admin';
|
let redirect = this.authService.redirectUrl ? this.router.parseUrl(this.authService.redirectUrl) : '/admin';
|
||||||
|
|
||||||
// #docregion preserve
|
// #docregion preserve
|
||||||
// Set our navigation extras object
|
// Set our navigation extras object
|
||||||
@ -39,7 +39,7 @@ export class LoginComponent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Redirect the user
|
// Redirect the user
|
||||||
this.router.navigate([redirect], navigationExtras);
|
this.router.navigateByUrl(redirect, navigationExtras);
|
||||||
// #enddocregion preserve
|
// #enddocregion preserve
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"projectType": "schematics"
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
|
||||||
|
"dest": "../../dist/my-lib",
|
||||||
|
"lib": {
|
||||||
|
"entryFile": "src/public_api.ts"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
// #docplaster
|
||||||
|
// #docregion collection
|
||||||
|
{
|
||||||
|
"name": "my-lib",
|
||||||
|
"version": "0.0.1",
|
||||||
|
// #enddocregion collection
|
||||||
|
"scripts": {
|
||||||
|
"build": "../../node_modules/.bin/tsc -p tsconfig.schematics.json",
|
||||||
|
"copy:schemas": "cp --parents schematics/*/schema.json ../../dist/my-lib/",
|
||||||
|
"copy:files": "cp --parents -p schematics/*/files/** ../../dist/my-lib/",
|
||||||
|
"copy:collection": "cp schematics/collection.json ../../dist/my-lib/schematics/collection.json",
|
||||||
|
"postbuild": "npm run copy:schemas && npm run copy:files && npm run copy:collection"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/common": "^7.2.0",
|
||||||
|
"@angular/core": "^7.2.0"
|
||||||
|
},
|
||||||
|
// #docregion collection
|
||||||
|
"schematics": "./schematics/collection.json"
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../../../node_modules/@angular-devkit/schematics/collection-schema.json",
|
||||||
|
"schematics": {
|
||||||
|
"ng-add": {
|
||||||
|
"description": "Add my library to the project.",
|
||||||
|
"factory": "./ng-add/index#ngAdd"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../../../node_modules/@angular-devkit/schematics/collection-schema.json",
|
||||||
|
"schematics": {
|
||||||
|
"ng-add": {
|
||||||
|
"description": "Add my library to the project.",
|
||||||
|
"factory": "./ng-add/index#ngAdd"
|
||||||
|
},
|
||||||
|
"my-service": {
|
||||||
|
"description": "Generate a service in the project.",
|
||||||
|
"factory": "./my-service/index#myService",
|
||||||
|
"schema": "./my-service/schema.json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
// #docregion template
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class <%= classify(name) %>Service {
|
||||||
|
constructor(private http: HttpClient) { }
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
import { Rule, Tree } from '@angular-devkit/schematics';
|
||||||
|
|
||||||
|
import { Schema as MyServiceSchema } from './schema';
|
||||||
|
|
||||||
|
// #docregion factory
|
||||||
|
export function myService(options: MyServiceSchema): Rule {
|
||||||
|
return (tree: Tree) => {
|
||||||
|
return tree;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// #enddocregion factory
|
@ -0,0 +1,66 @@
|
|||||||
|
// #docplaster
|
||||||
|
// #docregion schematics-imports, schema-imports, workspace
|
||||||
|
import {
|
||||||
|
Rule, Tree, SchematicsException,
|
||||||
|
apply, url, applyTemplates, move,
|
||||||
|
chain, mergeWith
|
||||||
|
} from '@angular-devkit/schematics';
|
||||||
|
|
||||||
|
import { strings, normalize, experimental } from '@angular-devkit/core';
|
||||||
|
// #enddocregion schematics-imports
|
||||||
|
|
||||||
|
import { Schema as MyServiceSchema } from './schema';
|
||||||
|
// #enddocregion schema-imports
|
||||||
|
|
||||||
|
export function myService(options: MyServiceSchema): Rule {
|
||||||
|
return (tree: Tree) => {
|
||||||
|
const workspaceConfig = tree.read('/angular.json');
|
||||||
|
if (!workspaceConfig) {
|
||||||
|
throw new SchematicsException('Could not find Angular workspace configuration');
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert workspace to string
|
||||||
|
const workspaceContent = workspaceConfig.toString();
|
||||||
|
|
||||||
|
// parse workspace string into JSON object
|
||||||
|
const workspace: experimental.workspace.WorkspaceSchema = JSON.parse(workspaceContent);
|
||||||
|
// #enddocregion workspace
|
||||||
|
// #docregion project-fallback
|
||||||
|
if (!options.project) {
|
||||||
|
options.project = workspace.defaultProject;
|
||||||
|
}
|
||||||
|
// #enddocregion project-fallback
|
||||||
|
|
||||||
|
// #docregion project-info
|
||||||
|
const projectName = options.project as string;
|
||||||
|
|
||||||
|
const project = workspace.projects[projectName];
|
||||||
|
|
||||||
|
const projectType = project.projectType === 'application' ? 'app' : 'lib';
|
||||||
|
// #enddocregion project-info
|
||||||
|
|
||||||
|
// #docregion path
|
||||||
|
if (options.path === undefined) {
|
||||||
|
options.path = `${project.sourceRoot}/${projectType}`;
|
||||||
|
}
|
||||||
|
// #enddocregion path
|
||||||
|
|
||||||
|
// #docregion template
|
||||||
|
const templateSource = apply(url('./files'), [
|
||||||
|
applyTemplates({
|
||||||
|
classify: strings.classify,
|
||||||
|
dasherize: strings.dasherize,
|
||||||
|
name: options.name
|
||||||
|
}),
|
||||||
|
move(normalize(options.path as string))
|
||||||
|
]);
|
||||||
|
// #enddocregion template
|
||||||
|
|
||||||
|
// #docregion chain
|
||||||
|
return chain([
|
||||||
|
mergeWith(templateSource)
|
||||||
|
]);
|
||||||
|
// #enddocregion chain
|
||||||
|
// #docregion workspace
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/schema",
|
||||||
|
"id": "SchematicsMyService",
|
||||||
|
"title": "My Service Schema",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"description": "The name of the service.",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "path",
|
||||||
|
"description": "The path to create the service.",
|
||||||
|
"visible": false
|
||||||
|
},
|
||||||
|
"project": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The name of the project.",
|
||||||
|
"$default": {
|
||||||
|
"$source": "projectName"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"name"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
export interface Schema {
|
||||||
|
// The name of the service.
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
// The path to create the service.
|
||||||
|
path?: string;
|
||||||
|
|
||||||
|
// The name of the project.
|
||||||
|
project?: string;
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
|
||||||
|
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
|
||||||
|
|
||||||
|
// Just return the tree
|
||||||
|
export function ngAdd(_options: any): Rule {
|
||||||
|
return (tree: Tree, _context: SchematicContext) => {
|
||||||
|
_context.addTask(new NodePackageInstallTask());
|
||||||
|
return tree;
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { MyLibComponent } from './my-lib.component';
|
||||||
|
|
||||||
|
describe('MyLibComponent', () => {
|
||||||
|
let component: MyLibComponent;
|
||||||
|
let fixture: ComponentFixture<MyLibComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ MyLibComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(MyLibComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,19 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'lib-my-lib',
|
||||||
|
template: `
|
||||||
|
<p>
|
||||||
|
my-lib works!
|
||||||
|
</p>
|
||||||
|
`,
|
||||||
|
styles: []
|
||||||
|
})
|
||||||
|
export class MyLibComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { MyLibComponent } from './my-lib.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [MyLibComponent],
|
||||||
|
imports: [
|
||||||
|
],
|
||||||
|
exports: [MyLibComponent]
|
||||||
|
})
|
||||||
|
export class MyLibModule { }
|
@ -0,0 +1,12 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { MyLibService } from './my-lib.service';
|
||||||
|
|
||||||
|
describe('MyLibService', () => {
|
||||||
|
beforeEach(() => TestBed.configureTestingModule({}));
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
const service: MyLibService = TestBed.get(MyLibService);
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,9 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class MyLibService {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* Public API Surface of my-lib
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from './lib/my-lib.service';
|
||||||
|
export * from './lib/my-lib.component';
|
||||||
|
export * from './lib/my-lib.module';
|
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../out-tsc/lib",
|
||||||
|
"target": "es2015",
|
||||||
|
"module": "es2015",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"declaration": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"inlineSources": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"importHelpers": true,
|
||||||
|
"types": [],
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"es2018"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"annotateForClosureCompiler": true,
|
||||||
|
"skipTemplateCodegen": true,
|
||||||
|
"strictMetadataEmit": true,
|
||||||
|
"fullTemplateTypeCheck": true,
|
||||||
|
"strictInjectionParameters": true,
|
||||||
|
"enableResourceInlining": true
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"src/test.ts",
|
||||||
|
"**/*.spec.ts"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"lib": [
|
||||||
|
"es2018",
|
||||||
|
"dom"
|
||||||
|
],
|
||||||
|
"declaration": true,
|
||||||
|
"module": "commonjs",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"noEmitOnError": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"noImplicitThis": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"rootDir": "schematics",
|
||||||
|
"outDir": "../../dist/my-lib/schematics",
|
||||||
|
"skipDefaultLibCheck": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"target": "es6",
|
||||||
|
"types": [
|
||||||
|
"jasmine",
|
||||||
|
"node"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"schematics/**/*"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"schematics/*/files/**/*"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "../../out-tsc/spec",
|
||||||
|
"types": [
|
||||||
|
"jasmine",
|
||||||
|
"node"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"src/test.ts"
|
||||||
|
],
|
||||||
|
"include": [
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/*.d.ts"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
template: `
|
||||||
|
<h2>Library Schematics</h2>
|
||||||
|
`,
|
||||||
|
styles: []
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
title = 'schematics-for-libraries';
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
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 { }
|
14
aio/content/examples/schematics-for-libraries/src/index.html
Normal file
14
aio/content/examples/schematics-for-libraries/src/index.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>SchematicsForLibraries</title>
|
||||||
|
<base href="/">
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<app-root></app-root>
|
||||||
|
</body>
|
||||||
|
</html>
|
12
aio/content/examples/schematics-for-libraries/src/main.ts
Normal file
12
aio/content/examples/schematics-for-libraries/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.error(err));
|
10
aio/content/examples/schematics-for-libraries/zipper.json
Normal file
10
aio/content/examples/schematics-for-libraries/zipper.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"description": "Schematics For Libraries",
|
||||||
|
"files": [
|
||||||
|
"!**/*.d.ts",
|
||||||
|
"!**/*.js",
|
||||||
|
"!**/*.[1].*",
|
||||||
|
"**/*.template"
|
||||||
|
],
|
||||||
|
"tags": ["Angular", "Libraries", "Schematics"]
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"projectType": "service-worker",
|
"projectType": "service-worker",
|
||||||
"e2e": [
|
"e2e": [
|
||||||
{"cmd": "yarn", "args": ["e2e", "--no-webdriver-update"]},
|
{"cmd": "yarn", "args": ["e2e", "--no-webdriver-update", "--port={PORT}"]},
|
||||||
{"cmd": "yarn", "args": ["build", "--prod"]},
|
{"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.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(fs.existsSync('./dist/ngsw-worker.js'), 'ngsw-worker.js is missing')"]},
|
||||||
|
@ -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 -->
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,19 +1,16 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Http } from '@angular/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
|
||||||
|
|
||||||
import { Hero } from './hero.model';
|
import { Hero } from './hero.model';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class HeroService {
|
export class HeroService {
|
||||||
|
|
||||||
constructor(private http: Http) {}
|
constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
getHeroes(): Observable<Hero[]> {
|
getHeroes(): Observable<Hero[]> {
|
||||||
return this.http.get('api/heroes').pipe(
|
return this.http.get<Hero[]>('api/heroes');
|
||||||
map(resp => resp.json().data as Hero[])
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
/* avoid */
|
/* avoid */
|
||||||
|
|
||||||
import { OnInit } from '@angular/core';
|
import { OnInit } from '@angular/core';
|
||||||
import { Http, Response } from '@angular/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { catchError, finalize, map } from 'rxjs/operators';
|
import { catchError, finalize } from 'rxjs/operators';
|
||||||
|
|
||||||
import { Hero } from '../shared/hero.model';
|
import { Hero } from '../shared/hero.model';
|
||||||
|
|
||||||
@ -13,11 +13,10 @@ const heroesUrl = 'http://angular.io';
|
|||||||
|
|
||||||
export class HeroListComponent implements OnInit {
|
export class HeroListComponent implements OnInit {
|
||||||
heroes: Hero[];
|
heroes: Hero[];
|
||||||
constructor(private http: Http) {}
|
constructor(private http: HttpClient) {}
|
||||||
getHeroes() {
|
getHeroes() {
|
||||||
this.heroes = [];
|
this.heroes = [];
|
||||||
this.http.get(heroesUrl).pipe(
|
this.http.get(heroesUrl).pipe(
|
||||||
map((response: Response) => <Hero[]>response.json().data),
|
|
||||||
catchError(this.catchBadResponse),
|
catchError(this.catchBadResponse),
|
||||||
finalize(() => this.hideSpinner())
|
finalize(() => this.hideSpinner())
|
||||||
).subscribe((heroes: Hero[]) => this.heroes = heroes);
|
).subscribe((heroes: Hero[]) => this.heroes = heroes);
|
||||||
|
@ -1,18 +1,16 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Http, Response } from '@angular/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { map } from 'rxjs/operators';
|
|
||||||
|
|
||||||
import { Hero } from './hero.model';
|
import { Hero } from './hero.model';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
// #docregion example
|
// #docregion example
|
||||||
export class HeroService {
|
export class HeroService {
|
||||||
constructor(private http: Http) { }
|
constructor(private http: HttpClient) { }
|
||||||
|
|
||||||
getHeroes() {
|
getHeroes() {
|
||||||
return this.http.get('api/heroes').pipe(
|
return this.http.get<Hero[]>('api/heroes');
|
||||||
map((response: Response) => <Hero[]>response.json()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #enddocregion example
|
// #enddocregion example
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Inject } from '@angular/core';
|
import { Inject } from '@angular/core';
|
||||||
import { Http } from '@angular/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
|
||||||
import { HeroService } from './hero.service';
|
import { HeroService } from './hero.service';
|
||||||
// #docregion example
|
// #docregion example
|
||||||
@ -9,6 +9,6 @@ import { HeroService } from './hero.service';
|
|||||||
export class HeroArena {
|
export class HeroArena {
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(HeroService) private heroService: HeroService,
|
@Inject(HeroService) private heroService: HeroService,
|
||||||
@Inject(Http) private http: Http) {}
|
@Inject(HttpClient) private http: HttpClient) {}
|
||||||
}
|
}
|
||||||
// #enddocregion example
|
// #enddocregion example
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion
|
// #docregion
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Http } from '@angular/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
|
||||||
import { HeroService } from './hero.service';
|
import { HeroService } from './hero.service';
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ import { HeroService } from './hero.service';
|
|||||||
export class HeroArena {
|
export class HeroArena {
|
||||||
constructor(
|
constructor(
|
||||||
private heroService: HeroService,
|
private heroService: HeroService,
|
||||||
private http: Http) {}
|
private http: HttpClient) {}
|
||||||
// #enddocregion example
|
// #enddocregion example
|
||||||
// test harness
|
// test harness
|
||||||
getParticipants() {
|
getParticipants() {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
import { HttpModule } from '@angular/http';
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
|
import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
|
||||||
|
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
@ -44,7 +44,7 @@ import * as s0901 from '../09-01/app/app.module';
|
|||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
HttpModule,
|
HttpClientModule,
|
||||||
InMemoryWebApiModule.forRoot(HeroData),
|
InMemoryWebApiModule.forRoot(HeroData),
|
||||||
|
|
||||||
s0101.AppModule,
|
s0101.AppModule,
|
||||||
|
@ -4,86 +4,103 @@ import { interval, of } from 'rxjs';
|
|||||||
import { delay, take } from 'rxjs/operators';
|
import { delay, take } from 'rxjs/operators';
|
||||||
|
|
||||||
describe('Angular async helper', () => {
|
describe('Angular async helper', () => {
|
||||||
let actuallyDone = false;
|
|
||||||
|
|
||||||
beforeEach(() => { actuallyDone = false; });
|
describe('async', () => {
|
||||||
|
let actuallyDone = false;
|
||||||
|
|
||||||
afterEach(() => { expect(actuallyDone).toBe(true, 'actuallyDone should be true'); });
|
beforeEach(() => { actuallyDone = false; });
|
||||||
|
|
||||||
it('should run normal test', () => { actuallyDone = true; });
|
afterEach(() => { expect(actuallyDone).toBe(true, 'actuallyDone should be true'); });
|
||||||
|
|
||||||
it('should run normal async test', (done: DoneFn) => {
|
it('should run normal test', () => { actuallyDone = true; });
|
||||||
setTimeout(() => {
|
|
||||||
actuallyDone = true;
|
it('should run normal async test', (done: DoneFn) => {
|
||||||
done();
|
setTimeout(() => {
|
||||||
}, 0);
|
actuallyDone = true;
|
||||||
|
done();
|
||||||
|
}, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should run async test with task',
|
||||||
|
async(() => { setTimeout(() => { actuallyDone = true; }, 0); }));
|
||||||
|
|
||||||
|
it('should run async test with task', async(() => {
|
||||||
|
const id = setInterval(() => {
|
||||||
|
actuallyDone = true;
|
||||||
|
clearInterval(id);
|
||||||
|
}, 100);
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should run async test with successful promise', async(() => {
|
||||||
|
const p = new Promise(resolve => { setTimeout(resolve, 10); });
|
||||||
|
p.then(() => { actuallyDone = true; });
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should run async test with failed promise', async(() => {
|
||||||
|
const p = new Promise((resolve, reject) => { setTimeout(reject, 10); });
|
||||||
|
p.catch(() => { actuallyDone = true; });
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Use done. Can also use async or fakeAsync.
|
||||||
|
it('should run async test with successful delayed Observable', (done: DoneFn) => {
|
||||||
|
const source = of (true).pipe(delay(10));
|
||||||
|
source.subscribe(val => actuallyDone = true, err => fail(err), done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should run async test with successful delayed Observable', async(() => {
|
||||||
|
const source = of (true).pipe(delay(10));
|
||||||
|
source.subscribe(val => actuallyDone = true, err => fail(err));
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should run async test with successful delayed Observable', fakeAsync(() => {
|
||||||
|
const source = of (true).pipe(delay(10));
|
||||||
|
source.subscribe(val => actuallyDone = true, err => fail(err));
|
||||||
|
|
||||||
|
tick(10);
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should run async test with task',
|
describe('fakeAsync', () => {
|
||||||
async(() => { setTimeout(() => { actuallyDone = true; }, 0); }));
|
// #docregion fake-async-test-tick
|
||||||
|
it('should run timeout callback with delay after call tick with millis', fakeAsync(() => {
|
||||||
|
let called = false;
|
||||||
|
setTimeout(() => { called = true; }, 100);
|
||||||
|
tick(100);
|
||||||
|
expect(called).toBe(true);
|
||||||
|
}));
|
||||||
|
// #enddocregion fake-async-test-tick
|
||||||
|
|
||||||
it('should run async test with task', async(() => {
|
// #docregion fake-async-test-date
|
||||||
const id = setInterval(() => {
|
it('should get Date diff correctly in fakeAsync', fakeAsync(() => {
|
||||||
actuallyDone = true;
|
const start = Date.now();
|
||||||
clearInterval(id);
|
tick(100);
|
||||||
}, 100);
|
const end = Date.now();
|
||||||
}));
|
expect(end - start).toBe(100);
|
||||||
|
}));
|
||||||
|
// #enddocregion fake-async-test-date
|
||||||
|
|
||||||
it('should run async test with successful promise', async(() => {
|
// #docregion fake-async-test-rxjs
|
||||||
const p = new Promise(resolve => { setTimeout(resolve, 10); });
|
it('should get Date diff correctly in fakeAsync with rxjs scheduler', fakeAsync(() => {
|
||||||
p.then(() => { actuallyDone = true; });
|
// need to add `import 'zone.js/dist/zone-patch-rxjs-fake-async'
|
||||||
}));
|
// to patch rxjs scheduler
|
||||||
|
let result = null;
|
||||||
|
of ('hello').pipe(delay(1000)).subscribe(v => { result = v; });
|
||||||
|
expect(result).toBeNull();
|
||||||
|
tick(1000);
|
||||||
|
expect(result).toBe('hello');
|
||||||
|
|
||||||
it('should run async test with failed promise', async(() => {
|
const start = new Date().getTime();
|
||||||
const p = new Promise((resolve, reject) => { setTimeout(reject, 10); });
|
let dateDiff = 0;
|
||||||
p.catch(() => { actuallyDone = true; });
|
interval(1000).pipe(take(2)).subscribe(() => dateDiff = (new Date().getTime() - start));
|
||||||
}));
|
|
||||||
|
|
||||||
// Use done. Can also use async or fakeAsync.
|
tick(1000);
|
||||||
it('should run async test with successful delayed Observable', (done: DoneFn) => {
|
expect(dateDiff).toBe(1000);
|
||||||
const source = of (true).pipe(delay(10));
|
tick(1000);
|
||||||
source.subscribe(val => actuallyDone = true, err => fail(err), done);
|
expect(dateDiff).toBe(2000);
|
||||||
|
}));
|
||||||
|
// #enddocregion fake-async-test-rxjs
|
||||||
});
|
});
|
||||||
|
|
||||||
// #docregion fake-async-test-tick
|
|
||||||
it('should run timeout callback with delay after call tick with millis', fakeAsync(() => {
|
|
||||||
let called = false;
|
|
||||||
setTimeout(() => { called = true; }, 100);
|
|
||||||
tick(100);
|
|
||||||
expect(called).toBe(true);
|
|
||||||
}));
|
|
||||||
// #enddocregion fake-async-test-tick
|
|
||||||
|
|
||||||
// #docregion fake-async-test-date
|
|
||||||
it('should get Date diff correctly in fakeAsync', fakeAsync(() => {
|
|
||||||
const start = Date.now();
|
|
||||||
tick(100);
|
|
||||||
const end = Date.now();
|
|
||||||
expect(end - start).toBe(100);
|
|
||||||
}));
|
|
||||||
// #enddocregion fake-async-test-date
|
|
||||||
|
|
||||||
// #docregion fake-async-test-rxjs
|
|
||||||
it('should get Date diff correctly in fakeAsync with rxjs scheduler', fakeAsync(() => {
|
|
||||||
// need to add `import 'zone.js/dist/zone-patch-rxjs-fake-async'
|
|
||||||
// to patch rxjs scheduler
|
|
||||||
let result = null;
|
|
||||||
of ('hello').pipe(delay(1000)).subscribe(v => { result = v; });
|
|
||||||
expect(result).toBeNull();
|
|
||||||
tick(1000);
|
|
||||||
expect(result).toBe('hello');
|
|
||||||
|
|
||||||
const start = new Date().getTime();
|
|
||||||
let dateDiff = 0;
|
|
||||||
interval(1000).pipe(take(2)).subscribe(() => dateDiff = (new Date().getTime() - start));
|
|
||||||
|
|
||||||
tick(1000);
|
|
||||||
expect(dateDiff).toBe(1000);
|
|
||||||
tick(1000);
|
|
||||||
expect(dateDiff).toBe(2000);
|
|
||||||
}));
|
|
||||||
// #enddocregion fake-async-test-rxjs
|
|
||||||
|
|
||||||
// #docregion fake-async-test-clock
|
// #docregion fake-async-test-clock
|
||||||
describe('use jasmine.clock()', () => {
|
describe('use jasmine.clock()', () => {
|
||||||
// need to config __zone_symbol__fakeAsyncPatchLock flag
|
// need to config __zone_symbol__fakeAsyncPatchLock flag
|
||||||
@ -124,16 +141,4 @@ describe('Angular async helper', () => {
|
|||||||
});
|
});
|
||||||
// #enddocregion async-test-promise-then
|
// #enddocregion async-test-promise-then
|
||||||
|
|
||||||
it('should run async test with successful delayed Observable', async(() => {
|
|
||||||
const source = of (true).pipe(delay(10));
|
|
||||||
source.subscribe(val => actuallyDone = true, err => fail(err));
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should run async test with successful delayed Observable', fakeAsync(() => {
|
|
||||||
const source = of (true).pipe(delay(10));
|
|
||||||
source.subscribe(val => actuallyDone = true, err => fail(err));
|
|
||||||
|
|
||||||
tick(10);
|
|
||||||
}));
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -1,126 +0,0 @@
|
|||||||
/**
|
|
||||||
* Test the HeroService when implemented with the OLD HttpModule
|
|
||||||
*/
|
|
||||||
import {
|
|
||||||
async, inject, TestBed
|
|
||||||
} from '@angular/core/testing';
|
|
||||||
|
|
||||||
import {
|
|
||||||
MockBackend,
|
|
||||||
MockConnection
|
|
||||||
} from '@angular/http/testing';
|
|
||||||
|
|
||||||
import {
|
|
||||||
HttpModule, Http, XHRBackend, Response, ResponseOptions
|
|
||||||
} from '@angular/http';
|
|
||||||
|
|
||||||
import { of } from 'rxjs';
|
|
||||||
|
|
||||||
import { Hero } from './hero';
|
|
||||||
import { HttpHeroService } from './http-hero.service';
|
|
||||||
|
|
||||||
const makeHeroData = () => [
|
|
||||||
{ id: 1, name: 'Windstorm' },
|
|
||||||
{ id: 2, name: 'Bombasto' },
|
|
||||||
{ id: 3, name: 'Magneta' },
|
|
||||||
{ id: 4, name: 'Tornado' }
|
|
||||||
] as Hero[];
|
|
||||||
|
|
||||||
//////// Tests /////////////
|
|
||||||
describe('HttpHeroService (using old HttpModule)', () => {
|
|
||||||
let backend: MockBackend;
|
|
||||||
let service: HttpHeroService;
|
|
||||||
|
|
||||||
beforeEach( () => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
imports: [ HttpModule ],
|
|
||||||
providers: [
|
|
||||||
HttpHeroService,
|
|
||||||
{ provide: XHRBackend, useClass: MockBackend }
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can instantiate service via DI', () => {
|
|
||||||
service = TestBed.get(HttpHeroService);
|
|
||||||
expect(service instanceof HttpHeroService).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can instantiate service with "new"', () => {
|
|
||||||
const http = TestBed.get(Http);
|
|
||||||
expect(http).not.toBeNull('http should be provided');
|
|
||||||
let service = new HttpHeroService(http);
|
|
||||||
expect(service instanceof HttpHeroService).toBe(true, 'new service should be ok');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can provide the mockBackend as XHRBackend', () => {
|
|
||||||
const backend = TestBed.get(XHRBackend);
|
|
||||||
expect(backend).not.toBeNull('backend should be provided');
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('when getHeroes', () => {
|
|
||||||
let fakeHeroes: Hero[];
|
|
||||||
let http: Http;
|
|
||||||
let response: Response;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
|
|
||||||
backend = TestBed.get(XHRBackend);
|
|
||||||
http = TestBed.get(Http);
|
|
||||||
|
|
||||||
service = new HttpHeroService(http);
|
|
||||||
fakeHeroes = makeHeroData();
|
|
||||||
let options = new ResponseOptions({status: 200, body: {data: fakeHeroes}});
|
|
||||||
response = new Response(options);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have expected fake heroes (then)', () => {
|
|
||||||
backend.connections.subscribe((c: MockConnection) => c.mockRespond(response));
|
|
||||||
|
|
||||||
service.getHeroes().toPromise()
|
|
||||||
// .then(() => Promise.reject('deliberate'))
|
|
||||||
.then(heroes => {
|
|
||||||
expect(heroes.length).toBe(fakeHeroes.length,
|
|
||||||
'should have expected no. of heroes');
|
|
||||||
})
|
|
||||||
.catch(fail);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have expected fake heroes (Observable tap)', () => {
|
|
||||||
backend.connections.subscribe((c: MockConnection) => c.mockRespond(response));
|
|
||||||
|
|
||||||
service.getHeroes().subscribe(
|
|
||||||
heroes => {
|
|
||||||
expect(heroes.length).toBe(fakeHeroes.length,
|
|
||||||
'should have expected no. of heroes');
|
|
||||||
},
|
|
||||||
fail
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('should be OK returning no heroes', () => {
|
|
||||||
let resp = new Response(new ResponseOptions({status: 200, body: {data: []}}));
|
|
||||||
backend.connections.subscribe((c: MockConnection) => c.mockRespond(resp));
|
|
||||||
|
|
||||||
service.getHeroes().subscribe(
|
|
||||||
heroes => {
|
|
||||||
expect(heroes.length).toBe(0, 'should have no heroes');
|
|
||||||
},
|
|
||||||
fail
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should treat 404 as an Observable error', () => {
|
|
||||||
let resp = new Response(new ResponseOptions({status: 404}));
|
|
||||||
backend.connections.subscribe((c: MockConnection) => c.mockRespond(resp));
|
|
||||||
|
|
||||||
service.getHeroes().subscribe(
|
|
||||||
heroes => fail('should not respond with heroes'),
|
|
||||||
err => {
|
|
||||||
expect(err).toMatch(/Bad response status/, 'should catch bad response status code');
|
|
||||||
return of(null); // failure is the expected test result
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,69 +0,0 @@
|
|||||||
// The OLD Http module. See HeroService for use of the current HttpClient
|
|
||||||
// #docplaster
|
|
||||||
// #docregion
|
|
||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { Http, Response } from '@angular/http';
|
|
||||||
import { Headers, RequestOptions } from '@angular/http';
|
|
||||||
import { Hero } from './hero';
|
|
||||||
|
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
import { throwError } from 'rxjs';
|
|
||||||
import { catchError, map } from 'rxjs/operators';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class HttpHeroService {
|
|
||||||
private _heroesUrl = 'app/heroes'; // URL to web api
|
|
||||||
|
|
||||||
constructor (private http: Http) {}
|
|
||||||
|
|
||||||
getHeroes (): Observable<Hero[]> {
|
|
||||||
return this.http.get(this._heroesUrl).pipe(
|
|
||||||
map(this.extractData),
|
|
||||||
// tap(data => console.log(data)), // eyeball results in the console
|
|
||||||
catchError(this.handleError)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getHero(id: number | string) {
|
|
||||||
return this.http.get('app/heroes/?id=${id}').pipe(
|
|
||||||
map((r: Response) => r.json().data as Hero[])
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
addHero (name: string): Observable<Hero> {
|
|
||||||
let body = JSON.stringify({ name });
|
|
||||||
let headers = new Headers({ 'Content-Type': 'application/json' });
|
|
||||||
let options = new RequestOptions({ headers: headers });
|
|
||||||
|
|
||||||
return this.http.post(this._heroesUrl, body, options).pipe(
|
|
||||||
map(this.extractData),
|
|
||||||
catchError(this.handleError)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateHero (hero: Hero): Observable<Hero> {
|
|
||||||
let body = JSON.stringify(hero);
|
|
||||||
let headers = new Headers({ 'Content-Type': 'application/json' });
|
|
||||||
let options = new RequestOptions({ headers: headers });
|
|
||||||
|
|
||||||
return this.http.put(this._heroesUrl, body, options).pipe(
|
|
||||||
map(this.extractData),
|
|
||||||
catchError(this.handleError)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private extractData(res: Response) {
|
|
||||||
if (res.status < 200 || res.status >= 300) {
|
|
||||||
throw new Error('Bad response status: ' + res.status);
|
|
||||||
}
|
|
||||||
let body = res.json();
|
|
||||||
return body.data || { };
|
|
||||||
}
|
|
||||||
|
|
||||||
private handleError (error: any) {
|
|
||||||
// In a real world app, we might send the error to remote logging infrastructure
|
|
||||||
let errMsg = error.message || 'Server error';
|
|
||||||
console.error(errMsg); // log to console instead
|
|
||||||
return throwError(errMsg);
|
|
||||||
}
|
|
||||||
}
|
|
@ -41,7 +41,6 @@
|
|||||||
'app/hero/hero-detail.component.spec',
|
'app/hero/hero-detail.component.spec',
|
||||||
'app/hero/hero-list.component.spec',
|
'app/hero/hero-list.component.spec',
|
||||||
'app/model/hero.service.spec',
|
'app/model/hero.service.spec',
|
||||||
'app/model/http-hero.service.spec',
|
|
||||||
'app/shared/highlight.directive.spec',
|
'app/shared/highlight.directive.spec',
|
||||||
'app/shared/title-case.pipe.spec',
|
'app/shared/title-case.pipe.spec',
|
||||||
'app/twain/twain.component.spec',
|
'app/twain/twain.component.spec',
|
||||||
|
@ -17,7 +17,6 @@ import './app/hero/hero-detail.component.no-testbed.spec.ts';
|
|||||||
import './app/hero/hero-detail.component.spec.ts';
|
import './app/hero/hero-detail.component.spec.ts';
|
||||||
import './app/hero/hero-list.component.spec.ts';
|
import './app/hero/hero-list.component.spec.ts';
|
||||||
import './app/model/hero.service.spec.ts';
|
import './app/model/hero.service.spec.ts';
|
||||||
import './app/model/http-hero.service.spec.ts';
|
|
||||||
import './app/model/testing/http-client.spec.ts';
|
import './app/model/testing/http-client.spec.ts';
|
||||||
import './app/shared/highlight.directive.spec.ts';
|
import './app/shared/highlight.directive.spec.ts';
|
||||||
import './app/shared/title-case.pipe.spec.ts';
|
import './app/shared/title-case.pipe.spec.ts';
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
<!-- #docregion name-input -->
|
<!-- #docregion name-input -->
|
||||||
<div>
|
<div>
|
||||||
<label>name:
|
<label>name:
|
||||||
<input [(ngModel)]="hero.name" placeholder="name">
|
<input [(ngModel)]="hero.name" placeholder="name"/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<!-- #enddocregion name-input -->
|
<!-- #enddocregion name-input -->
|
||||||
|
@ -5,6 +5,6 @@
|
|||||||
<div><span>id: </span>{{hero.id}}</div>
|
<div><span>id: </span>{{hero.id}}</div>
|
||||||
<div>
|
<div>
|
||||||
<label>name:
|
<label>name:
|
||||||
<input [(ngModel)]="hero.name" placeholder="name">
|
<input [(ngModel)]="hero.name" placeholder="name"/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
<div><span>id: </span>{{selectedHero.id}}</div>
|
<div><span>id: </span>{{selectedHero.id}}</div>
|
||||||
<div>
|
<div>
|
||||||
<label>name:
|
<label>name:
|
||||||
<input [(ngModel)]="selectedHero.name" placeholder="name">
|
<input [(ngModel)]="selectedHero.name" placeholder="name"/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<!-- #enddocregion selectedHero-details -->
|
<!-- #enddocregion selectedHero-details -->
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
// angular bundles
|
// angular bundles
|
||||||
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
|
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
|
||||||
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
|
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
|
||||||
|
'@angular/common/http': 'npm:@angular/common/bundles/common-http.umd.js',
|
||||||
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
|
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
|
||||||
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
|
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
|
||||||
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
|
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
|
||||||
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
|
|
||||||
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
|
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
|
||||||
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
|
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
|
||||||
// #docregion upgrade-static-umd
|
// #docregion upgrade-static-umd
|
||||||
|
@ -6,9 +6,9 @@ import { BrowserModule } from '@angular/platform-browser';
|
|||||||
// #docregion upgrademodule
|
// #docregion upgrademodule
|
||||||
import { UpgradeModule } from '@angular/upgrade/static';
|
import { UpgradeModule } from '@angular/upgrade/static';
|
||||||
// #enddocregion upgrademodule
|
// #enddocregion upgrademodule
|
||||||
// #docregion httpmodule
|
// #docregion httpclientmodule
|
||||||
import { HttpModule } from '@angular/http';
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
// #enddocregion httpmodule
|
// #enddocregion httpclientmodule
|
||||||
// #docregion phonelist
|
// #docregion phonelist
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
// #enddocregion phonelist
|
// #enddocregion phonelist
|
||||||
@ -28,7 +28,7 @@ import { routeParamsProvider } from './ajs-upgraded-providers';
|
|||||||
import { PhoneDetailComponent } from './phone-detail/phone-detail.component';
|
import { PhoneDetailComponent } from './phone-detail/phone-detail.component';
|
||||||
// #enddocregion phonedetail
|
// #enddocregion phonedetail
|
||||||
|
|
||||||
// #docregion bare, upgrademodule, httpmodule, phone, phonelist, phonedetail, checkmarkpipe
|
// #docregion bare, upgrademodule, httpclientmodule, phone, phonelist, phonedetail, checkmarkpipe
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@ -36,12 +36,12 @@ import { PhoneDetailComponent } from './phone-detail/phone-detail.component';
|
|||||||
// #enddocregion bare
|
// #enddocregion bare
|
||||||
UpgradeModule,
|
UpgradeModule,
|
||||||
// #enddocregion upgrademodule
|
// #enddocregion upgrademodule
|
||||||
HttpModule,
|
HttpClientModule,
|
||||||
// #enddocregion httpmodule, phone
|
// #enddocregion httpclientmodule, phone
|
||||||
FormsModule,
|
FormsModule,
|
||||||
// #docregion bare, upgrademodule, httpmodule, phone
|
// #docregion bare, upgrademodule, httpclientmodule, phone
|
||||||
],
|
],
|
||||||
// #enddocregion bare, upgrademodule, httpmodule, phone
|
// #enddocregion bare, upgrademodule, httpclientmodule, phone
|
||||||
declarations: [
|
declarations: [
|
||||||
PhoneListComponent,
|
PhoneListComponent,
|
||||||
// #enddocregion phonelist
|
// #enddocregion phonelist
|
||||||
@ -63,7 +63,7 @@ import { PhoneDetailComponent } from './phone-detail/phone-detail.component';
|
|||||||
// #docregion phone
|
// #docregion phone
|
||||||
]
|
]
|
||||||
// #enddocregion routeparams
|
// #enddocregion routeparams
|
||||||
// #docregion bare, upgrademodule, httpmodule, phonelist
|
// #docregion bare, upgrademodule, httpclientmodule, phonelist
|
||||||
})
|
})
|
||||||
export class AppModule {
|
export class AppModule {
|
||||||
// #enddocregion bare
|
// #enddocregion bare
|
||||||
@ -73,4 +73,4 @@ export class AppModule {
|
|||||||
}
|
}
|
||||||
// #docregion bare
|
// #docregion bare
|
||||||
}
|
}
|
||||||
// #enddocregion bare, upgrademodule, httpmodule, phone, phonelist, phonedetail, checkmarkpipe
|
// #enddocregion bare, upgrademodule, httpclientmodule, phone, phonelist, phonedetail, checkmarkpipe
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { inject, TestBed } from '@angular/core/testing';
|
import { inject, TestBed } from '@angular/core/testing';
|
||||||
import {
|
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
|
||||||
Http,
|
|
||||||
BaseRequestOptions,
|
|
||||||
ResponseOptions,
|
|
||||||
Response
|
|
||||||
} from '@angular/http';
|
|
||||||
import { MockBackend, MockConnection } from '@angular/http/testing';
|
|
||||||
import { Phone, PhoneData } from './phone.service';
|
import { Phone, PhoneData } from './phone.service';
|
||||||
|
|
||||||
describe('Phone', function() {
|
describe('Phone', function() {
|
||||||
@ -16,35 +10,34 @@ describe('Phone', function() {
|
|||||||
{name: 'Phone Y', snippet: '', images: []},
|
{name: 'Phone Y', snippet: '', images: []},
|
||||||
{name: 'Phone Z', snippet: '', images: []}
|
{name: 'Phone Z', snippet: '', images: []}
|
||||||
];
|
];
|
||||||
let mockBackend: MockBackend;
|
let httpMock: HttpTestingController;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
|
imports: [
|
||||||
|
HttpClientTestingModule
|
||||||
|
],
|
||||||
providers: [
|
providers: [
|
||||||
Phone,
|
Phone,
|
||||||
MockBackend,
|
|
||||||
BaseRequestOptions,
|
|
||||||
{ provide: Http,
|
|
||||||
useFactory: (backend: MockBackend, options: BaseRequestOptions) => new Http(backend, options),
|
|
||||||
deps: [MockBackend, BaseRequestOptions]
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(inject([MockBackend, Phone], (_mockBackend_: MockBackend, _phone_: Phone) => {
|
beforeEach(inject([HttpTestingController, Phone], (_httpMock_: HttpTestingController, _phone_: Phone) => {
|
||||||
mockBackend = _mockBackend_;
|
httpMock = _httpMock_;
|
||||||
phone = _phone_;
|
phone = _phone_;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should fetch the phones data from `/phones/phones.json`', (done: () => void) => {
|
afterEach(() => {
|
||||||
mockBackend.connections.subscribe((conn: MockConnection) => {
|
httpMock.verify();
|
||||||
conn.mockRespond(new Response(new ResponseOptions({body: JSON.stringify(phonesData)})));
|
});
|
||||||
});
|
|
||||||
|
it('should fetch the phones data from `/phones/phones.json`', () => {
|
||||||
phone.query().subscribe(result => {
|
phone.query().subscribe(result => {
|
||||||
expect(result).toEqual(phonesData);
|
expect(result).toEqual(phonesData);
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
|
const req = httpMock.expectOne(`/phones/phones.json`);
|
||||||
|
req.flush(phonesData);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Http, Response } from '@angular/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
|
||||||
|
|
||||||
// #docregion downgrade-injectable
|
// #docregion downgrade-injectable
|
||||||
declare var angular: angular.IAngularStatic;
|
declare var angular: angular.IAngularStatic;
|
||||||
@ -22,16 +21,12 @@ export interface PhoneData {
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class Phone {
|
export class Phone {
|
||||||
// #enddocregion classdef, downgrade-injectable
|
// #enddocregion classdef, downgrade-injectable
|
||||||
constructor(private http: Http) { }
|
constructor(private http: HttpClient) { }
|
||||||
query(): Observable<PhoneData[]> {
|
query(): Observable<PhoneData[]> {
|
||||||
return this.http.get(`phones/phones.json`).pipe(
|
return this.http.get<PhoneData[]>(`phones/phones.json`);
|
||||||
map((res: Response) => res.json())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
get(id: string): Observable<PhoneData> {
|
get(id: string): Observable<PhoneData> {
|
||||||
return this.http.get(`phones/${id}.json`).pipe(
|
return this.http.get<PhoneData>(`phones/${id}.json`);
|
||||||
map((res: Response) => res.json())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
// #docregion classdef, downgrade-injectable
|
// #docregion classdef, downgrade-injectable
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,6 @@ System.config({
|
|||||||
'@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
|
'@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
|
||||||
'@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
|
'@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
|
||||||
'@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
|
'@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
|
||||||
'@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
|
|
||||||
'@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
|
'@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
|
||||||
'@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js',
|
'@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js',
|
||||||
},
|
},
|
||||||
|
@ -48,7 +48,6 @@ System.config({
|
|||||||
'@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
|
'@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
|
||||||
'@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
|
'@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
|
||||||
'@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
|
'@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
|
||||||
'@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
|
|
||||||
'@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
|
'@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
|
||||||
'@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js',
|
'@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js',
|
||||||
},
|
},
|
||||||
|
@ -6,11 +6,13 @@ import uglify from 'rollup-plugin-uglify'
|
|||||||
|
|
||||||
//paths are relative to the execution path
|
//paths are relative to the execution path
|
||||||
export default {
|
export default {
|
||||||
entry: 'app/main-aot.js',
|
input: 'app/main-aot.js',
|
||||||
dest: 'aot/dist/build.js', // output a single application bundle
|
output: {
|
||||||
sourceMap: true,
|
file: 'aot/dist/build.js', // output a single application bundle
|
||||||
sourceMapFile: 'aot/dist/build.js.map',
|
format: 'iife',
|
||||||
format: 'iife',
|
sourcemap: true,
|
||||||
|
sourcemapFile: 'aot/dist/build.js.map'
|
||||||
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
nodeResolve({jsnext: true, module: true}),
|
nodeResolve({jsnext: true, module: true}),
|
||||||
commonjs({
|
commonjs({
|
||||||
|
@ -16,10 +16,10 @@
|
|||||||
// angular bundles
|
// angular bundles
|
||||||
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
|
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
|
||||||
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
|
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
|
||||||
|
'@angular/common/http': 'npm:@angular/common/bundles/common-http.umd.js',
|
||||||
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
|
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
|
||||||
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
|
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
|
||||||
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
|
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
|
||||||
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
|
|
||||||
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
|
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
|
||||||
'@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js',
|
'@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js',
|
||||||
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
|
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { HttpModule } from '@angular/http';
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
@ -15,7 +15,7 @@ import { PhoneListComponent } from './phone-list/phone-list.component';
|
|||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
HttpModule,
|
HttpClientModule,
|
||||||
AppRoutingModule
|
AppRoutingModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -1,11 +1,5 @@
|
|||||||
import { inject, TestBed } from '@angular/core/testing';
|
import { inject, TestBed } from '@angular/core/testing';
|
||||||
import {
|
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
|
||||||
Http,
|
|
||||||
BaseRequestOptions,
|
|
||||||
ResponseOptions,
|
|
||||||
Response
|
|
||||||
} from '@angular/http';
|
|
||||||
import { MockBackend, MockConnection } from '@angular/http/testing';
|
|
||||||
import { Phone, PhoneData } from './phone.service';
|
import { Phone, PhoneData } from './phone.service';
|
||||||
|
|
||||||
describe('Phone', function() {
|
describe('Phone', function() {
|
||||||
@ -15,35 +9,26 @@ describe('Phone', function() {
|
|||||||
{name: 'Phone Y', snippet: '', images: []},
|
{name: 'Phone Y', snippet: '', images: []},
|
||||||
{name: 'Phone Z', snippet: '', images: []}
|
{name: 'Phone Z', snippet: '', images: []}
|
||||||
];
|
];
|
||||||
let mockBackend: MockBackend;
|
let mockHttp: HttpTestingController;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
providers: [
|
imports: [HttpClientTestingModule],
|
||||||
Phone,
|
providers: [Phone]
|
||||||
MockBackend,
|
|
||||||
BaseRequestOptions,
|
|
||||||
{ provide: Http,
|
|
||||||
useFactory: (backend: MockBackend, options: BaseRequestOptions) => new Http(backend, options),
|
|
||||||
deps: [MockBackend, BaseRequestOptions]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(inject([MockBackend, Phone], (_mockBackend_: MockBackend, _phone_: Phone) => {
|
beforeEach(inject([HttpTestingController, Phone], (_mockHttp_: HttpTestingController, _phone_: Phone) => {
|
||||||
mockBackend = _mockBackend_;
|
mockHttp = _mockHttp_;
|
||||||
phone = _phone_;
|
phone = _phone_;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should fetch the phones data from `/phones/phones.json`', (done: () => void) => {
|
it('should fetch the phones data from `/phones/phones.json`', () => {
|
||||||
mockBackend.connections.subscribe((conn: MockConnection) => {
|
|
||||||
conn.mockRespond(new Response(new ResponseOptions({body: JSON.stringify(phonesData)})));
|
|
||||||
});
|
|
||||||
phone.query().subscribe(result => {
|
phone.query().subscribe(result => {
|
||||||
expect(result).toEqual(phonesData);
|
expect(result).toEqual(phonesData);
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
|
const req = mockHttp.expectOne(`/phones/phones.json`);
|
||||||
|
req.flush(phonesData);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Http, Response } from '@angular/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
|
||||||
|
|
||||||
export interface PhoneData {
|
export interface PhoneData {
|
||||||
name: string;
|
name: string;
|
||||||
@ -12,15 +11,11 @@ export interface PhoneData {
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class Phone {
|
export class Phone {
|
||||||
constructor(private http: Http) { }
|
constructor(private http: HttpClient) { }
|
||||||
query(): Observable<PhoneData[]> {
|
query(): Observable<PhoneData[]> {
|
||||||
return this.http.get(`phones/phones.json`).pipe(
|
return this.http.get<PhoneData[]>(`phones/phones.json`);
|
||||||
map((res: Response) => res.json())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
get(id: string): Observable<PhoneData> {
|
get(id: string): Observable<PhoneData> {
|
||||||
return this.http.get(`phones/${id}.json`).pipe(
|
return this.http.get<PhoneData>(`phones/${id}.json`);
|
||||||
map((res: Response) => res.json())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,10 +44,10 @@ System.config({
|
|||||||
map: {
|
map: {
|
||||||
'@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
|
'@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
|
||||||
'@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
|
'@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
|
||||||
|
'@angular/common/http/testing': 'npm:@angular/common/bundles/common-http-testing.umd.js',
|
||||||
'@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
|
'@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
|
||||||
'@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
|
'@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
|
||||||
'@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
|
'@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
|
||||||
'@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
|
|
||||||
'@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
|
'@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
|
||||||
'@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js',
|
'@angular/forms/testing': 'npm:@angular/forms/bundles/forms-testing.umd.js',
|
||||||
},
|
},
|
||||||
|
@ -16,10 +16,10 @@
|
|||||||
// angular bundles
|
// angular bundles
|
||||||
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
|
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
|
||||||
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
|
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
|
||||||
|
'@angular/common/http': 'npm:@angular/common/bundles/common-http.umd.js',
|
||||||
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
|
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
|
||||||
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
|
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
|
||||||
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
|
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
|
||||||
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
|
|
||||||
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
|
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
|
||||||
'@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js',
|
'@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js',
|
||||||
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
|
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
|
||||||
|
59
aio/content/guide/app-shell.md
Normal file
59
aio/content/guide/app-shell.md
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# App shell
|
||||||
|
|
||||||
|
App shell is a way to render a portion of your application via a route at build time.
|
||||||
|
It can improve the user experience by quickly launching a static rendered page (a skeleton common to all pages) while the browser downloads the full client version and switches to it automatically after the code loads.
|
||||||
|
|
||||||
|
This gives users a meaningful first paint of your application that appears quickly because the browser can simply render the HTML and CSS without the need to initialize any JavaScript.
|
||||||
|
|
||||||
|
Learn more in [The App Shell Model](https://developers.google.com/web/fundamentals/architecture/app-shell).
|
||||||
|
|
||||||
|
## Step 1: Prepare the application
|
||||||
|
|
||||||
|
You can do this with the following CLI command:
|
||||||
|
<code-example format="." language="bash" linenums="false">
|
||||||
|
ng new my-app --routing
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
For an existing application, you have to manually add the `RouterModule` and defining a `<router-outlet>` within your application.
|
||||||
|
|
||||||
|
## Step 2: Create the app shell
|
||||||
|
|
||||||
|
Use the CLI to automatically create the app shell.
|
||||||
|
|
||||||
|
<code-example format="." language="bash" linenums="false">
|
||||||
|
ng generate app-shell --client-project my-app --universal-project server-app
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
* `my-app` takes the name of your client application.
|
||||||
|
* `server-app` takes the name of the Universal (or server) application.
|
||||||
|
|
||||||
|
After running this command you will notice that the `angular.json` configuration file has been updated to add two new targets, with a few other changes.
|
||||||
|
|
||||||
|
<code-example format="." language="none" linenums="false">
|
||||||
|
"server": {
|
||||||
|
"builder": "@angular-devkit/build-angular:server",
|
||||||
|
"options": {
|
||||||
|
"outputPath": "dist/my-app-server",
|
||||||
|
"main": "src/main.server.ts",
|
||||||
|
"tsConfig": "tsconfig.server.json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"app-shell": {
|
||||||
|
"builder": "@angular-devkit/build-angular:app-shell",
|
||||||
|
"options": {
|
||||||
|
"browserTarget": "my-app:build",
|
||||||
|
"serverTarget": "my-app:server",
|
||||||
|
"route": "shell"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
## Step 3: Verify the app is built with the shell content
|
||||||
|
|
||||||
|
Use the CLI to build the `app-shell` target.
|
||||||
|
|
||||||
|
<code-example format="." language="bash" linenums="false">
|
||||||
|
ng run my-app:app-shell
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
To verify the build output, open `dist/my-app/index.html`. Look for default text `app-shell works!` to show that the app shell route was rendered as part of the output.
|
@ -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>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
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.
|
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.
|
A 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
|
## Getting started
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ This builder, among other things, ensures that the library is always built with
|
|||||||
|
|
||||||
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.
|
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.
|
The public API for your library is maintained in the `public-api.ts` file in your library folder.
|
||||||
Anything exported from this file is made public when your library is imported into an application.
|
Anything exported from this file is made public when your library is imported into an application.
|
||||||
Use an NgModule to expose services and components.
|
Use an NgModule to expose services and components.
|
||||||
|
|
||||||
|
@ -182,8 +182,7 @@ Child modules and component injectors are independent of each other, and create
|
|||||||
|
|
||||||
Thanks to [injector inheritance](guide/hierarchical-dependency-injection),
|
Thanks to [injector inheritance](guide/hierarchical-dependency-injection),
|
||||||
you can still inject application-wide services into these components.
|
you can still inject application-wide services into these components.
|
||||||
A component's injector is a child of its parent component's injector,
|
A component's injector is a child of its parent component's injector, and inherits from all ancestor injectors all the way back to the application's _root_ injector. Angular can inject a service provided by any injector in that lineage.
|
||||||
and a descendent of its parent's parent's injector, and so on all the way back to the application's _root_ injector. Angular can inject a service provided by any injector in that lineage.
|
|
||||||
|
|
||||||
For example, Angular can inject `HeroListComponent` with both the `HeroService` provided in `HeroComponent` and the `UserService` provided in `AppModule`.
|
For example, Angular can inject `HeroListComponent` with both the `HeroService` provided in `HeroComponent` and the `UserService` provided in `AppModule`.
|
||||||
|
|
||||||
|
@ -1,43 +1,54 @@
|
|||||||
# Workspace and project file structure
|
# Workspace and project file structure
|
||||||
|
|
||||||
You develop apps in the context of an Angular [workspace](guide/glossary#workspace). A workspace contains the files for one or more [projects](guide/glossary#project). A project is the set of files that comprise a standalone app, a library, or a set of end-to-end (e2e) tests.
|
You develop applications in the context of an Angular [workspace](guide/glossary#workspace). A workspace contains the files for one or more [projects](guide/glossary#project). A project is the set of files that comprise a standalone application or a shareable library.
|
||||||
|
|
||||||
The Angular CLI command `ng new <project_name>` gets you started.
|
The Angular CLI `ng new` command creates a workspace.
|
||||||
When you run this command, the CLI installs the necessary Angular npm packages and other dependencies in a new workspace, with a root folder named *project_name*.
|
|
||||||
It also creates the following workspace and starter project files:
|
|
||||||
|
|
||||||
* An initial skeleton app project, also called *project_name* (in the `src/` subfolder).
|
<code-example language="bash" linenums="false">
|
||||||
* An end-to-end test project (in the `e2e/` subfolder).
|
ng new <project_name>
|
||||||
* Related configuration files.
|
</code-example>
|
||||||
|
|
||||||
The initial app project contains a simple Welcome app, ready to run.
|
When you run this command, the CLI installs the necessary Angular npm packages and other dependencies in a new workspace, with a root folder named *project_name*.
|
||||||
|
The workspace root folder contains workspace configuration files and a README file with generated descriptive text that you can customize.
|
||||||
|
|
||||||
## Workspace files
|
By default, `ng new` also creates an initial skeleton application, along with its end-to-end tests.
|
||||||
|
The skeleton is for a simple Welcome application that is ready to run and easy to modify.
|
||||||
|
This *root application* has the same name as the workspace, and the source files reside in the `src/` subfolder of the workspace.
|
||||||
|
|
||||||
The top level of the workspace contains a number of workspace-wide configuration files.
|
This default behavior is suitable for a typical "multi-repo" development style where each application resides in its own workspace.
|
||||||
|
Beginners and intermediate users are encouraged to use `ng new` to create a separate workspace for each application.
|
||||||
|
|
||||||
|
Angular also supports workspaces with [multiple projects](#multiple-projects).
|
||||||
|
This type of development environment is suitable for advanced users who are developing [shareable libraries](guide/glossary#library),
|
||||||
|
and for enterprises that use a "mono-repo" development style, with a single repository and global configuration for all Angular projects.
|
||||||
|
|
||||||
|
To set up a mono-repo workspace, you should skip the creating the root application.
|
||||||
|
See [Setting up for a multi-project workspace](#multiple-projects) below.
|
||||||
|
|
||||||
|
## Workspace configuration files
|
||||||
|
|
||||||
|
All projects within a workspace share a [CLI configuration context](guide/workspace-config).
|
||||||
|
The top level of the workspace contains workspace-wide configuration files.
|
||||||
|
|
||||||
| WORKSPACE CONFIG FILES | PURPOSE |
|
| WORKSPACE CONFIG FILES | PURPOSE |
|
||||||
| :--------------------- | :------------------------------------------|
|
| :--------------------- | :------------------------------------------|
|
||||||
|
| `node_modules/` | Provides [npm packages](guide/npm-packages) to the entire workspace. Workspace-wide `node_modules` dependencies are visible to all projects. |
|
||||||
| `.editorconfig` | Configuration for code editors. See [EditorConfig](https://editorconfig.org/). |
|
| `.editorconfig` | Configuration for code editors. See [EditorConfig](https://editorconfig.org/). |
|
||||||
| `.gitignore` | Specifies intentionally untracked files that [Git](https://git-scm.com/) should ignore. |
|
| `.gitignore` | Specifies intentionally untracked files that [Git](https://git-scm.com/) should ignore. |
|
||||||
| `angular.json` | CLI configuration defaults for all projects in the workspace, including configuration options for build, serve, and test tools that the CLI uses, such as [TSLint](https://palantir.github.io/tslint/), [Karma](https://karma-runner.github.io/), and [Protractor](http://www.protractortest.org/). For details, see [Angular Workspace Configuration](guide/workspace-config). |
|
| `angular.json` | CLI configuration defaults for all projects in the workspace, including configuration options for build, serve, and test tools that the CLI uses, such as [TSLint](https://palantir.github.io/tslint/), [Karma](https://karma-runner.github.io/), and [Protractor](http://www.protractortest.org/). For details, see [Angular Workspace Configuration](guide/workspace-config). |
|
||||||
| `node_modules` | Provides [npm packages](guide/npm-packages) to the entire workspace. |
|
| `package.json` | Configures [npm package dependencies](guide/npm-packages) that are available to all projects in the workspace. See [npm documentation](https://docs.npmjs.com/files/package.json) for the specific format and contents of this file. |
|
||||||
| `package.json` | Configures [npm package dependencies](guide/npm-packages) that are available to all projects in the workspace. See [npm documentation](https://docs.npmjs.com/files/package.json) for the specific format and contents of this file. |
|
| `package-lock.json` | Provides version information for all packages installed into `node_modules` by the npm client. See [npm documentation](https://docs.npmjs.com/files/package-lock.json) for details. If you use the yarn client, this file will be [yarn.lock](https://yarnpkg.com/lang/en/docs/yarn-lock/) instead. |
|
||||||
| `package-lock.json` | Provides version information for all packages installed into `node_modules` by the npm client. See [npm documentation](https://docs.npmjs.com/files/package-lock.json) for details. If you use the yarn client, this file will be [yarn.lock](https://yarnpkg.com/lang/en/docs/yarn-lock/) instead. |
|
| `README.md` | Introductory documentation for the root app. |
|
||||||
| `tsconfig.json` | Default [TypeScript](https://www.typescriptlang.org/) configuration for apps in the workspace, including TypeScript and Angular template compiler options. See [TypeScript Configuration](guide/typescript-configuration). |
|
| `tsconfig.json` | Default [TypeScript](https://www.typescriptlang.org/) configuration for projects in the workspace. |
|
||||||
| `tslint.json` | Default [TSLint](https://palantir.github.io/tslint/) configuration for apps in the workspace. |
|
| `tslint.json` | Default [TSLint](https://palantir.github.io/tslint/) configuration for projects in the workspace. |
|
||||||
| `README.md` | Introductory documentation. |
|
|
||||||
|
|
||||||
All projects within a workspace share a [CLI configuration context](guide/workspace-config).
|
## Application project files
|
||||||
Project-specific [TypeScript](https://www.typescriptlang.org/) configuration files inherit from the workspace-wide `tsconfig.*.json`, and app-specific [TSLint](https://palantir.github.io/tslint/) configuration files inherit from the workspace-wide `tslint.json`.
|
|
||||||
|
|
||||||
### Default app project files
|
By default, the CLI command `ng new my-app` creates a workspace folder named "my-app" and generates a new application skeleton for a root application at the top level of the workspace.
|
||||||
|
A newly generated application contains source files for a root module, with a root component and template.
|
||||||
|
|
||||||
The CLI command `ng new my-app` creates a workspace folder named "my-app" and generates a new app skeleton.
|
When the workspace file structure is in place, you can use the `ng generate` command on the command line to add functionality and data to the application.
|
||||||
This initial app is the *default app* for CLI commands (unless you change the default after creating additional apps).
|
This initial starter application is the *default app* for CLI commands (unless you change the default after creating [additional apps](#multiple-projects)).
|
||||||
|
|
||||||
A newly generated app contains the source files for a root module, with a root component and template.
|
|
||||||
When the workspace file structure is in place, you can use the `ng generate` command on the command line to add functionality and data to the initial app.
|
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
<div class="alert is-helpful">
|
||||||
|
|
||||||
@ -45,69 +56,109 @@ When the workspace file structure is in place, you can use the `ng generate` com
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
The `src/` subfolder contains the source files (app logic, data, and assets), along with configuration files for the initial app.
|
For a single-application workspace, the `src/` subfolder of the workspace contains the source files (application logic, data, and assets) for the root application.
|
||||||
Workspace-wide `node_modules` dependencies are visible to this project.
|
For a multi-project workspace, additional projects in the `projects/` folder contain a `project-name/src/` subfolder with the same structure.
|
||||||
|
|
||||||
| APP SOURCE & CONFIG FILES | PURPOSE |
|
### Application source files
|
||||||
|
|
||||||
|
Files at the top level of `src/` support testing and running your application. Subfolders contain the application source and application-specific configuration.
|
||||||
|
|
||||||
|
| APP SUPPORT FILES | PURPOSE |
|
||||||
| :--------------------- | :------------------------------------------|
|
| :--------------------- | :------------------------------------------|
|
||||||
| `app/` | Contains the component files in which your app logic and data are defined. See details in [App source folder](#app-src) below. |
|
| `app/` | Contains the component files in which your application logic and data are defined. See details [below](#app-src). |
|
||||||
| `assets/` | Contains image files and other asset files to be copied as-is when you build your application. |
|
| `assets/` | Contains image and other asset files to be copied as-is when you build your application. |
|
||||||
| `environments/` | Contains build configuration options for particular target environments. By default there is an unnamed standard development environment and a production ("prod") environment. You can define additional target environment configurations. |
|
| `environments/` | Contains build configuration options for particular target environments. By default there is an unnamed standard development environment and a production ("prod") environment. You can define additional target environment configurations. |
|
||||||
| `browserslist` | Configures sharing of target browsers and Node.js versions among various front-end tools. See [Browserslist on GitHub](https://github.com/browserslist/browserslist) for more information. |
|
| `favicon.ico` | An icon to use for this application in the bookmark bar. |
|
||||||
| `favicon.ico` | An icon to use for this app in the bookmark bar. |
|
|
||||||
| `index.html` | The main HTML page that is served when someone visits your site. The CLI automatically adds all JavaScript and CSS files when building your app, so you typically don't need to add any `<script>` or` <link>` tags here manually. |
|
| `index.html` | The main HTML page that is served when someone visits your site. The CLI automatically adds all JavaScript and CSS files when building your app, so you typically don't need to add any `<script>` or` <link>` tags here manually. |
|
||||||
| `main.ts` | The main entry point for your app. Compiles the application with the [JIT compiler](https://angular.io/guide/glossary#jit) and bootstraps the application's root module (AppModule) to run in the browser. You can also use the [AOT compiler](https://angular.io/guide/aot-compiler) without changing any code by appending the `--aot` flag to the CLI `build` and `serve` commands. |
|
| `main.ts` | The main entry point for your application. Compiles the application with the [JIT compiler](https://angular.io/guide/glossary#jit) and bootstraps the application's root module (AppModule) to run in the browser. You can also use the [AOT compiler](https://angular.io/guide/aot-compiler) without changing any code by appending the `--aot` flag to the CLI `build` and `serve` commands. |
|
||||||
| `polyfills.ts` | Provides polyfill scripts for browser support. |
|
| `polyfills.ts` | Provides polyfill scripts for browser support. |
|
||||||
| `styles.sass` | Lists CSS files that supply styles for a project. The extension reflects the style preprocessor you have configured for the project. |
|
| `styles.sass` | Lists CSS files that supply styles for a project. The extension reflects the style preprocessor you have configured for the project. |
|
||||||
| `test.ts` | The main entry point for your unit tests, with some Angular-specific configuration. You don't typically need to edit this file. |
|
| `test.ts` | The main entry point for your unit tests, with some Angular-specific configuration. You don't typically need to edit this file. |
|
||||||
| `tsconfig.app.json` | Inherits from the workspace-wide `tsconfig.json` file. |
|
|
||||||
| `tsconfig.spec.json` | Inherits from the workspace-wide `tsconfig.json` file. |
|
|
||||||
| `tslint.json` | Inherits from the workspace-wide `tslint.json` file. |
|
|
||||||
|
|
||||||
### Default app project e2e files
|
|
||||||
|
|
||||||
An `e2e/` subfolder contains configuration and source files for a set of end-to-end tests that correspond to the initial app.
|
|
||||||
Workspace-wide `node_modules` dependencies are visible to this project.
|
|
||||||
|
|
||||||
<code-example language="none" linenums="false">
|
|
||||||
my-app/
|
|
||||||
e2e/ (end-to-end test app for my-app)
|
|
||||||
src/ (app source files)
|
|
||||||
protractor.conf.js (test-tool config)
|
|
||||||
tsconfig.e2e.json (TypeScript config inherits from workspace tsconfig.json)
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
### Project folders for additional apps and libraries
|
|
||||||
|
|
||||||
When you generate new projects in a workspace,
|
|
||||||
the CLI creates a new *workspace*`/projects` folder, and adds the generated files there.
|
|
||||||
|
|
||||||
When you generate an app (`ng generate application my-other-app`), the CLI adds folders under `projects/` for both the app and its corresponding end-to-end tests. Newly generated libraries are also added under `projects/`.
|
|
||||||
|
|
||||||
<code-example language="none" linenums="false">
|
|
||||||
my-app/
|
|
||||||
...
|
|
||||||
projects/ (additional apps and libs)
|
|
||||||
my-other-app/ (a second app)
|
|
||||||
src/
|
|
||||||
(config files)
|
|
||||||
my-other-app-e2e/ (corresponding test app)
|
|
||||||
src/
|
|
||||||
(config files)
|
|
||||||
my-lib/ (a generated library)
|
|
||||||
(config files)
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
{@a app-src}
|
{@a app-src}
|
||||||
## App source folder
|
|
||||||
|
|
||||||
Inside the `src/` folder, the `app/` folder contains your app's logic and data. Angular components, templates, and styles go here. An `assets/` subfolder contains images and anything else your app needs. Files at the top level of `src/` support testing and running your app.
|
Inside the `src/` folder, the `app/` folder contains your project's logic and data.
|
||||||
|
Angular components, templates, and styles go here.
|
||||||
|
|
||||||
| APP SOURCE FILES | PURPOSE |
|
| `src/app/` FILES | PURPOSE |
|
||||||
| :-------------------------- | :------------------------------------------|
|
| :-------------------------- | :------------------------------------------|
|
||||||
| `app/app.component.ts` | Defines the logic for the app's root component, named `AppComponent`. The view associated with this root component becomes the root of the [view hierarchy](guide/glossary#view-hierarchy) as you add components and services to your app. |
|
| `app/app.component.ts` | Defines the logic for the app's root component, named `AppComponent`. The view associated with this root component becomes the root of the [view hierarchy](guide/glossary#view-hierarchy) as you add components and services to your application. |
|
||||||
| `app/app.component.html` | Defines the HTML template associated with the root `AppComponent`. |
|
| `app/app.component.html` | Defines the HTML template associated with the root `AppComponent`. |
|
||||||
| `app/app.component.css` | Defines the base CSS stylesheet for the root `AppComponent`. |
|
| `app/app.component.css` | Defines the base CSS stylesheet for the root `AppComponent`. |
|
||||||
| `app/app.component.spec.ts` | Defines a unit test for the root `AppComponent`. |
|
| `app/app.component.spec.ts` | Defines a unit test for the root `AppComponent`. |
|
||||||
| `app/app.module.ts` | Defines the root module, named `AppModule`, that tells Angular how to assemble the application. Initially declares only the `AppComponent`. As you add more components to the app, they must be declared here. |
|
| `app/app.module.ts` | Defines the root module, named `AppModule`, that tells Angular how to assemble the application. Initially declares only the `AppComponent`. As you add more components to the app, they must be declared here. |
|
||||||
| `assets/*` | Contains image files and other asset files to be copied as-is when you build your application. |
|
|
||||||
|
### Application configuration files
|
||||||
|
|
||||||
|
The application-specific configuration files for the root application reside at the workspace root level.
|
||||||
|
For a multi-project workspace, project-specific configuration files are in the project root, under `projects/project-name/`.
|
||||||
|
|
||||||
|
Project-specific [TypeScript](https://www.typescriptlang.org/) configuration files inherit from the workspace-wide `tsconfig.json`, and project-specific [TSLint](https://palantir.github.io/tslint/) configuration files inherit from the workspace-wide `tslint.json`.
|
||||||
|
|
||||||
|
| APPLICATION-SPECIFIC CONFIG FILES | PURPOSE |
|
||||||
|
| :--------------------- | :------------------------------------------|
|
||||||
|
| `browserslist` | Configures sharing of target browsers and Node.js versions among various front-end tools. See [Browserslist on GitHub](https://github.com/browserslist/browserslist) for more information. |
|
||||||
|
| `karma.conf.js` | Application-specific [Karma](https://karma-runner.github.io/2.0/config/configuration-file.html) configuration. |
|
||||||
|
| `tsconfig.app.json` | Application-specific [TypeScript](https://www.typescriptlang.org/) configuration, including TypeScript and Angular template compiler options. See [TypeScript Configuration](guide/typescript-configuration). |
|
||||||
|
| `tsconfig.spec.json` | [TypeScript](https://www.typescriptlang.org/) configuration for the application tests. See [TypeScript Configuration](guide/typescript-configuration). |
|
||||||
|
| `tslint.json` | Application-specific [TSLint](https://palantir.github.io/tslint/) configuration. |
|
||||||
|
|
||||||
|
### End-to-end test files
|
||||||
|
|
||||||
|
An `e2e/` subfolder contains source files for a set of end-to-end tests that correspond to an application, along with test-specific configuration files.
|
||||||
|
|
||||||
|
<code-example language="none" linenums="false">
|
||||||
|
my-app/
|
||||||
|
e2e/
|
||||||
|
src/ (end-to-end tests for my-app)
|
||||||
|
app.e2e-spec.ts
|
||||||
|
app.po.ts
|
||||||
|
protractor.conf.js (test-tool config)
|
||||||
|
tsconfig.json (TypeScript config inherits from workspace)
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
{@a multiple-projects}
|
||||||
|
|
||||||
|
## Multiple projects
|
||||||
|
|
||||||
|
A multi-project workspace is suitable for an enterprise that uses a single repository and global configuration for all Angular projects (the "mono-repo" model). A multi-project workspace also supports library development.
|
||||||
|
|
||||||
|
### Setting up for a multi-project workspace
|
||||||
|
|
||||||
|
If you intend to have multiple projects in a workspace, you can skip the initial application generation when you create the workspace, and give the workspace a unique name.
|
||||||
|
The following command creates a workspace with all of the workspace-wide configuration files, but no root application.
|
||||||
|
|
||||||
|
<code-example language="bash" linenums="false">
|
||||||
|
ng new my-workspace --createApplication="false"
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
You can then generate apps and libraries with names that are unique within the workspace.
|
||||||
|
|
||||||
|
<code-example language="bash" linenums="false">
|
||||||
|
cd my-workspace
|
||||||
|
ng generate application my-first-app
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
### Multiple project file structure
|
||||||
|
|
||||||
|
The first explicitly generated application goes into the `projects/` folder along with all other projects in the workspace.
|
||||||
|
Newly generated libraries are also added under `projects/`.
|
||||||
|
When you create projects this way, the file structure of the workspace is entirely consistent with the structure of the [workspace configuration file](guide/workspace-config), `angular.json`.
|
||||||
|
|
||||||
|
<code-example language="none" linenums="false">
|
||||||
|
my-workspace/
|
||||||
|
... (workspace-wide config files)
|
||||||
|
projects/ (generated applications and libraries)
|
||||||
|
my-first-app/ --(an explicitly generated application)
|
||||||
|
... --(application-specific config)
|
||||||
|
e2e/ ----(corresponding e2e tests)
|
||||||
|
src/ ----(e2e tests source)
|
||||||
|
... ----(e2e-specific config)
|
||||||
|
src/ --(source and support files for application)
|
||||||
|
my-lib/ --(a generated library)
|
||||||
|
... --(library-specific config)
|
||||||
|
src/ --source and support files for library)
|
||||||
|
</code-example>
|
||||||
|
|
||||||
|
Libraries (unlike applications and their associated e2e projects) have their own `package.json` configuration files.
|
||||||
|
For more information about the library project structure, see [Creating Libraries](https://angular.io/guide/creating-libraries).
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user