diff --git a/.bazelrc b/.bazelrc index f7804b95e9fad..1f07b2fb6d1e2 100644 --- a/.bazelrc +++ b/.bazelrc @@ -74,8 +74,8 @@ test --test_output=errors # Trick bazel into treating BUILD files under integration/bazel as being regular files # This lets us glob() up all the files inside this integration test to make them inputs to tests # (Note, we cannot use common --deleted_packages because the bazel version command doesn't support it) -build --deleted_packages=integration/bazel,integration/bazel/src,integration/bazel/src/hello-world,integration/bazel/test,integration/bazel/test/e2e -query --deleted_packages=integration/bazel,integration/bazel/src,integration/bazel/src/hello-world,integration/bazel/test,integration/bazel/test/e2e +build --deleted_packages=integration/bazel,integration/bazel/src,integration/bazel/src/hello-world,integration/bazel/test,integration/bazel/tools,integration/bazel/test/e2e +query --deleted_packages=integration/bazel,integration/bazel/src,integration/bazel/src/hello-world,integration/bazel/test,integration/bazel/tools,integration/bazel/test/e2e ################################ # Temporary Settings for Ivy # diff --git a/.bazelversion b/.bazelversion index 44d4d72062f32..a57c344a29c88 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1,3 +1,3 @@ -3.2.0 +3.6.0 # [NB: this comment has to be after the first line, see https://github.com/bazelbuild/bazelisk/issues/117] # When updating the Bazel version you also need to update the RBE toolchains version in package.bzl diff --git a/.circleci/bazel.linux.rc b/.circleci/bazel.linux.rc index 9ecef0e1c6039..9bbc339b2004a 100644 --- a/.circleci/bazel.linux.rc +++ b/.circleci/bazel.linux.rc @@ -14,8 +14,8 @@ build --repository_cache=/home/circleci/bazel_repository_cache # Bazel doesn't calculate the memory ceiling correctly when running under Docker. # Limit Bazel to consuming resources that fit in CircleCI "xlarge" class # https://circleci.com/docs/2.0/configuration-reference/#resource_class -build --local_cpu_resources=8 -build --local_ram_resources=14336 +build --local_cpu_resources=20 +build --local_ram_resources=32768 # All build executed remotely should be done using our RBE configuration. build:remote --google_default_credentials diff --git a/.circleci/bazel.windows.rc b/.circleci/bazel.windows.rc index ce3e53392c8a4..309b1cba13214 100644 --- a/.circleci/bazel.windows.rc +++ b/.circleci/bazel.windows.rc @@ -6,13 +6,9 @@ # https://docs.bazel.build/versions/master/guide.html#bazelrc-syntax-and-semantics try-import %workspace%/.circleci/bazel.common.rc -# Save downloaded repositories in a location that can be cached by CircleCI. This helps us -# speeding up the analysis time significantly with Bazel managed node dependencies on the CI. -build --repository_cache=C:/Users/circleci/bazel_repository_cache - # Manually set the local resources used in windows CI runs -build --local_ram_resources=13500 -build --local_cpu_resources=4 +build --local_ram_resources=120000 +build --local_cpu_resources=32 # All windows jobs run on master and should use http caching build --remote_http_cache=https://storage.googleapis.com/angular-team-cache diff --git a/.circleci/config.yml b/.circleci/config.yml index c5347a6d6df39..b7053771f4bda 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -27,8 +27,6 @@ var_3: &cache_key v7-angular-node-12-{{ checksum ".bazelversion" }}-{{ checksum # folder will contain all previously used versions and ultimately cause the cache restoring to # be slower due to its growing size. var_4: &cache_key_fallback v7-angular-node-12-{{ checksum ".bazelversion" }} -var_3_win: &cache_key_win v7-angular-win-node-12-{{ checksum ".bazelversion" }}-{{ checksum "yarn.lock" }}-{{ checksum "WORKSPACE" }}-{{ checksum "packages/bazel/package.bzl" }}-{{ checksum "aio/yarn.lock" }} -var_4_win: &cache_key_win_fallback v7-angular-win-node-12-{{ checksum ".bazelversion" }} # Workspace initially persisted by the `setup` job, and then enhanced by `build-npm-packages` and # `build-ivy-npm-packages`. @@ -157,23 +155,12 @@ commands: setup_win: description: Setup windows node environment steps: - # Use the Linux workspace directly, as it already has checkout, rebased and node modules. - - custom_attach_workspace + - checkout # Install Bazel pre-requisites that aren't in the preconfigured CircleCI Windows VM. - run: ./.circleci/windows-env.ps1 - run: node --version - run: yarn --version - - restore_cache: - keys: - - *cache_key_win - - *cache_key_win_fallback - # Reinstall to get windows binaries. - run: yarn install --frozen-lockfile --non-interactive - # Install @bazel/bazelisk globally and use that for the first run. - # Workaround for https://github.com/bazelbuild/rules_nodejs/issues/894 - # NB: the issue was for @bazel/bazel but the same problem applies to @bazel/bazelisk - - run: yarn global add @bazel/bazelisk@$env:BAZELISK_VERSION - - run: bazelisk info notify_webhook_on_fail: description: Notify a webhook about failure diff --git a/.circleci/windows-env.ps1 b/.circleci/windows-env.ps1 index ece28bb8bfc17..014c2fcf97e22 100644 --- a/.circleci/windows-env.ps1 +++ b/.circleci/windows-env.ps1 @@ -2,8 +2,8 @@ # https://docs.bazel.build/versions/master/install-windows.html # https://docs.bazel.build/versions/master/windows.html # Install MSYS2 and packages -choco install msys2 --version 20180531.0.0 --no-progress --package-parameters "/NoUpdate" -C:\tools\msys64\usr\bin\bash.exe -l -c "pacman --needed --noconfirm -S zip unzip patch diffutils git" +choco install msys2 --version 20200903.0.0 --no-progress --package-parameters "/NoUpdate" +C:\tools\msys64\usr\bin\bash.exe -l -c "pacman --needed --noconfirm -S zip unzip patch diffutils" # Add PATH modifications to the Powershell profile. This is the win equivalent of .bash_profile. # https://docs.microsoft.com/en-us/previous-versions//bb613488(v=vs.85) @@ -41,7 +41,8 @@ copy .circleci\bazel.windows.rc ${Env:USERPROFILE}\.bazelrc #################################################################################################### # Install specific version of node. #################################################################################################### -choco install nodejs --version 12.14.1 --no-progress +nvm install 12.14.1 +nvm use 12.14.1 # These Bazel prereqs aren't needed because the CircleCI image already includes them. # choco install yarn --version 1.16.0 --no-progress diff --git a/.github/angular-robot.yml b/.github/angular-robot.yml index 290d1b32347c9..7ecd1b6cd0de2 100644 --- a/.github/angular-robot.yml +++ b/.github/angular-robot.yml @@ -38,6 +38,7 @@ merge: - "modules/benchmarks/**" - "modules/system.d.ts" - "packages/**" + - "dev-infra/benchmark/driver-utilities/**" # list of patterns to ignore for the files changed by the PR exclude: - "packages/*" @@ -47,7 +48,10 @@ merge: - "packages/bazel/src/ng_package/**" - "packages/bazel/src/protractor/**" - "packages/bazel/src/schematics/**" + - "packages/compiler-cli/src/ngcc/**" + - "packages/compiler-cli/linker/**" - "packages/compiler-cli/ngcc/**" + - "packages/compiler-cli/src/ngtsc/sourcemaps/**" - "packages/docs/**" - "packages/elements/schematics/**" - "packages/examples/**" @@ -55,6 +59,8 @@ merge: - "packages/localize/**" - "packages/private/**" - "packages/service-worker/**" + - "packages/common/locales/**" + - "packages/http/**" - "**/.gitignore" - "**/.gitkeep" - "**/yarn.lock" @@ -68,20 +74,20 @@ merge: - "packages/**/integrationtest/**" - "packages/**/test/**" - "packages/zone.js/*" + - "packages/zone.js/dist/**" - "packages/zone.js/doc/**" - "packages/zone.js/example/**" - "packages/zone.js/scripts/**" # comment that will be added to a PR when there is a conflict, leave empty or set to false to disable - mergeConflictComment: "Hi @{{PRAuthor}}! This PR has merge conflicts due to recent upstream merges. -\nPlease help to unblock it by resolving these conflicts. Thanks!" + mergeConflictComment: "Hi @{{PRAuthor}}! This PR has merge conflicts due to recent upstream merges.\nPlease help to unblock it by resolving these conflicts. Thanks!" # label to monitor - mergeLabel: "PR action: merge" + mergeLabel: "action: merge" # adding any of these labels will also add the merge label mergeLinkedLabels: - - "PR action: merge-assistance" + - "action: merge-assistance" # list of checks that will determine if the merge label can be added checks: @@ -94,17 +100,17 @@ merge: # whether the PR shouldn't have a conflict with the base branch noConflict: true - # list of labels that a PR needs to have, checked with a regexp (e.g. "PR target:" will work for the label "PR target: master") + # list of labels that a PR needs to have, checked with a regexp (e.g. "target:" will work for the label "target: master") requiredLabels: - - "PR target: *" + - "target: *" - "cla: yes" # list of labels that a PR shouldn't have, checked after the required labels with a regexp forbiddenLabels: - - "PR target: TBD" - - "PR action: cleanup" - - "PR action: review" - - "PR state: blocked" + - "target: TBD" + - "action: cleanup" + - "action: review" + - "state: blocked" - "cla: no" # list of PR statuses that need to be successful @@ -121,12 +127,7 @@ merge: # the comment that will be added when the merge label is added despite failing checks, leave empty or set to false to disable # {{MERGE_LABEL}} will be replaced by the value of the mergeLabel option # {{PLACEHOLDER}} will be replaced by the list of failing checks - mergeRemovedComment: "I see that you just added the `{{MERGE_LABEL}}` label, but the following checks are still failing: -\n{{PLACEHOLDER}} -\n -\n**If you want your PR to be merged, it has to pass all the CI checks.** -\n -\nIf you can't get the PR to a green state due to flakes or broken master, please try rebasing to master and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help." + mergeRemovedComment: "I see that you just added the `{{MERGE_LABEL}}` label, but the following checks are still failing:\n{{PLACEHOLDER}}\n\n**If you want your PR to be merged, it has to pass all the CI checks.**\n\nIf you can't get the PR to a green state due to flakes or broken master, please try rebasing to master and/or restarting the CI job. If that fails and you believe that the issue is not due to your change, please contact the caretaker and ask for help." # options for the triage plugin triage: @@ -141,24 +142,28 @@ triage: # arrays of labels that determine if an issue has been fully triaged l2TriageLabels: - - - "type: bug/fix" - - "severity*" - - "freq*" + - "P0" - "comp: *" - - - "type: feature" + - "P1" - "comp: *" - - - "type: refactor" + - "P2" - "comp: *" - - - "type: RFC / Discussion / question" + - "P3" - "comp: *" - - - "type: confusing" + - "P4" - "comp: *" - - - "type: use-case" + - "P5" + - "comp: *" + - + - "feature" + - "comp: *" + - + - "discussion" - "comp: *" # options for the triage PR plugin @@ -186,4 +191,4 @@ rerunCircleCI: # set to true to disable disabled: false # the label which when added triggers a rerun of the default CircleCI workflow - triggerRerunLabel: "PR action: rerun CI at HEAD" + triggerRerunLabel: "action: rerun CI at HEAD" diff --git a/.github/workflows/lock-closed.yml b/.github/workflows/lock-closed.yml index 4b88f003a7430..4a299ed90223e 100644 --- a/.github/workflows/lock-closed.yml +++ b/.github/workflows/lock-closed.yml @@ -10,6 +10,6 @@ jobs: if: github.repository == 'angular/angular' runs-on: ubuntu-latest steps: - - uses: angular/dev-infra/github-actions/lock-closed@66462f6 + - uses: angular/dev-infra/github-actions/lock-closed@414834b2b24dd2df37c6ed00808387ee6fd91b66 with: lock-bot-key: ${{ secrets.LOCK_BOT_PRIVATE_KEY }} diff --git a/.gitignore b/.gitignore index 5c592aed143aa..333dd7813c03a 100644 --- a/.gitignore +++ b/.gitignore @@ -40,8 +40,14 @@ yarn-error.log # User specific bazel settings .bazelrc.user +# User specific ng-dev settings +.ng-dev.user* + .notes.md baseline.json # Ignore .history for the xyz.local-history VSCode extension .history + +# CLDR data +tools/gulp-tasks/cldr/cldr-data/ diff --git a/.gitmessage b/.gitmessage index 46b6ffbd5caeb..536045e1d90f6 100644 --- a/.gitmessage +++ b/.gitmessage @@ -105,9 +105,9 @@ Fixes # # │ │ # │ └─⫸ Commit Scope: animations|bazel|benchpress|common|compiler|compiler-cli|core| # │ elements|forms|http|language-service|localize|platform-browser| -# │ platform-browser-dynamic|platform-server|platform-webworker| -# │ platform-webworker-dynamic|router|service-worker|upgrade|zone.js| -# │ packaging|changelog|dev-infra|docs-infra|migrations|ngcc|ve +# │ platform-browser-dynamic|platform-server|router|service-worker| +# │ upgrade|zone.js|packaging|changelog|dev-infra|docs-infra|migrations| +# │ ngcc|ve # │ https://github.com/angular/angular/blob/master/CONTRIBUTING.md#scope # │ # └─⫸ Commit Type: build|ci|docs|feat|fix|perf|refactor|style|test diff --git a/.ng-dev/caretaker.ts b/.ng-dev/caretaker.ts new file mode 100644 index 0000000000000..6d6aaa9684e28 --- /dev/null +++ b/.ng-dev/caretaker.ts @@ -0,0 +1,19 @@ +import {CaretakerConfig} from '../dev-infra/caretaker/config'; + +/** The configuration for `ng-dev caretaker` commands. */ +export const caretaker: CaretakerConfig = { + githubQueries: [ + { + name: 'Merge Queue', + query: `is:pr is:open status:success label:"action: merge"`, + }, + { + name: 'Merge Assistance Queue', + query: `is:pr is:open label:"action: merge-assistance"`, + }, + { + name: 'Initial Triage Queue', + query: `is:open no:milestone`, + } + ] +}; diff --git a/.ng-dev/commit-message.ts b/.ng-dev/commit-message.ts index 25033dd704036..0d247628cdd51 100644 --- a/.ng-dev/commit-message.ts +++ b/.ng-dev/commit-message.ts @@ -7,19 +7,6 @@ export const commitMessage: CommitMessageConfig = { maxLineLength: 120, minBodyLength: 20, minBodyLengthTypeExcludes: ['docs', 'upstream'], - types: [ - 'build', - 'ci', - 'docs', - 'feat', - 'fix', - 'perf', - 'refactor', - 'release', - 'style', - 'test', - 'upstream', - ], scopes: [ 'animations', 'bazel', diff --git a/.ng-dev/config.ts b/.ng-dev/config.ts index c620e02b730aa..4f059b5a6ec63 100644 --- a/.ng-dev/config.ts +++ b/.ng-dev/config.ts @@ -1,11 +1,15 @@ +import {caretaker} from './caretaker'; import {commitMessage} from './commit-message'; import {format} from './format'; import {github} from './github'; import {merge} from './merge'; +import {release} from './release'; module.exports = { commitMessage, format, github, merge, + caretaker, + release, }; diff --git a/.ng-dev/merge.ts b/.ng-dev/merge.ts index cb508bd3b121a..797c2d454752b 100644 --- a/.ng-dev/merge.ts +++ b/.ng-dev/merge.ts @@ -1,38 +1,28 @@ -import {MergeConfig} from '../dev-infra/pr/merge/config'; +import {DevInfraMergeConfig} from '../dev-infra/pr/merge/config'; +import {getDefaultTargetLabelConfiguration} from '../dev-infra/pr/merge/defaults'; +import {github} from './github'; +import {release} from './release'; /** * Configuration for the merge tool in `ng-dev`. This sets up the labels which * are respected by the merge script (e.g. the target labels). */ -export const merge = (): MergeConfig => { - // TODO: resume dynamically determining patch branch - const patch = '10.0.x'; +export const merge: DevInfraMergeConfig['merge'] = async api => { return { githubApiMerge: false, claSignedLabel: 'cla: yes', - mergeReadyLabel: /^PR action: merge(-assistance)?/, - caretakerNoteLabel: 'PR action: merge-assistance', + mergeReadyLabel: /^action: merge(-assistance)?/, + caretakerNoteLabel: 'action: merge-assistance', commitMessageFixupLabel: 'commit message fixup', - labels: [ - { - pattern: 'PR target: master-only', - branches: ['master'], - }, - { - pattern: 'PR target: patch-only', - branches: [patch], - }, - { - pattern: 'PR target: master & patch', - branches: ['master', patch], - }, - ], + // We can pick any of the NPM packages as we are in a monorepo where all packages are + // published together with the same version and branching. + labels: await getDefaultTargetLabelConfiguration(api, github, release), requiredBaseCommits: { // PRs that target either `master` or the patch branch, need to be rebased // on top of the latest commit message validation fix. // These SHAs are the commits that update the required license text in the header. 'master': '5aeb9a4124922d8ac08eb73b8f322905a32b0b3a', - [patch]: '27b95ba64a5d99757f4042073fd1860e20e3ed24' + '10.0.x': '27b95ba64a5d99757f4042073fd1860e20e3ed24', }, }; }; diff --git a/.ng-dev/release.ts b/.ng-dev/release.ts new file mode 100644 index 0000000000000..12f5b4a71c7b2 --- /dev/null +++ b/.ng-dev/release.ts @@ -0,0 +1,33 @@ +import {join} from 'path'; +import {exec} from 'shelljs'; +import {ReleaseConfig} from '../dev-infra/release/config'; + +/** Configuration for the `ng-dev release` command. */ +export const release: ReleaseConfig = { + npmPackages: [ + '@angular/animations', + '@angular/bazel', + '@angular/common', + '@angular/compiler', + '@angular/compiler-cli', + '@angular/core', + '@angular/elements', + '@angular/forms', + '@angular/language-service', + '@angular/localize', + '@angular/platform-browser', + '@angular/platform-browser-dynamic', + '@angular/platform-server', + '@angular/platform-webworker', + '@angular/platform-webworker-dynamic', + '@angular/router', + '@angular/service-worker', + '@angular/upgrade', + ], + // TODO: Implement release package building here. + buildPackages: async () => [], + // TODO: This can be removed once there is an org-wide tool for changelog generation. + generateReleaseNotesForHead: async () => { + exec('yarn -s gulp changelog', {cwd: join(__dirname, '../')}); + }, +}; diff --git a/.nvmrc b/.nvmrc index 5c088ddb94afa..72eb55e33db6b 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -12.14.1 +12.19 diff --git a/.pullapprove.yml b/.pullapprove.yml index b7f001b6a240b..9e6fa7ff9dcf6 100644 --- a/.pullapprove.yml +++ b/.pullapprove.yml @@ -186,6 +186,7 @@ groups: - IgorMinar # Igor Minar - jbogarthyde # Judy Bogart - jelbourn # Jeremy Elbourn + - jessicajaniuk # Jessica Janiuk - JiaLiPassion # Jia Li - JoostK # Joost Koehoorn - josephperrott # Joey Perrott @@ -284,7 +285,7 @@ groups: users: - alxhub - crisbeto - - devversion + # OOO as of 2020-09-28 - devversion # ========================================================= @@ -303,8 +304,6 @@ groups: 'packages/platform-browser/**', 'packages/examples/platform-browser/**', 'packages/platform-browser-dynamic/**', - 'packages/platform-webworker/**', - 'packages/platform-webworker-dynamic/**', 'packages/examples/common/**', 'packages/docs/**', 'aio/content/guide/accessibility.md', @@ -325,7 +324,10 @@ groups: 'aio/content/guide/component-interaction.md', 'aio/content/examples/component-interaction/**', 'aio/content/images/guide/component-interaction/**', + 'aio/content/guide/component-overview.md', + 'aio/content/examples/component-overview/**', 'aio/content/guide/component-styles.md', + 'aio/content/guide/view-encapsulation.md', 'aio/content/examples/component-styles/**', 'aio/content/guide/dependency-injection.md', 'aio/content/examples/dependency-injection/**', @@ -378,6 +380,7 @@ groups: 'aio/content/examples/binding-syntax/**', 'aio/content/guide/property-binding.md', 'aio/content/examples/property-binding/**', + 'aio/content/guide/property-binding-best-practices.md', 'aio/content/guide/attribute-binding.md', 'aio/content/examples/attribute-binding/**', 'aio/content/guide/two-way-binding.md', @@ -406,6 +409,7 @@ groups: 'aio/content/guide/structural-directives.md', 'aio/content/examples/structural-directives/**', 'aio/content/guide/svg-in-templates.md', + 'aio/content/guide/style-precedence.md', 'aio/content/images/guide/structural-directives/**', 'aio/content/guide/template-statements.md', 'aio/content/guide/user-input.md', @@ -419,7 +423,7 @@ groups: - atscott - ~kara # do not request reviews from Kara, but allow her to approve PRs - mhevery - - pkozlowski-opensource + # OOO as of 2020-09-28 - pkozlowski-opensource # ========================================================= @@ -509,8 +513,8 @@ groups: - > contains_any_globs(files, [ 'packages/core/src/i18n/**', - 'packages/core/src/render3/i18n.ts', - 'packages/core/src/render3/i18n.md', + 'packages/core/src/render3/i18n/**', + 'packages/core/src/render3/instructions/i18n.ts', 'packages/core/src/render3/interfaces/i18n.ts', 'packages/common/locales/**', 'packages/common/src/i18n/**', @@ -662,7 +666,7 @@ groups: users: - AndrewKushnir - IgorMinar - - pkozlowski-opensource + # OOO as of 2020-09-28 - pkozlowski-opensource # ========================================================= @@ -679,7 +683,7 @@ groups: reviewers: users: - IgorMinar - - pkozlowski-opensource + # OOO as of 2020-09-28 - pkozlowski-opensource # ========================================================= @@ -697,7 +701,7 @@ groups: users: - IgorMinar - jelbourn - - pkozlowski-opensource + # OOO as of 2020-09-28 - pkozlowski-opensource # ========================================================= @@ -723,7 +727,7 @@ groups: - IgorMinar - mhevery - jelbourn - - pkozlowski-opensource + # OOO as of 2020-09-28 - pkozlowski-opensource reviews: request: -1 # request reviews from everyone required: 2 # require at least 2 approvals @@ -1115,11 +1119,13 @@ groups: 'docs/DEBUG.md', 'docs/DEBUG_COMPONENTS_REPO_IVY.md', 'docs/DEVELOPER.md', + 'docs/FIXUP_COMMITS.md', 'docs/GITHUB_PROCESS.md', 'docs/PR_REVIEW.md', 'docs/SAVED_REPLIES.md', 'docs/TOOLS.md', 'docs/TRIAGE_AND_LABELS.md', + 'docs/images/**', 'goldens/*', 'modules/*', 'packages/*', @@ -1150,7 +1156,7 @@ groups: ]) reviewers: users: - - devversion + # OOO as of 2020-09-28 - devversion - filipesilva - gkalpak - IgorMinar @@ -1184,7 +1190,7 @@ groups: - atscott - jelbourn - petebacondarwin - - pkozlowski-opensource + # OOO as of 2020-09-28 - pkozlowski-opensource reviews: request: 4 # Request reviews from four people required: 3 # Require that three people approve @@ -1212,7 +1218,7 @@ groups: - atscott - jelbourn - petebacondarwin - - pkozlowski-opensource + # OOO as of 2020-09-28 - pkozlowski-opensource reviews: request: 4 # Request reviews from four people required: 2 # Require that two people approve @@ -1240,7 +1246,7 @@ groups: - atscott - jelbourn - petebacondarwin - - pkozlowski-opensource + # OOO as of 2020-09-28 - pkozlowski-opensource #################################################################################### diff --git a/.yarn/releases/yarn-1.22.4.js b/.yarn/releases/yarn-1.22.5.js similarity index 99% rename from .yarn/releases/yarn-1.22.4.js rename to .yarn/releases/yarn-1.22.5.js index 09eb37a2cbfcf..d31be0b947fbb 100755 --- a/.yarn/releases/yarn-1.22.4.js +++ b/.yarn/releases/yarn-1.22.5.js @@ -44654,7 +44654,7 @@ const FOLDERS_IGNORE = [ const DEFAULT_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([...FOLDERS_IGNORE, // ignore cruft -'yarn.lock', '.lock-wscript', '.wafpickle-{0..9}', '*.swp', '._*', 'npm-debug.log', 'yarn-error.log', '.npmrc', '.yarnrc', '.npmignore', '.gitignore', '.DS_Store']); +'yarn.lock', '.lock-wscript', '.wafpickle-{0..9}', '*.swp', '._*', 'npm-debug.log', 'yarn-error.log', '.npmrc', '.yarnrc', '.yarnrc.yml', '.npmignore', '.gitignore', '.DS_Store']); const NEVER_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([ // never ignore these files @@ -44663,6 +44663,7 @@ const NEVER_IGNORE = (0, (_filter || _load_filter()).ignoreLinesToRegex)([ function packWithIgnoreAndHeaders(cwd, ignoreFunction, { mapHeader } = {}) { return tar.pack(cwd, { ignore: ignoreFunction, + sort: true, map: header => { const suffix = header.name === '.' ? '' : `/${header.name}`; header.name = `package${suffix}`; @@ -46678,7 +46679,7 @@ function mkdirfix (name, opts, cb) { /* 194 */ /***/ (function(module, exports) { -module.exports = {"name":"yarn","installationMethod":"unknown","version":"1.22.4","license":"BSD-2-Clause","preferGlobal":true,"description":"📦🐈 Fast, reliable, and secure dependency management.","dependencies":{"@zkochan/cmd-shim":"^3.1.0","babel-runtime":"^6.26.0","bytes":"^3.0.0","camelcase":"^4.0.0","chalk":"^2.1.0","cli-table3":"^0.4.0","commander":"^2.9.0","death":"^1.0.0","debug":"^3.0.0","deep-equal":"^1.0.1","detect-indent":"^5.0.0","dnscache":"^1.0.1","glob":"^7.1.1","gunzip-maybe":"^1.4.0","hash-for-dep":"^1.2.3","imports-loader":"^0.8.0","ini":"^1.3.4","inquirer":"^6.2.0","invariant":"^2.2.0","is-builtin-module":"^2.0.0","is-ci":"^1.0.10","is-webpack-bundle":"^1.0.0","js-yaml":"^3.13.1","leven":"^2.0.0","loud-rejection":"^1.2.0","micromatch":"^2.3.11","mkdirp":"^0.5.1","node-emoji":"^1.6.1","normalize-url":"^2.0.0","npm-logical-tree":"^1.2.1","object-path":"^0.11.2","proper-lockfile":"^2.0.0","puka":"^1.0.0","read":"^1.0.7","request":"^2.87.0","request-capture-har":"^1.2.2","rimraf":"^2.5.0","semver":"^5.1.0","ssri":"^5.3.0","strip-ansi":"^4.0.0","strip-bom":"^3.0.0","tar-fs":"^1.16.0","tar-stream":"^1.6.1","uuid":"^3.0.1","v8-compile-cache":"^2.0.0","validate-npm-package-license":"^3.0.4","yn":"^2.0.0"},"devDependencies":{"babel-core":"^6.26.0","babel-eslint":"^7.2.3","babel-loader":"^6.2.5","babel-plugin-array-includes":"^2.0.3","babel-plugin-inline-import":"^3.0.0","babel-plugin-transform-builtin-extend":"^1.1.2","babel-plugin-transform-inline-imports-commonjs":"^1.0.0","babel-plugin-transform-runtime":"^6.4.3","babel-preset-env":"^1.6.0","babel-preset-flow":"^6.23.0","babel-preset-stage-0":"^6.0.0","babylon":"^6.5.0","commitizen":"^2.9.6","cz-conventional-changelog":"^2.0.0","eslint":"^4.3.0","eslint-config-fb-strict":"^22.0.0","eslint-plugin-babel":"^5.0.0","eslint-plugin-flowtype":"^2.35.0","eslint-plugin-jasmine":"^2.6.2","eslint-plugin-jest":"^21.0.0","eslint-plugin-jsx-a11y":"^6.0.2","eslint-plugin-prefer-object-spread":"^1.2.1","eslint-plugin-prettier":"^2.1.2","eslint-plugin-react":"^7.1.0","eslint-plugin-relay":"^0.0.28","eslint-plugin-yarn-internal":"file:scripts/eslint-rules","execa":"^0.11.0","fancy-log":"^1.3.2","flow-bin":"^0.66.0","git-release-notes":"^3.0.0","gulp":"^4.0.0","gulp-babel":"^7.0.0","gulp-if":"^2.0.1","gulp-newer":"^1.0.0","gulp-plumber":"^1.0.1","gulp-sourcemaps":"^2.2.0","jest":"^22.4.4","jsinspect":"^0.12.6","minimatch":"^3.0.4","mock-stdin":"^0.3.0","prettier":"^1.5.2","string-replace-loader":"^2.1.1","temp":"^0.8.3","webpack":"^2.1.0-beta.25","yargs":"^6.3.0"},"resolutions":{"sshpk":"^1.14.2"},"engines":{"node":">=4.0.0"},"repository":"yarnpkg/yarn","bin":{"yarn":"./bin/yarn.js","yarnpkg":"./bin/yarn.js"},"scripts":{"build":"gulp build","build-bundle":"node ./scripts/build-webpack.js","build-chocolatey":"powershell ./scripts/build-chocolatey.ps1","build-deb":"./scripts/build-deb.sh","build-dist":"bash ./scripts/build-dist.sh","build-win-installer":"scripts\\build-windows-installer.bat","changelog":"git-release-notes $(git describe --tags --abbrev=0 $(git describe --tags --abbrev=0)^)..$(git describe --tags --abbrev=0) scripts/changelog.md","dupe-check":"yarn jsinspect ./src","lint":"eslint . && flow check","pkg-tests":"yarn --cwd packages/pkg-tests jest yarn.test.js","prettier":"eslint src __tests__ --fix","release-branch":"./scripts/release-branch.sh","test":"yarn lint && yarn test-only","test-only":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --verbose","test-only-debug":"node --inspect-brk --max_old_space_size=4096 node_modules/jest/bin/jest.js --runInBand --verbose","test-coverage":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --coverage --verbose","watch":"gulp watch","commit":"git-cz"},"jest":{"collectCoverageFrom":["src/**/*.js"],"testEnvironment":"node","modulePathIgnorePatterns":["__tests__/fixtures/","packages/pkg-tests/pkg-tests-fixtures","dist/"],"testPathIgnorePatterns":["__tests__/(fixtures|__mocks__)/","updates/","_(temp|mock|install|init|helpers).js$","packages/pkg-tests"]},"config":{"commitizen":{"path":"./node_modules/cz-conventional-changelog"}}} +module.exports = {"name":"yarn","installationMethod":"unknown","version":"1.22.5","license":"BSD-2-Clause","preferGlobal":true,"description":"📦🐈 Fast, reliable, and secure dependency management.","dependencies":{"@zkochan/cmd-shim":"^3.1.0","babel-runtime":"^6.26.0","bytes":"^3.0.0","camelcase":"^4.0.0","chalk":"^2.1.0","cli-table3":"^0.4.0","commander":"^2.9.0","death":"^1.0.0","debug":"^3.0.0","deep-equal":"^1.0.1","detect-indent":"^5.0.0","dnscache":"^1.0.1","glob":"^7.1.1","gunzip-maybe":"^1.4.0","hash-for-dep":"^1.2.3","imports-loader":"^0.8.0","ini":"^1.3.4","inquirer":"^6.2.0","invariant":"^2.2.0","is-builtin-module":"^2.0.0","is-ci":"^1.0.10","is-webpack-bundle":"^1.0.0","js-yaml":"^3.13.1","leven":"^2.0.0","loud-rejection":"^1.2.0","micromatch":"^2.3.11","mkdirp":"^0.5.1","node-emoji":"^1.6.1","normalize-url":"^2.0.0","npm-logical-tree":"^1.2.1","object-path":"^0.11.2","proper-lockfile":"^2.0.0","puka":"^1.0.0","read":"^1.0.7","request":"^2.87.0","request-capture-har":"^1.2.2","rimraf":"^2.5.0","semver":"^5.1.0","ssri":"^5.3.0","strip-ansi":"^4.0.0","strip-bom":"^3.0.0","tar-fs":"^1.16.0","tar-stream":"^1.6.1","uuid":"^3.0.1","v8-compile-cache":"^2.0.0","validate-npm-package-license":"^3.0.4","yn":"^2.0.0"},"devDependencies":{"babel-core":"^6.26.0","babel-eslint":"^7.2.3","babel-loader":"^6.2.5","babel-plugin-array-includes":"^2.0.3","babel-plugin-inline-import":"^3.0.0","babel-plugin-transform-builtin-extend":"^1.1.2","babel-plugin-transform-inline-imports-commonjs":"^1.0.0","babel-plugin-transform-runtime":"^6.4.3","babel-preset-env":"^1.6.0","babel-preset-flow":"^6.23.0","babel-preset-stage-0":"^6.0.0","babylon":"^6.5.0","commitizen":"^2.9.6","cz-conventional-changelog":"^2.0.0","eslint":"^4.3.0","eslint-config-fb-strict":"^22.0.0","eslint-plugin-babel":"^5.0.0","eslint-plugin-flowtype":"^2.35.0","eslint-plugin-jasmine":"^2.6.2","eslint-plugin-jest":"^21.0.0","eslint-plugin-jsx-a11y":"^6.0.2","eslint-plugin-prefer-object-spread":"^1.2.1","eslint-plugin-prettier":"^2.1.2","eslint-plugin-react":"^7.1.0","eslint-plugin-relay":"^0.0.28","eslint-plugin-yarn-internal":"file:scripts/eslint-rules","execa":"^0.11.0","fancy-log":"^1.3.2","flow-bin":"^0.66.0","git-release-notes":"^3.0.0","gulp":"^4.0.0","gulp-babel":"^7.0.0","gulp-if":"^2.0.1","gulp-newer":"^1.0.0","gulp-plumber":"^1.0.1","gulp-sourcemaps":"^2.2.0","jest":"^22.4.4","jsinspect":"^0.12.6","minimatch":"^3.0.4","mock-stdin":"^0.3.0","prettier":"^1.5.2","string-replace-loader":"^2.1.1","temp":"^0.8.3","webpack":"^2.1.0-beta.25","yargs":"^6.3.0"},"resolutions":{"sshpk":"^1.14.2"},"engines":{"node":">=4.0.0"},"repository":"yarnpkg/yarn","bin":{"yarn":"./bin/yarn.js","yarnpkg":"./bin/yarn.js"},"scripts":{"build":"gulp build","build-bundle":"node ./scripts/build-webpack.js","build-chocolatey":"powershell ./scripts/build-chocolatey.ps1","build-deb":"./scripts/build-deb.sh","build-dist":"bash ./scripts/build-dist.sh","build-win-installer":"scripts\\build-windows-installer.bat","changelog":"git-release-notes $(git describe --tags --abbrev=0 $(git describe --tags --abbrev=0)^)..$(git describe --tags --abbrev=0) scripts/changelog.md","dupe-check":"yarn jsinspect ./src","lint":"eslint . && flow check","pkg-tests":"yarn --cwd packages/pkg-tests jest yarn.test.js","prettier":"eslint src __tests__ --fix","release-branch":"./scripts/release-branch.sh","test":"yarn lint && yarn test-only","test-only":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --verbose","test-only-debug":"node --inspect-brk --max_old_space_size=4096 node_modules/jest/bin/jest.js --runInBand --verbose","test-coverage":"node --max_old_space_size=4096 node_modules/jest/bin/jest.js --coverage --verbose","watch":"gulp watch","commit":"git-cz"},"jest":{"collectCoverageFrom":["src/**/*.js"],"testEnvironment":"node","modulePathIgnorePatterns":["__tests__/fixtures/","packages/pkg-tests/pkg-tests-fixtures","dist/"],"testPathIgnorePatterns":["__tests__/(fixtures|__mocks__)/","updates/","_(temp|mock|install|init|helpers).js$","packages/pkg-tests"]},"config":{"commitizen":{"path":"./node_modules/cz-conventional-changelog"}}} /***/ }), /* 195 */ @@ -98338,7 +98339,7 @@ var _buildSubCommands = (0, (_buildSubCommands2 || _load_buildSubCommands()).def const bundle = yield fetchBundle(config, bundleUrl); - const yarnPath = path.resolve(config.lockfileFolder, `.yarn/releases/yarn-${bundleVersion}.js`); + const yarnPath = path.resolve(config.lockfileFolder, `.yarn/releases/yarn-${bundleVersion}.cjs`); reporter.log(`Saving it into ${chalk.magenta(yarnPath)}...`); yield (_fs || _load_fs()).mkdirp(path.dirname(yarnPath)); yield (_fs || _load_fs()).writeFile(yarnPath, bundle); @@ -100190,7 +100191,7 @@ let main = exports.main = (() => { const config = new (_config || _load_config()).default(reporter); const outputWrapperEnabled = (0, (_conversion || _load_conversion()).boolifyWithDefault)(process.env.YARN_WRAP_OUTPUT, true); - const shouldWrapOutput = outputWrapperEnabled && !(_commander || _load_commander()).default.json && command.hasWrapper((_commander || _load_commander()).default, (_commander || _load_commander()).default.args); + const shouldWrapOutput = outputWrapperEnabled && !(_commander || _load_commander()).default.json && command.hasWrapper((_commander || _load_commander()).default, (_commander || _load_commander()).default.args) && !(commandName === 'init' && (_commander || _load_commander()).default[`2`]); if (shouldWrapOutput) { reporter.header(commandName, { name: 'yarn', version: (_yarnVersion || _load_yarnVersion()).version }); @@ -100604,7 +100605,7 @@ let start = (() => { }); try { - if (yarnPath.endsWith(`.js`)) { + if (/\.[cm]?js$/.test(yarnPath)) { exitCode = yield (0, (_child || _load_child()).spawnp)(process.execPath, [yarnPath, ...argv], opts); } else { exitCode = yield (0, (_child || _load_child()).spawnp)(yarnPath, argv, opts); diff --git a/.yarnrc b/.yarnrc index 860f7e3a8be42..54b28414542d9 100644 --- a/.yarnrc +++ b/.yarnrc @@ -2,4 +2,4 @@ # yarn lockfile v1 -yarn-path ".yarn/releases/yarn-1.22.4.js" +yarn-path ".yarn/releases/yarn-1.22.5.js" diff --git a/BUILD.bazel b/BUILD.bazel index 73e67bea63ea4..4ff7e77c85f46 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -34,7 +34,7 @@ filegroup( filegroup( name = "angularjs_scripts", srcs = [ - # We also declare the unminfied AngularJS files since these can be used for + # We also declare the unminified AngularJS files since these can be used for # local debugging (e.g. see: packages/upgrade/test/common/test_helpers.ts) "@npm//:node_modules/angular/angular.js", "@npm//:node_modules/angular/angular.min.js", @@ -47,3 +47,9 @@ filegroup( "@npm//:node_modules/angular-mocks-1.6/angular-mocks.js", ], ) + +# Detect if the build is running under --stamp +config_setting( + name = "stamp", + values = {"stamp": "true"}, +) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a466e36b135a..afaf3d9be9862 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,171 +1,676 @@ - -# 10.1.0-next.4 (2020-08-04) + +# 11.0.0-rc.0 (2020-10-21) ### Bug Fixes -* **common:** narrow `NgIf` context variables in template type checker ([#36627](https://github.com/angular/angular/issues/36627)) ([9c8bc4a](https://github.com/angular/angular/commit/9c8bc4a)) -* **compiler:** mark `NgModuleFactory` construction as not side effectful ([#38147](https://github.com/angular/angular/issues/38147)) ([7f8c222](https://github.com/angular/angular/commit/7f8c222)) +* **common:** update locales using new CLDR data ([#39343](https://github.com/angular/angular/issues/39343)) ([3738233](https://github.com/angular/angular/commit/3738233)) +* **compiler:** promote constants in templates to Trusted Types ([#39211](https://github.com/angular/angular/issues/39211)) ([6e18d2d](https://github.com/angular/angular/commit/6e18d2d)) +* **core:** guard reading of global `ngDevMode` for undefined. ([#36055](https://github.com/angular/angular/issues/36055)) ([f541e5f](https://github.com/angular/angular/commit/f541e5f)) +* **language-service:** [Ivy] create compiler only when program changes ([#39231](https://github.com/angular/angular/issues/39231)) ([8f1317f](https://github.com/angular/angular/commit/8f1317f)) +* **ngcc:** ensure that "inline exports" can be interpreted correctly ([#39267](https://github.com/angular/angular/issues/39267)) ([822b838](https://github.com/angular/angular/commit/822b838)) +* **platform-server:** Resolve absolute URL from baseUrl ([#39334](https://github.com/angular/angular/issues/39334)) ([b4e8399](https://github.com/angular/angular/commit/b4e8399)) +* **router:** incorrect signature for createUrlTree ([#39347](https://github.com/angular/angular/issues/39347)) ([161b278](https://github.com/angular/angular/commit/161b278)) -### Features +### Code Refactoring -* **core:** rename async to waitForAsync to avoid confusing ([#37583](https://github.com/angular/angular/issues/37583)) ([8f07429](https://github.com/angular/angular/commit/8f07429)) -* **core:** update reference and doc to change `async` to `waitAsync`. ([#37583](https://github.com/angular/angular/issues/37583)) ([8fbf40b](https://github.com/angular/angular/commit/8fbf40b)) +* **compiler:** remove support for TypeScript 3.9 ([#39313](https://github.com/angular/angular/issues/39313)) ([736e064](https://github.com/angular/angular/commit/736e064)) +### BREAKING CHANGES - -## 10.0.8 (2020-08-04) +* **platform-server:** If you use `useAbsoluteUrl` to setup `platform-server`, you now need to +also specify `baseUrl`. +We are intentionally making this a breaking change in a minor release, +because if `useAbsoluteUrl` is set to `true` then the behavior of the +application could be unpredictable, resulting in issues that are hard to +discover but could be affecting production environments. +* **compiler:** TypeScript 3.9 is no longer supported, please upgrade to TypeScript 4.0. + + + + +# 10.2.0 (2020-10-21) ### Bug Fixes -* **compiler:** add PURE annotation to getInheritedFactory calls ([#38291](https://github.com/angular/angular/issues/38291)) ([03d8e31](https://github.com/angular/angular/commit/03d8e31)) -* **compiler:** update unparsable character reference entity error messages ([#38319](https://github.com/angular/angular/issues/38319)) ([cea4678](https://github.com/angular/angular/commit/cea4678)), closes [#26067](https://github.com/angular/angular/issues/26067) +* **core:** guard reading of global `ngDevMode` for undefined. ([#36055](https://github.com/angular/angular/issues/36055)) ([02405f1](https://github.com/angular/angular/commit/02405f1)) +* **platform-server:** Resolve absolute URL from baseUrl ([#39334](https://github.com/angular/angular/issues/39334)) ([71fb99f](https://github.com/angular/angular/commit/71fb99f)) +### BREAKING CHANGES + +* **platform-server:** If you use `useAbsoluteUrl` to setup `platform-server`, you now need to +also specify `baseUrl`. +We are intentionally making this a breaking change in a minor release, +because if `useAbsoluteUrl` is set to `true` then the behavior of the +application could be unpredictable, resulting in issues that are hard to +discover but could be affecting production environments. - -## 10.0.7 (2020-07-30) + + + +# 11.0.0-next.6 (2020-10-14) ### Bug Fixes -* **compiler:** Metadata should not include methods on Object.prototype ([#38292](https://github.com/angular/angular/issues/38292)) ([879ff08](https://github.com/angular/angular/commit/879ff08)) +* **compiler-cli:** type checking of expressions within ICUs ([#39072](https://github.com/angular/angular/issues/39072)) ([0a16e60](https://github.com/angular/angular/commit/0a16e60)), closes [#39064](https://github.com/angular/angular/issues/39064) +* **core:** migrate relative link resolution with single quotes ([#39102](https://github.com/angular/angular/issues/39102)) ([049b453](https://github.com/angular/angular/commit/049b453)), closes [#39082](https://github.com/angular/angular/issues/39082) +* **core:** use Trusted Types policy in inert DOM builder ([#39208](https://github.com/angular/angular/issues/39208)) ([7d49299](https://github.com/angular/angular/commit/7d49299)) +* **core:** use Trusted Types policy in named_array_type ([#39209](https://github.com/angular/angular/issues/39209)) ([f6d5cdf](https://github.com/angular/angular/commit/f6d5cdf)) +* **router:** Allow undefined inputs on routerLink ([#39151](https://github.com/angular/angular/issues/39151)) ([b0b4953](https://github.com/angular/angular/commit/b0b4953)) +* **router:** create schematic for preserveQueryParams ([#38762](https://github.com/angular/angular/issues/38762)) ([93ee05d](https://github.com/angular/angular/commit/93ee05d)) +* **router:** remove preserveQueryParams symbol ([#38762](https://github.com/angular/angular/issues/38762)) ([783a5bd](https://github.com/angular/angular/commit/783a5bd)) + + +### Features + +* **core:** add automated migration to replace async with waitForAsync ([#39212](https://github.com/angular/angular/issues/39212)) ([5ce71e0](https://github.com/angular/angular/commit/5ce71e0)) +* **core:** add automated migration to replace ViewEncapsulation.Native ([#38882](https://github.com/angular/angular/issues/38882)) ([0e733f3](https://github.com/angular/angular/commit/0e733f3)) +* **core:** add initialNavigation schematic ([#36926](https://github.com/angular/angular/issues/36926)) ([0ec7043](https://github.com/angular/angular/commit/0ec7043)) +* **core:** add Trusted Types workaround for Function constructor ([#39209](https://github.com/angular/angular/issues/39209)) ([5913e5c](https://github.com/angular/angular/commit/5913e5c)) +* **core:** create internal Trusted Types module ([#39207](https://github.com/angular/angular/issues/39207)) ([0875fd2](https://github.com/angular/angular/commit/0875fd2)) +* **core:** depend on type definitions for Trusted Types ([#39207](https://github.com/angular/angular/issues/39207)) ([c4266fb](https://github.com/angular/angular/commit/c4266fb)) +* **core:** remove ViewEncapsulation.Native ([#38882](https://github.com/angular/angular/issues/38882)) ([4a1c12c](https://github.com/angular/angular/commit/4a1c12c)) +* **language-service:** [Ivy] getSemanticDiagnostics for external templates ([#39065](https://github.com/angular/angular/issues/39065)) ([63624a2](https://github.com/angular/angular/commit/63624a2)) +* **language-service:** Add getTypeDefinitionAtPosition (go to type definition) ([#39145](https://github.com/angular/angular/issues/39145)) ([a84976f](https://github.com/angular/angular/commit/a84976f)) +* **language-service:** Add module name to directive quick info ([#39121](https://github.com/angular/angular/issues/39121)) ([4604fe9](https://github.com/angular/angular/commit/4604fe9)) +* **router:** add new initialNavigation options to replace legacy ([#37480](https://github.com/angular/angular/issues/37480)) ([c4becca](https://github.com/angular/angular/commit/c4becca)) + + +### BREAKING CHANGES +* **router:** * The `initialNavigation` property for the options in + `RouterModule.forRoot` no longer supports `legacy_disabled`, + `legacy_enabled`, `true`, or `false` as valid values. + `legacy_enabled` (the old default) is instead `enabledNonBlocking` +* `enabled` is deprecated as a valid value for the + `RouterModule.forRoot` `initialNavigation` option. `enabledBlocking` + has been introduced to replace it +* **router:** preserveQueryParams has been removed, use +queryParamsHandling="preserve" instead +* **router:** If you were accessing the `RouterLink` values of `queryParams`, +`fragment` or `queryParamsHandling` you might need to relax the typing to also +accept `undefined` and `null`. ([#39151](https://github.com/angular/angular/issues/39151)) +* **core:** * `ViewEncapsulation.Native` has been removed. Use `ViewEncapsulation.ShadowDom` instead. Existing +usages will be updated automatically by `ng update`. +* **compiler-cli:** Expressions within ICUs are now type-checked again, fixing a regression +in Ivy. This may cause compilation failures if errors are found in +expressions that appear within an ICU. Please correct these expressions +to resolve the type-check errors. - -# 10.1.0-next.3 (2020-07-28) + +## 10.1.6 (2020-10-14) ### Bug Fixes -* **elements:** run strategy methods in correct zone ([#37814](https://github.com/angular/angular/issues/37814)) ([8df888d](https://github.com/angular/angular/commit/8df888d)), closes [#24181](https://github.com/angular/angular/issues/24181) +* **compiler:** incorrectly encapsulating [@import](https://github.com/import) containing colons and semicolons ([#38716](https://github.com/angular/angular/issues/38716)) ([52a0c6b](https://github.com/angular/angular/commit/52a0c6b)), closes [#38587](https://github.com/angular/angular/issues/38587) +* **compiler-cli:** support namespaced query types in directives ([#38959](https://github.com/angular/angular/issues/38959)) ([#39272](https://github.com/angular/angular/issues/39272)) ([f752ab9](https://github.com/angular/angular/commit/f752ab9)) +* **elements:** detect matchesSelector prototype without IIFE ([#37799](https://github.com/angular/angular/issues/37799)) ([952fd86](https://github.com/angular/angular/commit/952fd86)), closes [#24551](https://github.com/angular/angular/issues/24551) +* **ngcc:** ensure that "inline exports" can be interpreted correctly ([#39272](https://github.com/angular/angular/issues/39272)) ([e08d021](https://github.com/angular/angular/commit/e08d021)) +* **ngcc:** handle aliases in UMD export declarations ([#38959](https://github.com/angular/angular/issues/38959)) ([#39272](https://github.com/angular/angular/issues/39272)) ([9963c5d](https://github.com/angular/angular/commit/9963c5d)), closes [#38947](https://github.com/angular/angular/issues/38947) +* **ngcc:** map `exports` to the current module in UMD files ([#38959](https://github.com/angular/angular/issues/38959)) ([#39272](https://github.com/angular/angular/issues/39272)) ([13c4a7b](https://github.com/angular/angular/commit/13c4a7b)) +* **ngcc:** support inline export declarations in UMD files ([#38959](https://github.com/angular/angular/issues/38959)) ([#39272](https://github.com/angular/angular/issues/39272)) ([9c875b3](https://github.com/angular/angular/commit/9c875b3)), closes [#38947](https://github.com/angular/angular/issues/38947) +### build - -## 10.0.6 (2020-07-28) +* upgrade angular build, integration/bazel and [@angular](https://github.com/angular)/bazel package to rule_nodejs 2.2.0 ([#39182](https://github.com/angular/angular/issues/39182)) ([7628c36](https://github.com/angular/angular/commit/7628c36)) + + +### Performance Improvements + +* **ngcc:** do not rescan program source files when referenced from multiple root files ([#39254](https://github.com/angular/angular/issues/39254)) ([5221df8](https://github.com/angular/angular/commit/5221df8)), closes [#39240](https://github.com/angular/angular/issues/39240) + + + +# 11.0.0-next.5 (2020-10-07) ### Bug Fixes -* **compiler:** share identical stylesheets between components in the same file ([#38213](https://github.com/angular/angular/issues/38213)) ([264950b](https://github.com/angular/angular/commit/264950b)), closes [#38204](https://github.com/angular/angular/issues/38204) -* **compiler-cli:** Add support for string literal class members ([#38226](https://github.com/angular/angular/issues/38226)) ([b1e7775](https://github.com/angular/angular/commit/b1e7775)) -* **core:** `Attribute` decorator `attributeName` is mandatory ([#38131](https://github.com/angular/angular/issues/38131)) ([1c4fcce](https://github.com/angular/angular/commit/1c4fcce)), closes [#32658](https://github.com/angular/angular/issues/32658) -* **core:** unify the signature between ngZone and noopZone ([#37581](https://github.com/angular/angular/issues/37581)) ([d5264f5](https://github.com/angular/angular/commit/d5264f5)) +* **common:** add boolean to valid json for testing ([#37893](https://github.com/angular/angular/issues/37893)) ([3c474ec](https://github.com/angular/angular/commit/3c474ec)), closes [#20690](https://github.com/angular/angular/issues/20690) +* **core:** use single quotes for relative link resolution migration to align with style guide ([#39070](https://github.com/angular/angular/issues/39070)) ([8894706](https://github.com/angular/angular/commit/8894706)) +* **forms:** improve types of directive constructor arguments ([#38944](https://github.com/angular/angular/issues/38944)) ([246de9a](https://github.com/angular/angular/commit/246de9a)) +* **forms:** include null in .parent of abstract control ([#32671](https://github.com/angular/angular/issues/32671)) ([f4f1bcc](https://github.com/angular/angular/commit/f4f1bcc)), closes [#16999](https://github.com/angular/angular/issues/16999) +* **language-service:** [Ivy] hybrid visitor should not locate let keyword ([#39061](https://github.com/angular/angular/issues/39061)) ([70e13dc](https://github.com/angular/angular/commit/70e13dc)) +* **router:** properly assign ExtraOptions to Router in RouterTestingModule ([#39096](https://github.com/angular/angular/issues/39096)) ([d8c0534](https://github.com/angular/angular/commit/d8c0534)), closes [#23347](https://github.com/angular/angular/issues/23347) + + +### Features +* **compiler-cli:** support getting resource dependencies for a source file ([#38048](https://github.com/angular/angular/issues/38048)) ([5dbf357](https://github.com/angular/angular/commit/5dbf357)) +* **forms:** add migration for AbstractControl.parent accesses ([#39009](https://github.com/angular/angular/issues/39009)) ([aeec223](https://github.com/angular/angular/commit/aeec223)), closes [#32671](https://github.com/angular/angular/issues/32671) +* **language-service:** Add getDefinitionAndBoundSpan (go to definition) ([#39101](https://github.com/angular/angular/issues/39101)) ([3975dd9](https://github.com/angular/angular/commit/3975dd9)) +* **language-service:** add quick info for inline templates in ivy ([#39060](https://github.com/angular/angular/issues/39060)) ([904adb7](https://github.com/angular/angular/commit/904adb7)) - -# 10.1.0-next.2 (2020-07-22) +### BREAKING CHANGES + +* **forms:** Directives in the `@angular/forms` package used to have `any[]` as a type of `validators` and +`asyncValidators` arguments in constructors. Now these arguments are properly typed, so if your +code relies on directive constructor types it may require some updates to improve type safety. +* **forms:** Type of AbstractFormControl.parent now includes null + +`null` is now included in the types of .parent. If you don't already have a check for this case, +the TypeScript compiler might compain. A v11 migration exists which adds the not-null assertion +operator where necessary. + +In an unlikely case your code was testing the parnet against undefined with sitrct equality, +you'll need to change this to `=== null` instead, since the parent is not explicily initialized +with `null` instead of being left `undefined`. + + + + +## 10.1.5 (2020-10-07) ### Bug Fixes -* **core:** Allow modification of lifecycle hooks any time before bootstrap ([#35464](https://github.com/angular/angular/issues/35464)) ([737506e](https://github.com/angular/angular/commit/737506e)), closes [#30497](https://github.com/angular/angular/issues/30497) +* **router:** update getRouteGuards to check if the context outlet is activated ([#39049](https://github.com/angular/angular/issues/39049)) ([771f731](https://github.com/angular/angular/commit/771f731)), closes [#39030](https://github.com/angular/angular/issues/39030) +* **compiler:** Recover on malformed keyed reads and keyed writes ([#39004](https://github.com/angular/angular/issues/39004)) ([f50313f](https://github.com/angular/angular/commit/f50313f)), closes [#38596](https://github.com/angular/angular/issues/38596) + + + + +# 11.0.0-next.4 (2020-09-30) + + +### Bug Fixes + +* **common:** correct and simplify typing of `KeyValuePipe` ([#37447](https://github.com/angular/angular/issues/37447)) ([4dfe0fa](https://github.com/angular/angular/commit/4dfe0fa)) +* **common:** correct and simplify typing of AsyncPipe ([#37447](https://github.com/angular/angular/issues/37447)) ([5f815c0](https://github.com/angular/angular/commit/5f815c0)) +* **common:** correct and simplify typing of I18nPluralPipe ([#37447](https://github.com/angular/angular/issues/37447)) ([3b919ef](https://github.com/angular/angular/commit/3b919ef)) +* **common:** correct typing and implementation of `SlicePipe` ([#37447](https://github.com/angular/angular/issues/37447)) ([4744c22](https://github.com/angular/angular/commit/4744c22)) +* **common:** let case conversion pipes accept type unions with `null` ([#36259](https://github.com/angular/angular/issues/36259)) ([#37447](https://github.com/angular/angular/issues/37447)) ([c7d5555](https://github.com/angular/angular/commit/c7d5555)) +* **compiler-cli:** perform DOM schema checks even in basic mode in g3 ([#38943](https://github.com/angular/angular/issues/38943)) ([40975e0](https://github.com/angular/angular/commit/40975e0)) +* **language-service:** hybrid visitor returns parent node of BoundAttribute ([#38995](https://github.com/angular/angular/issues/38995)) ([323be39](https://github.com/angular/angular/commit/323be39)) +* **packaging:** remove polyfills needed to run tests on IE9 and IE 10 ([#38931](https://github.com/angular/angular/issues/38931)) ([4ca1c73](https://github.com/angular/angular/commit/4ca1c73)) +* **platform-webworker:** remove platform-webworker and platform-webworker-dynamic ([#38846](https://github.com/angular/angular/issues/38846)) ([93c3d8f](https://github.com/angular/angular/commit/93c3d8f)) +* **router:** make relativeLinkResolution corrected by default ([#25609](https://github.com/angular/angular/issues/25609)) ([837889f](https://github.com/angular/angular/commit/837889f)), closes [#22394](https://github.com/angular/angular/issues/22394) + + +### Code Refactoring + +* **router:** Adjust type of parameter in navigateByUrl and createUrlTree to be more accurate ([#38227](https://github.com/angular/angular/issues/38227)) ([e4f4d18](https://github.com/angular/angular/commit/e4f4d18)), closes [#18798](https://github.com/angular/angular/issues/18798) ### Features -* **common:** add ReadonlyMap in place of Map in keyValuePipe ([#37311](https://github.com/angular/angular/issues/37311)) ([3373453](https://github.com/angular/angular/commit/3373453)), closes [#37308](https://github.com/angular/angular/issues/37308) -* **forms:** AbstractControl to store raw validators in addition to combined validators function ([#37881](https://github.com/angular/angular/issues/37881)) ([ad7046b](https://github.com/angular/angular/commit/ad7046b)) -* **localize:** allow duplicate messages to be handled during extraction ([#38082](https://github.com/angular/angular/issues/38082)) ([cf9a47b](https://github.com/angular/angular/commit/cf9a47b)), closes [#38077](https://github.com/angular/angular/issues/38077) +* **common:** stricter types for DatePipe ([#37447](https://github.com/angular/angular/issues/37447)) ([daf8b7f](https://github.com/angular/angular/commit/daf8b7f)) +* **common:** stricter types for number pipes ([#37447](https://github.com/angular/angular/issues/37447)) ([7b2aac9](https://github.com/angular/angular/commit/7b2aac9)) +* **compiler:** Add keySpan to Variable Node ([#38965](https://github.com/angular/angular/issues/38965)) ([239968d](https://github.com/angular/angular/commit/239968d)) +* **router:** Add `relativeLinkResolution` migration to update default value ([#38698](https://github.com/angular/angular/issues/38698)) ([15ea811](https://github.com/angular/angular/commit/15ea811)) +### BREAKING CHANGES + +* **packaging:** In v10, IE 9, 10, and IE mobile support was deprecated. In v11, Angular framework removes IE 9, +10, and IE mobile support completely. +Supporting outdated browsers like these increases bundle size, code complexity, and test load, +and also requires time and effort that could be spent on improvements to the framework. +For example, fixing issues can be more difficult, as a straightforward fix for modern browsers +could break old ones that have quirks due to not receiving updates from vendors. +* **platform-webworker:** @angular/platform-webworker and @angular/platform-webworker-dynamic +have been removed as they were deprecated in v8 +* **common:** The `slice` pipe now returns `null` for the `undefined` input value, +which is consistent with the behavior of most pipes. If you rely on +`undefined` being the result in that case, you now need to check for it +explicitly. +* **common:** The typing of the `keyvalue` pipe has been fixed to report that for +input objects that have `number` keys, the result will contain the +string representation of the keys. This was already the case and the +code has simply been updated to reflect this. Please update the +consumers of the pipe output if they were relying on the incorrect +types. Note that this does not affect use cases where the input values +are `Map`s, so if you need to preserve `number`s, this is an effective +way. +* **common:** The signatures of the number pipes now explicitly state which types are +accepted. This should only cause issues in corner cases, as any other +values would result in runtime exceptions. +* **common:** The signature of the `date` pipe now explicitly states which types are +accepted. This should only cause issues in corner cases, as any other +values would result in runtime exceptions. +* **common:** The async pipe no longer claims to return `undefined` for an input that +was typed as `undefined`. Note that the code actually returned `null` on +`undefined` inputs. In the unlikely case you were relying on this, +please fix the typing of the consumers of the pipe output. +* **common:** The case conversion pipes no longer let falsy values through. They now +map both `null` and `undefined` to `null` and raise an exception on +invalid input (`0`, `false`, `NaN`) just like most "common pipes". If +your code required falsy values to pass through, you need to handle them +explicitly. +* **router:** While the new parameter types allow a variable of type +`NavigationExtras` to be passed in, they will not allow object literals, +as they may only specify known properties. They will also not accept +types that do not have properties in common with the ones in the `Pick`. +To fix this error, only specify properties from the `NavigationExtras` which are +actually used in the respective function calls or use a type assertion +on the object or variable: `as NavigationExtras`. +* **router:** This commit changes the default value of +`relativeLinkResolution` from `'legacy'` to `'default'`. If your +application previously used the default by not specifying a value in the +`ExtraOptions` and uses relative links when navigating from children of +empty path routes, you will need to update your `RouterModule` to +specifically specify `'legacy'` for `relativeLinkResolution`. +See https://angular.io/api/router/ExtraOptions#relativeLinkResolution +for more details. + + + + +## 10.1.4 (2020-09-30) + + +### Bug Fixes + +* **compiler-cli:** enable [@types](https://github.com/types) discovery in incremental rebuilds ([#39011](https://github.com/angular/angular/issues/39011)) ([6e99427](https://github.com/angular/angular/commit/6e99427)), closes [#38979](https://github.com/angular/angular/issues/38979) + + + + +# 11.0.0-next.3 (2020-09-23) + + +### Bug Fixes + +* **common:** add `params` and `reportProgress` options to `HttpClient.put()` overload ([#37873](https://github.com/angular/angular/issues/37873)) ([dd8d8c8](https://github.com/angular/angular/commit/dd8d8c8)), closes [#23600](https://github.com/angular/angular/issues/23600) +* **compiler-cli:** generate `let` statements in ES2015+ mode ([#38775](https://github.com/angular/angular/issues/38775)) ([123bff7](https://github.com/angular/angular/commit/123bff7)) +* **core:** ensure TestBed is not instantiated before override provider ([#38717](https://github.com/angular/angular/issues/38717)) ([c8f056b](https://github.com/angular/angular/commit/c8f056b)) +* **forms:** type NG_VALUE_ACCESSOR injection token as array ([#29723](https://github.com/angular/angular/issues/29723)) ([2b1b718](https://github.com/angular/angular/commit/2b1b718)), closes [#29351](https://github.com/angular/angular/issues/29351) - -## 10.0.5 (2020-07-22) + +### Features + +* **common:** Add ISO week-numbering year formats support to formatDate ([#38828](https://github.com/angular/angular/issues/38828)) ([984ed39](https://github.com/angular/angular/commit/984ed39)) +* **compiler:** Parse and recover on incomplete opening HTML tags ([#38681](https://github.com/angular/angular/issues/38681)) ([6ae3b68](https://github.com/angular/angular/commit/6ae3b68)), closes [#38596](https://github.com/angular/angular/issues/38596) +* **router:** add migration to update calls to navigateByUrl and createUrlTree with invalid parameters ([#38825](https://github.com/angular/angular/issues/38825)) ([7849fdd](https://github.com/angular/angular/commit/7849fdd)), closes [#38227](https://github.com/angular/angular/issues/38227) +* **service-worker:** add the option to prefer network for navigation requests ([#38565](https://github.com/angular/angular/issues/38565)) ([a206852](https://github.com/angular/angular/commit/a206852)), closes [#38194](https://github.com/angular/angular/issues/38194) + + +### BREAKING CHANGES + +* **core:** If you call `TestBed.overrideProvider` after TestBed initialization, provider overrides are not applied. This +behavior is consistent with other override methods (such as `TestBed.overrideDirective`, etc) but they +throw an error to indicate that, when the check was missing in the `TestBed.overrideProvider` function. +Now calling `TestBed.overrideProvider` after TestBed initialization also triggers an +error, thus there is a chance that some tests (where `TestBed.overrideProvider` is +called after TestBed initialization) will start to fail and require updates to move `TestBed.overrideProvider` calls +before TestBed initialization is completed. + + + + +## 10.1.3 (2020-09-23) ### Bug Fixes -* **compiler:** properly associate source spans for implicitly closed elements ([#38126](https://github.com/angular/angular/issues/38126)) ([e80278c](https://github.com/angular/angular/commit/e80278c)), closes [#36118](https://github.com/angular/angular/issues/36118) -* **compiler-cli:** ensure file_system handles mixed Windows drives ([#38030](https://github.com/angular/angular/issues/38030)) ([dba4023](https://github.com/angular/angular/commit/dba4023)), closes [#36777](https://github.com/angular/angular/issues/36777) -* **core:** Allow modification of lifecycle hooks any time before bootstrap ([#38119](https://github.com/angular/angular/issues/38119)) ([14b4718](https://github.com/angular/angular/commit/14b4718)), closes [#30497](https://github.com/angular/angular/issues/30497) -* **core:** error due to integer overflow when there are too many host bindings ([#38014](https://github.com/angular/angular/issues/38014)) ([7b6e73c](https://github.com/angular/angular/commit/7b6e73c)), closes [#37876](https://github.com/angular/angular/issues/37876) [#37876](https://github.com/angular/angular/issues/37876) -* **core:** incorrectly validating properties on ng-content and ng-container ([#37773](https://github.com/angular/angular/issues/37773)) ([17ddab9](https://github.com/angular/angular/commit/17ddab9)) +* **http:** Fix error message when we call jsonp without importing HttpClientJsonpModule ([#38756](https://github.com/angular/angular/issues/38756)) ([3902ec0](https://github.com/angular/angular/commit/3902ec0)) +* **ngcc:** fix compilation of `ChangeDetectorRef` in pipe constructors ([#38892](https://github.com/angular/angular/issues/38892)) ([093c3a1](https://github.com/angular/angular/commit/093c3a1)), closes [#38666](https://github.com/angular/angular/issues/38666) [#38883](https://github.com/angular/angular/issues/38883) +### Reverts - -## 10.0.4 (2020-07-15) +* feat(router): better warning message when a router outlet has not been instantiated ([#38920](https://github.com/angular/angular/issues/38920)) ([04d0aa6](https://github.com/angular/angular/commit/04d0aa6)) + + + + +# 11.0.0-next.2 (2020-09-16) ### Bug Fixes -* **bazel:** ng_module rule does not expose flat module information in Ivy ([#36971](https://github.com/angular/angular/issues/36971)) ([b76a2dc](https://github.com/angular/angular/commit/b76a2dc)) -* **compiler:** check more cases for pipe usage inside host bindings ([#37883](https://github.com/angular/angular/issues/37883)) ([a94383f](https://github.com/angular/angular/commit/a94383f)), closes [#34655](https://github.com/angular/angular/issues/34655) [#37610](https://github.com/angular/angular/issues/37610) -* **language-service:** non-existent module format in package output ([#37778](https://github.com/angular/angular/issues/37778)) ([12f1773](https://github.com/angular/angular/commit/12f1773)) -* **language-service:** remove completion for string ([#37983](https://github.com/angular/angular/issues/37983)) ([387e838](https://github.com/angular/angular/commit/387e838)) -* **ngcc:** report a warning if ngcc tries to use a solution-style tsconfig ([#38003](https://github.com/angular/angular/issues/38003)) ([e3b8010](https://github.com/angular/angular/commit/e3b8010)), closes [#36386](https://github.com/angular/angular/issues/36386) -* **service-worker:** correctly handle relative base href ([#37922](https://github.com/angular/angular/issues/37922)) ([b186db7](https://github.com/angular/angular/commit/b186db7)), closes [#25055](https://github.com/angular/angular/issues/25055) [#25055](https://github.com/angular/angular/issues/25055) -* **service-worker:** correctly serve `ngsw/state` with a non-root SW scope ([#37922](https://github.com/angular/angular/issues/37922)) ([dc42c97](https://github.com/angular/angular/commit/dc42c97)), closes [#30505](https://github.com/angular/angular/issues/30505) +* **common:** do not round up fractions of a millisecond in `DatePipe` ([#38009](https://github.com/angular/angular/issues/38009)) ([26f2820](https://github.com/angular/angular/commit/26f2820)), closes [/www.ecma-international.org/ecma-262/5.1/#sec-15](https://github.com//www.ecma-international.org/ecma-262/5.1//issues/sec-15) [#37989](https://github.com/angular/angular/issues/37989) +* **common:** mark locale data arrays as readonly ([#30397](https://github.com/angular/angular/issues/30397)) ([6acea54](https://github.com/angular/angular/commit/6acea54)), closes [#27003](https://github.com/angular/angular/issues/27003) +* **compiler:** source span for microsyntax text att should be key span ([#38766](https://github.com/angular/angular/issues/38766)) ([8f349b2](https://github.com/angular/angular/commit/8f349b2)) +* **router:** Fix arguments order for call to shouldReuseRoute ([#26949](https://github.com/angular/angular/issues/26949)) ([3817e5f](https://github.com/angular/angular/commit/3817e5f)), closes [#16192](https://github.com/angular/angular/issues/16192) [#16192](https://github.com/angular/angular/issues/16192) ### Features -* **bazel:** provide LinkablePackageInfo from ng_module ([#37778](https://github.com/angular/angular/issues/37778)) ([6cd10a1](https://github.com/angular/angular/commit/6cd10a1)), closes [/github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl#L144-L146](https://github.com//github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl/issues/L144-L146) +* **compiler-cli:** `TemplateTypeChecker` operation to get `Symbol` from a template node ([#38618](https://github.com/angular/angular/issues/38618)) ([c4556db](https://github.com/angular/angular/commit/c4556db)) +* **compiler-cli:** Add ability to get `Symbol` of `Template`s and `Element`s in component template ([#38618](https://github.com/angular/angular/issues/38618)) ([cf2e8b9](https://github.com/angular/angular/commit/cf2e8b9)) +* **compiler-cli:** Add ability to get `Symbol` of AST expression in component template ([#38618](https://github.com/angular/angular/issues/38618)) ([f56ece4](https://github.com/angular/angular/commit/f56ece4)) +* **compiler-cli:** add ability to get symbol of reference or variable ([#38618](https://github.com/angular/angular/issues/38618)) ([19598b4](https://github.com/angular/angular/commit/19598b4)) +* **compiler-cli:** define interfaces to be used for TemplateTypeChecker ([#38618](https://github.com/angular/angular/issues/38618)) ([9e77bd3](https://github.com/angular/angular/commit/9e77bd3)) + + +### Performance Improvements + +* **compiler-cli:** only emit directive/pipe references that are used ([#38539](https://github.com/angular/angular/issues/38539)) ([077f516](https://github.com/angular/angular/commit/077f516)) +* **compiler-cli:** optimize computation of type-check scope information ([#38539](https://github.com/angular/angular/issues/38539)) ([297c060](https://github.com/angular/angular/commit/297c060)) +* **router:** use `ngDevMode` to tree-shake error messages in router ([#38674](https://github.com/angular/angular/issues/38674)) ([db21c4f](https://github.com/angular/angular/commit/db21c4f)) + + +### BREAKING CHANGES + +* **router:** This change corrects the argument order when calling +RouteReuseStrategy#shouldReuseRoute. Previously, when evaluating child +routes, they would be called with the future and current arguments would +be swapped. If your RouteReuseStrategy relies specifically on only the future +or current snapshot state, you may need to update the shouldReuseRoute +implementation's use of "future" and "current" ActivateRouteSnapshots. +* **common:** The locale data API has been marked as returning readonly arrays, rather +than mutable arrays, since these arrays are shared across calls to the +API. If you were mutating them (e.g. calling `sort()`, `push()`, `splice()`, etc) +then your code will not longer compile. If you need to mutate the array, you +should now take a copy (e.g. by calling `slice()`) and mutate the copy. +* **common:** When passing a date-time formatted string to the `DatePipe` in a format that contains +fractions of a millisecond, the milliseconds will now always be rounded down rather than +to the nearest millisecond. + +Most applications will not be affected by this change. If this is not the desired behaviour +then consider pre-processing the string to round the millisecond part before passing +it to the `DatePipe`. + + + + +## 10.1.2 (2020-09-16) + + +### Bug Fixes + +* **compiler:** detect pipes in ICUs in template binder ([#38810](https://github.com/angular/angular/issues/38810)) ([ec2dbe7](https://github.com/angular/angular/commit/ec2dbe7)), closes [#38539](https://github.com/angular/angular/issues/38539) [#38539](https://github.com/angular/angular/issues/38539) [#38539](https://github.com/angular/angular/issues/38539) +* **core:** clear the `RefreshTransplantedView` when detached ([#38768](https://github.com/angular/angular/issues/38768)) ([edb7f90](https://github.com/angular/angular/commit/edb7f90)), closes [#38619](https://github.com/angular/angular/issues/38619) +* **localize:** ensure that `formatOptions` is optional ([#38787](https://github.com/angular/angular/issues/38787)) ([a47383d](https://github.com/angular/angular/commit/a47383d)) +* **router:** Ensure routes are processed in priority order and only if needed ([#38780](https://github.com/angular/angular/issues/38780)) ([9c51ba3](https://github.com/angular/angular/commit/9c51ba3)), closes [#38691](https://github.com/angular/angular/issues/38691) +* **upgrade:** add try/catch when downgrading injectables ([#38671](https://github.com/angular/angular/issues/38671)) ([5de2ac3](https://github.com/angular/angular/commit/5de2ac3)), closes [#37579](https://github.com/angular/angular/issues/37579) + + +### Performance Improvements + +* **compiler-cli:** only emit directive/pipe references that are used ([#38843](https://github.com/angular/angular/issues/38843)) ([5658405](https://github.com/angular/angular/commit/5658405)) +* **compiler-cli:** optimize computation of type-check scope information ([#38843](https://github.com/angular/angular/issues/38843)) ([ebede67](https://github.com/angular/angular/commit/ebede67)) +* **ngcc:** introduce cache for sharing data across entry-points ([#38840](https://github.com/angular/angular/issues/38840)) ([58411e7](https://github.com/angular/angular/commit/58411e7)) +* **ngcc:** reduce maximum worker count ([#38840](https://github.com/angular/angular/issues/38840)) ([ea36466](https://github.com/angular/angular/commit/ea36466)) + + + + +# 11.0.0-next.1 (2020-09-09) + + +### Bug Fixes + +* **compiler-cli:** compute source-mappings for localized strings ([#38645](https://github.com/angular/angular/issues/38645)) ([7e0b3fd](https://github.com/angular/angular/commit/7e0b3fd)), closes [#38588](https://github.com/angular/angular/issues/38588) +* **core:** remove CollectionChangeRecord symbol ([#38668](https://github.com/angular/angular/issues/38668)) ([fdea180](https://github.com/angular/angular/commit/fdea180)) +* **router:** support lazy loading for empty path named outlets ([#38379](https://github.com/angular/angular/issues/38379)) ([926ffcd](https://github.com/angular/angular/commit/926ffcd)), closes [#12842](https://github.com/angular/angular/issues/12842) + + +### BREAKING CHANGES + +* **core:** CollectionChangeRecord has been removed, use IterableChangeRecord +instead + + + + +## 10.1.1 (2020-09-09) + + +### Bug Fixes + +* **compiler:** correct confusion between field and property names ([#38685](https://github.com/angular/angular/issues/38685)) ([a1c34c6](https://github.com/angular/angular/commit/a1c34c6)) +* **compiler-cli:** compute source-mappings for localized strings ([#38747](https://github.com/angular/angular/issues/38747)) ([b4eb016](https://github.com/angular/angular/commit/b4eb016)), closes [#38588](https://github.com/angular/angular/issues/38588) +* **compiler-cli:** ensure that a declaration is available in type-to-value conversion ([#38684](https://github.com/angular/angular/issues/38684)) ([56d5ff2](https://github.com/angular/angular/commit/56d5ff2)), closes [#38670](https://github.com/angular/angular/issues/38670) +* **core:** reset `tView` between tests in Ivy TestBed ([#38659](https://github.com/angular/angular/issues/38659)) ([efc7606](https://github.com/angular/angular/commit/efc7606)), closes [#38600](https://github.com/angular/angular/issues/38600) +* **localize:** do not expose NodeJS typings in $localize runtime code ([#38700](https://github.com/angular/angular/issues/38700)) ([4de8dc3](https://github.com/angular/angular/commit/4de8dc3)), closes [#38692](https://github.com/angular/angular/issues/38692) +* **localize:** enable whitespace preservation marker in XLIFF files ([#38737](https://github.com/angular/angular/issues/38737)) ([190dca0](https://github.com/angular/angular/commit/190dca0)), closes [#38679](https://github.com/angular/angular/issues/38679) +* **localize:** install `[@angular](https://github.com/angular)/localize` in `devDependencies` by default ([#38680](https://github.com/angular/angular/issues/38680)) ([dbab744](https://github.com/angular/angular/commit/dbab744)), closes [#38329](https://github.com/angular/angular/issues/38329) +* **localize:** render context of translation file parse errors ([#38673](https://github.com/angular/angular/issues/38673)) ([32f33f0](https://github.com/angular/angular/commit/32f33f0)), closes [#38377](https://github.com/angular/angular/issues/38377) +* **localize:** render location in XLIFF 2 even if there is no metadata ([#38713](https://github.com/angular/angular/issues/38713)) ([ab4f953](https://github.com/angular/angular/commit/ab4f953)), closes [#38705](https://github.com/angular/angular/issues/38705) +* **ngcc:** use aliased exported types correctly ([#38666](https://github.com/angular/angular/issues/38666)) ([6a28675](https://github.com/angular/angular/commit/6a28675)), closes [#38238](https://github.com/angular/angular/issues/38238) +* **router:** If users are using the Alt key when clicking the router links, prioritize browser’s default behavior ([#38375](https://github.com/angular/angular/issues/38375)) ([309709d](https://github.com/angular/angular/commit/309709d)) + + +### Performance Improvements + +* **core:** use `ngDevMode` to tree-shake error messages ([#38612](https://github.com/angular/angular/issues/38612)) ([b084bff](https://github.com/angular/angular/commit/b084bff)) - -# 10.1.0-next.1 (2020-07-15) + + +# 11.0.0-next.0 (2020-09-02) ### Bug Fixes -* **bazel:** ng_module rule does not expose flat module information in Ivy ([#36971](https://github.com/angular/angular/issues/36971)) ([1550663](https://github.com/angular/angular/commit/1550663)) -* **compiler:** check more cases for pipe usage inside host bindings ([#37883](https://github.com/angular/angular/issues/37883)) ([9322b9a](https://github.com/angular/angular/commit/9322b9a)), closes [#34655](https://github.com/angular/angular/issues/34655) [#37610](https://github.com/angular/angular/issues/37610) -* **compiler-cli:** ensure file_system handles mixed Windows drives ([#37959](https://github.com/angular/angular/issues/37959)) ([6b31155](https://github.com/angular/angular/commit/6b31155)), closes [#36777](https://github.com/angular/angular/issues/36777) -* **language-service:** remove completion for string ([#37983](https://github.com/angular/angular/issues/37983)) ([10aba15](https://github.com/angular/angular/commit/10aba15)) -* **ngcc:** report a warning if ngcc tries to use a solution-style tsconfig ([#38003](https://github.com/angular/angular/issues/38003)) ([b358495](https://github.com/angular/angular/commit/b358495)), closes [#36386](https://github.com/angular/angular/issues/36386) -* **router:** ensure duplicate popstate/hashchange events are handled correctly ([#37674](https://github.com/angular/angular/issues/37674)) ([9185c6e](https://github.com/angular/angular/commit/9185c6e)), closes [/github.com/angular/angular/issues/16710#issuecomment-646919529](https://github.com//github.com/angular/angular/issues/16710/issues/issuecomment-646919529) [#16710](https://github.com/angular/angular/issues/16710) -* **service-worker:** correctly handle relative base href ([#37922](https://github.com/angular/angular/issues/37922)) ([d19ef65](https://github.com/angular/angular/commit/d19ef65)), closes [#25055](https://github.com/angular/angular/issues/25055) [#25055](https://github.com/angular/angular/issues/25055) -* **service-worker:** correctly serve `ngsw/state` with a non-root SW scope ([#37922](https://github.com/angular/angular/issues/37922)) ([2156bee](https://github.com/angular/angular/commit/2156bee)), closes [#30505](https://github.com/angular/angular/issues/30505) +* **forms:** ensure to emit `statusChanges` on subsequent value update/validations ([#38354](https://github.com/angular/angular/issues/38354)) ([d9fea85](https://github.com/angular/angular/commit/d9fea85)), closes [#20424](https://github.com/angular/angular/issues/20424) [#14542](https://github.com/angular/angular/issues/14542) +* **service-worker:** fix condition to check for a cache-busted request ([#36847](https://github.com/angular/angular/issues/36847)) ([5be4edf](https://github.com/angular/angular/commit/5be4edf)) + + +### Features + +* **service-worker:** add `UnrecoverableStateError` ([#36847](https://github.com/angular/angular/issues/36847)) ([036a2fa](https://github.com/angular/angular/commit/036a2fa)), closes [#36539](https://github.com/angular/angular/issues/36539) + + +### BREAKING CHANGES + +* **forms:** Previously if FormControl, FormGroup and FormArray class instances had async validators +defined at initialization time, the status change event was not emitted once async validator +completed. After this change the status event is emitted into the `statusChanges` observable. +If your code relies on the old behavior, you can filter/ignore this additional status change +event. - -# 10.1.0-next.0 (2020-07-08) + +# 10.1.0 (2020-09-02) + + +### Features + +* **bazel:** provide LinkablePackageInfo from ng_module ([#37623](https://github.com/angular/angular/issues/37623)) ([6898eab](https://github.com/angular/angular/commit/6898eab)) +* **common:** add ReadonlyMap in place of Map in keyValuePipe ([#37311](https://github.com/angular/angular/issues/37311)) ([3373453](https://github.com/angular/angular/commit/3373453)), closes [#37308](https://github.com/angular/angular/issues/37308) +* **compiler-cli:** add `SourceFile.getOriginalLocation()` to sourcemaps package ([#32912](https://github.com/angular/angular/issues/32912)) ([6abb8d0](https://github.com/angular/angular/commit/6abb8d0)) +* **compiler-cli:** Add compiler option to report errors when assigning to restricted input fields ([#38249](https://github.com/angular/angular/issues/38249)) ([71138f6](https://github.com/angular/angular/commit/71138f6)) +* **compiler-cli:** add support for TypeScript 4.0 ([#38076](https://github.com/angular/angular/issues/38076)) ([0fc44e0](https://github.com/angular/angular/commit/0fc44e0)) +* **compiler-cli:** explain why an expression cannot be used in AOT compilations ([#37587](https://github.com/angular/angular/issues/37587)) ([712f1bd](https://github.com/angular/angular/commit/712f1bd)) +* **compiler:** support unary operators for more accurate type checking ([#37918](https://github.com/angular/angular/issues/37918)) ([874792d](https://github.com/angular/angular/commit/874792d)), closes [#20845](https://github.com/angular/angular/issues/20845) [#36178](https://github.com/angular/angular/issues/36178) +* **core:** rename async to waitForAsync to avoid confusing ([#37583](https://github.com/angular/angular/issues/37583)) ([8f07429](https://github.com/angular/angular/commit/8f07429)) +* **core:** support injection token as predicate in queries ([#37506](https://github.com/angular/angular/issues/37506)) ([97dc85b](https://github.com/angular/angular/commit/97dc85b)), closes [#21152](https://github.com/angular/angular/issues/21152) [#36144](https://github.com/angular/angular/issues/36144) +* **core:** update reference and doc to change `async` to `waitAsync`. ([#37583](https://github.com/angular/angular/issues/37583)) ([8fbf40b](https://github.com/angular/angular/commit/8fbf40b)) +* **forms:** AbstractControl to store raw validators in addition to combined validators function ([#37881](https://github.com/angular/angular/issues/37881)) ([ad7046b](https://github.com/angular/angular/commit/ad7046b)) +* **localize:** allow duplicate messages to be handled during extraction ([#38082](https://github.com/angular/angular/issues/38082)) ([cf9a47b](https://github.com/angular/angular/commit/cf9a47b)), closes [#38077](https://github.com/angular/angular/issues/38077) +* **localize:** expose `canParse()` diagnostics ([#37909](https://github.com/angular/angular/issues/37909)) ([ec32eba](https://github.com/angular/angular/commit/ec32eba)), closes [#37901](https://github.com/angular/angular/issues/37901) +* **localize:** implement message extraction tool ([#32912](https://github.com/angular/angular/issues/32912)) ([190561d](https://github.com/angular/angular/commit/190561d)) +* **platform-browser:** Allow `sms`-URLs ([#31463](https://github.com/angular/angular/issues/31463)) ([fc5c34d](https://github.com/angular/angular/commit/fc5c34d)), closes [#31462](https://github.com/angular/angular/issues/31462) +* **platform-server:** add option for absolute URL HTTP support ([#37539](https://github.com/angular/angular/issues/37539)) ([d37049a](https://github.com/angular/angular/commit/d37049a)), closes [#37071](https://github.com/angular/angular/issues/37071) +* **router:** better warning message when a router outlet has not been instantiated ([#30246](https://github.com/angular/angular/issues/30246)) ([1609815](https://github.com/angular/angular/commit/1609815)) ### Bug Fixes +* **bazel:** fix integration test for bazel building ([#38629](https://github.com/angular/angular/issues/38629)) ([dd82f2f](https://github.com/angular/angular/commit/dd82f2f)) * **common:** date pipe gives wrong week number ([#37632](https://github.com/angular/angular/issues/37632)) ([ef1fb6d](https://github.com/angular/angular/commit/ef1fb6d)), closes [#33961](https://github.com/angular/angular/issues/33961) +* **common:** narrow `NgIf` context variables in template type checker ([#36627](https://github.com/angular/angular/issues/36627)) ([9c8bc4a](https://github.com/angular/angular/commit/9c8bc4a)) +* **compiler-cli:** avoid creating value expressions for symbols from type-only imports ([#37912](https://github.com/angular/angular/issues/37912)) ([18098d3](https://github.com/angular/angular/commit/18098d3)), closes [#37900](https://github.com/angular/angular/issues/37900) * **compiler-cli:** ensure source-maps can handle webpack:// protocol ([#32912](https://github.com/angular/angular/issues/32912)) ([decd95e](https://github.com/angular/angular/commit/decd95e)) * **compiler-cli:** only read source-map comment from last line ([#32912](https://github.com/angular/angular/issues/32912)) ([07a07e3](https://github.com/angular/angular/commit/07a07e3)) +* **compiler-cli:** type-check inputs that include undefined when there's coercion members ([#38273](https://github.com/angular/angular/issues/38273)) ([7525f3a](https://github.com/angular/angular/commit/7525f3a)) +* **compiler:** incorrectly inferring namespace for HTML nodes inside SVG ([#38477](https://github.com/angular/angular/issues/38477)) ([0dda97e](https://github.com/angular/angular/commit/0dda97e)), closes [#37218](https://github.com/angular/angular/issues/37218) +* **compiler:** mark `NgModuleFactory` construction as not side effectful ([#38147](https://github.com/angular/angular/issues/38147)) ([7f8c222](https://github.com/angular/angular/commit/7f8c222)) +* **core:** Allow modification of lifecycle hooks any time before bootstrap ([#35464](https://github.com/angular/angular/issues/35464)) ([737506e](https://github.com/angular/angular/commit/737506e)), closes [#30497](https://github.com/angular/angular/issues/30497) +* **core:** detect DI parameters in JIT mode for downleveled ES2015 classes ([#38463](https://github.com/angular/angular/issues/38463)) ([ca07da4](https://github.com/angular/angular/commit/ca07da4)), closes [#38453](https://github.com/angular/angular/issues/38453) * **core:** determine required DOMParser feature availability ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([c509243](https://github.com/angular/angular/commit/c509243)) * **core:** do not trigger CSP alert/report in Firefox and Chrome ([#36578](https://github.com/angular/angular/issues/36578)) ([#36578](https://github.com/angular/angular/issues/36578)) ([b950d46](https://github.com/angular/angular/commit/b950d46)), closes [#25214](https://github.com/angular/angular/issues/25214) +* **core:** move generated i18n statements to the `consts` field of ComponentDef ([#38404](https://github.com/angular/angular/issues/38404)) ([cb05c01](https://github.com/angular/angular/commit/cb05c01)) +* **elements:** run strategy methods in correct zone ([#37814](https://github.com/angular/angular/issues/37814)) ([8df888d](https://github.com/angular/angular/commit/8df888d)), closes [#24181](https://github.com/angular/angular/issues/24181) * **forms:** handle form groups/arrays own pending async validation ([#22575](https://github.com/angular/angular/issues/22575)) ([77b62a5](https://github.com/angular/angular/commit/77b62a5)), closes [#10064](https://github.com/angular/angular/issues/10064) * **language-service:** non-existent module format in package output ([#37623](https://github.com/angular/angular/issues/37623)) ([413a0fb](https://github.com/angular/angular/commit/413a0fb)) +* **localize:** ensure required XLIFF parameters are serialized ([#38575](https://github.com/angular/angular/issues/38575)) ([f0af387](https://github.com/angular/angular/commit/f0af387)), closes [#38570](https://github.com/angular/angular/issues/38570) +* **localize:** extract the correct message ids ([#38498](https://github.com/angular/angular/issues/38498)) ([ac461e1](https://github.com/angular/angular/commit/ac461e1)) +* **localize:** render ICU placeholders in extracted translation files ([#38484](https://github.com/angular/angular/issues/38484)) ([81c3e80](https://github.com/angular/angular/commit/81c3e80)) +* **localize:** render text of extracted placeholders ([#38536](https://github.com/angular/angular/issues/38536)) ([14e90be](https://github.com/angular/angular/commit/14e90be)) +* **ngcc:** detect synthesized delegate constructors for downleveled ES2015 classes ([#38463](https://github.com/angular/angular/issues/38463)) ([3b9c802](https://github.com/angular/angular/commit/3b9c802)), closes [#38453](https://github.com/angular/angular/issues/38453) [#38453](https://github.com/angular/angular/issues/38453) +* **router:** defer loading of wildcard module until needed ([#38348](https://github.com/angular/angular/issues/38348)) ([8f708b5](https://github.com/angular/angular/commit/8f708b5)), closes [#25494](https://github.com/angular/angular/issues/25494) * **router:** fix navigation ignoring logic to compare to the browser url ([#37716](https://github.com/angular/angular/issues/37716)) ([a5ffca0](https://github.com/angular/angular/commit/a5ffca0)), closes [#16710](https://github.com/angular/angular/issues/16710) [#13586](https://github.com/angular/angular/issues/13586) * **router:** properly compare array queryParams for equality ([#37709](https://github.com/angular/angular/issues/37709)) ([#37860](https://github.com/angular/angular/issues/37860)) ([1801d0c](https://github.com/angular/angular/commit/1801d0c)) * **router:** remove parenthesis for primary outlet segment after removing auxiliary outlet segment ([#24656](https://github.com/angular/angular/issues/24656)) ([#37163](https://github.com/angular/angular/issues/37163)) ([71f008f](https://github.com/angular/angular/commit/71f008f)) +* **router:** restore 'history.state' object for navigations coming from Angular router ([#28108](https://github.com/angular/angular/issues/28108)) ([#28176](https://github.com/angular/angular/issues/28176)) ([df76a20](https://github.com/angular/angular/commit/df76a20)) +### Code Refactoring +* **router:** export DefaultRouteReuseStrategy to Router public_api ([#31575](https://github.com/angular/angular/issues/31575)) ([ca79880](https://github.com/angular/angular/commit/ca79880)) -### Features -* **bazel:** provide LinkablePackageInfo from ng_module ([#37623](https://github.com/angular/angular/issues/37623)) ([6898eab](https://github.com/angular/angular/commit/6898eab)) -* **compiler-cli:** add `SourceFile.getOriginalLocation()` to sourcemaps package ([#32912](https://github.com/angular/angular/issues/32912)) ([6abb8d0](https://github.com/angular/angular/commit/6abb8d0)) -* **compiler-cli:** explain why an expression cannot be used in AOT compilations ([#37587](https://github.com/angular/angular/issues/37587)) ([712f1bd](https://github.com/angular/angular/commit/712f1bd)) -* **core:** support injection token as predicate in queries ([#37506](https://github.com/angular/angular/issues/37506)) ([97dc85b](https://github.com/angular/angular/commit/97dc85b)), closes [#21152](https://github.com/angular/angular/issues/21152) [#36144](https://github.com/angular/angular/issues/36144) -* **localize:** expose `canParse()` diagnostics ([#37909](https://github.com/angular/angular/issues/37909)) ([ec32eba](https://github.com/angular/angular/commit/ec32eba)), closes [#37901](https://github.com/angular/angular/issues/37901) -* **localize:** implement message extraction tool ([#32912](https://github.com/angular/angular/issues/32912)) ([190561d](https://github.com/angular/angular/commit/190561d)) -* **platform-browser:** Allow `sms`-URLs ([#31463](https://github.com/angular/angular/issues/31463)) ([fc5c34d](https://github.com/angular/angular/commit/fc5c34d)), closes [#31462](https://github.com/angular/angular/issues/31462) -* **platform-server:** add option for absolute URL HTTP support ([#37539](https://github.com/angular/angular/issues/37539)) ([d37049a](https://github.com/angular/angular/commit/d37049a)), closes [#37071](https://github.com/angular/angular/issues/37071) ### Performance Improvements - +* **compiler-cli:** don't emit template guards when child scope is empty ([#38418](https://github.com/angular/angular/issues/38418)) ([1388c17](https://github.com/angular/angular/commit/1388c17)) * **compiler-cli:** fix regressions in incremental program reuse ([#37641](https://github.com/angular/angular/issues/37641)) ([5103d90](https://github.com/angular/angular/commit/5103d90)) +* **compiler-cli:** only generate directive declarations when used ([#38418](https://github.com/angular/angular/issues/38418)) ([fb8f4b4](https://github.com/angular/angular/commit/fb8f4b4)) +* **compiler-cli:** only generate type-check code for referenced DOM elements ([#38418](https://github.com/angular/angular/issues/38418)) ([f42e6ce](https://github.com/angular/angular/commit/f42e6ce)) +* **forms:** use internal `ngDevMode` flag to tree-shake error messages in prod builds ([#37821](https://github.com/angular/angular/issues/37821)) ([201a546](https://github.com/angular/angular/commit/201a546)), closes [#37697](https://github.com/angular/angular/issues/37697) * **ngcc:** shortcircuit tokenizing in ESM dependency host ([#37639](https://github.com/angular/angular/issues/37639)) ([bd7f440](https://github.com/angular/angular/commit/bd7f440)) * **ngcc:** use `EntryPointManifest` to speed up noop `ProgramBaseEntryPointFinder` ([#37665](https://github.com/angular/angular/issues/37665)) ([9318e23](https://github.com/angular/angular/commit/9318e23)) * **router:** apply prioritizedGuardValue operator to optimize CanLoad guards ([#37523](https://github.com/angular/angular/issues/37523)) ([d7dd295](https://github.com/angular/angular/commit/d7dd295)) + +## 10.0.14 (2020-08-26) + + + +## 10.0.12 (2020-08-24) + + +### Bug Fixes + +* **compiler-cli:** adding references to const enums in runtime code ([#38542](https://github.com/angular/angular/issues/38542)) ([814b436](https://github.com/angular/angular/commit/814b436)), closes [#38513](https://github.com/angular/angular/issues/38513) +* **core:** remove closing body tag from inert DOM builder ([#38454](https://github.com/angular/angular/issues/38454)) ([5528536](https://github.com/angular/angular/commit/5528536)) +* **localize:** include the last placeholder in parsed translation text ([#38452](https://github.com/angular/angular/issues/38452)) ([57d1a48](https://github.com/angular/angular/commit/57d1a48)) +* **localize:** parse all parts of a translation with nested HTML ([#38452](https://github.com/angular/angular/issues/38452)) ([07b99f5](https://github.com/angular/angular/commit/07b99f5)), closes [#38422](https://github.com/angular/angular/issues/38422) + + +### Features + +* **language-service:** introduce hybrid visitor to locate AST node ([#38540](https://github.com/angular/angular/issues/38540)) ([66d8c22](https://github.com/angular/angular/commit/66d8c22)) + + + +## 10.0.11 (2020-08-19) + + +### Bug Fixes + +* **router:** ensure routerLinkActive updates when associated routerLinks change (resubmit of [#38349](https://github.com/angular/angular/issues/38349)) ([#38511](https://github.com/angular/angular/issues/38511)) ([0af9533](https://github.com/angular/angular/commit/0af9533)), closes [#18469](https://github.com/angular/angular/issues/18469) + + + + +## 10.0.10 (2020-08-17) + + +### Bug Fixes + +* **common:** Allow scrolling when browser supports scrollTo ([#38468](https://github.com/angular/angular/issues/38468)) ([b32126c](https://github.com/angular/angular/commit/b32126c)), closes [#30630](https://github.com/angular/angular/issues/30630) +* **core:** detect DI parameters in JIT mode for downleveled ES2015 classes ([#38500](https://github.com/angular/angular/issues/38500)) ([863acb6](https://github.com/angular/angular/commit/863acb6)), closes [#38453](https://github.com/angular/angular/issues/38453) +* **core:** error if CSS custom property in host binding has number in name ([#38432](https://github.com/angular/angular/issues/38432)) ([cb83b8a](https://github.com/angular/angular/commit/cb83b8a)), closes [#37292](https://github.com/angular/angular/issues/37292) +* **core:** fix multiple nested views removal from ViewContainerRef ([#38317](https://github.com/angular/angular/issues/38317)) ([d5e09f4](https://github.com/angular/angular/commit/d5e09f4)), closes [#38201](https://github.com/angular/angular/issues/38201) +* **ngcc:** detect synthesized delegate constructors for downleveled ES2015 classes ([#38500](https://github.com/angular/angular/issues/38500)) ([f3dd6c2](https://github.com/angular/angular/commit/f3dd6c2)), closes [#38453](https://github.com/angular/angular/issues/38453) [#38453](https://github.com/angular/angular/issues/38453) +* **router:** ensure routerLinkActive updates when associated routerLinks change ([#38349](https://github.com/angular/angular/issues/38349)) ([989e8a1](https://github.com/angular/angular/commit/989e8a1)), closes [#18469](https://github.com/angular/angular/issues/18469) + + + + +## 10.0.9 (2020-08-12) + + +### Bug Fixes + +* **common:** ensure scrollRestoration is writable ([#30630](https://github.com/angular/angular/issues/30630)) ([#38357](https://github.com/angular/angular/issues/38357)) ([58f4b3a](https://github.com/angular/angular/commit/58f4b3a)), closes [#30629](https://github.com/angular/angular/issues/30629) +* **compiler:** evaluate safe navigation expressions in correct binding order ([#37911](https://github.com/angular/angular/issues/37911)) ([f5b9d87](https://github.com/angular/angular/commit/f5b9d87)), closes [#37194](https://github.com/angular/angular/issues/37194) +* **compiler-cli:** avoid creating value expressions for symbols from type-only imports ([#38415](https://github.com/angular/angular/issues/38415)) ([ca2b4bc](https://github.com/angular/angular/commit/ca2b4bc)), closes [#37912](https://github.com/angular/angular/issues/37912) +* **compiler-cli:** infer quote expressions as any type in type checker ([#37917](https://github.com/angular/angular/issues/37917)) ([5b87c67](https://github.com/angular/angular/commit/5b87c67)), closes [#36568](https://github.com/angular/angular/issues/36568) +* **compiler-cli:** mark eager `NgModuleFactory` construction as not side effectful ([#38320](https://github.com/angular/angular/issues/38320)) ([016a41b](https://github.com/angular/angular/commit/016a41b)), closes [#38147](https://github.com/angular/angular/issues/38147) +* **compiler-cli:** match wrapHost parameter types within plugin interface ([#38004](https://github.com/angular/angular/issues/38004)) ([df01a82](https://github.com/angular/angular/commit/df01a82)) +* **compiler-cli:** preserve quotes in class member names ([#38387](https://github.com/angular/angular/issues/38387)) ([c9acb7b](https://github.com/angular/angular/commit/c9acb7b)), closes [#38311](https://github.com/angular/angular/issues/38311) +* **core:** prevent NgModule scope being overwritten in JIT compiler ([#37795](https://github.com/angular/angular/issues/37795)) ([3acebdc](https://github.com/angular/angular/commit/3acebdc)), closes [#37105](https://github.com/angular/angular/issues/37105) +* **core:** queries not matching string injection tokens ([#38321](https://github.com/angular/angular/issues/38321)) ([32109dc](https://github.com/angular/angular/commit/32109dc)), closes [#38313](https://github.com/angular/angular/issues/38313) [#38315](https://github.com/angular/angular/issues/38315) +* **core:** Store the currently selected ICU in `LView` ([#38345](https://github.com/angular/angular/issues/38345)) ([ee5123f](https://github.com/angular/angular/commit/ee5123f)) +* **platform-server:** remove styles added by ServerStylesHost on destruction ([#38367](https://github.com/angular/angular/issues/38367)) ([7f11149](https://github.com/angular/angular/commit/7f11149)) +* **router:** prevent calling unsubscribe on undefined subscription in RouterPreloader ([#38344](https://github.com/angular/angular/issues/38344)) ([4151314](https://github.com/angular/angular/commit/4151314)) +* **service-worker:** fix the chrome debugger syntax highlighter ([#38332](https://github.com/angular/angular/issues/38332)) ([f5d5bac](https://github.com/angular/angular/commit/f5d5bac)) + + + +## 10.0.8 (2020-08-04) + + +### Bug Fixes + +* **compiler:** add PURE annotation to getInheritedFactory calls ([#38291](https://github.com/angular/angular/issues/38291)) ([03d8e31](https://github.com/angular/angular/commit/03d8e31)) +* **compiler:** update unparsable character reference entity error messages ([#38319](https://github.com/angular/angular/issues/38319)) ([cea4678](https://github.com/angular/angular/commit/cea4678)), closes [#26067](https://github.com/angular/angular/issues/26067) + + + + +## 10.0.7 (2020-07-30) + + +### Bug Fixes + +* **compiler:** Metadata should not include methods on Object.prototype ([#38292](https://github.com/angular/angular/issues/38292)) ([879ff08](https://github.com/angular/angular/commit/879ff08)) + + + + +## 10.0.6 (2020-07-28) + + +### Bug Fixes + +* **compiler:** share identical stylesheets between components in the same file ([#38213](https://github.com/angular/angular/issues/38213)) ([264950b](https://github.com/angular/angular/commit/264950b)), closes [#38204](https://github.com/angular/angular/issues/38204) +* **compiler-cli:** Add support for string literal class members ([#38226](https://github.com/angular/angular/issues/38226)) ([b1e7775](https://github.com/angular/angular/commit/b1e7775)) +* **core:** `Attribute` decorator `attributeName` is mandatory ([#38131](https://github.com/angular/angular/issues/38131)) ([1c4fcce](https://github.com/angular/angular/commit/1c4fcce)), closes [#32658](https://github.com/angular/angular/issues/32658) +* **core:** unify the signature between ngZone and noopZone ([#37581](https://github.com/angular/angular/issues/37581)) ([d5264f5](https://github.com/angular/angular/commit/d5264f5)) + + + + +## 10.0.5 (2020-07-22) + + +### Bug Fixes + +* **compiler:** properly associate source spans for implicitly closed elements ([#38126](https://github.com/angular/angular/issues/38126)) ([e80278c](https://github.com/angular/angular/commit/e80278c)), closes [#36118](https://github.com/angular/angular/issues/36118) +* **compiler-cli:** ensure file_system handles mixed Windows drives ([#38030](https://github.com/angular/angular/issues/38030)) ([dba4023](https://github.com/angular/angular/commit/dba4023)), closes [#36777](https://github.com/angular/angular/issues/36777) +* **core:** Allow modification of lifecycle hooks any time before bootstrap ([#38119](https://github.com/angular/angular/issues/38119)) ([14b4718](https://github.com/angular/angular/commit/14b4718)), closes [#30497](https://github.com/angular/angular/issues/30497) +* **core:** error due to integer overflow when there are too many host bindings ([#38014](https://github.com/angular/angular/issues/38014)) ([7b6e73c](https://github.com/angular/angular/commit/7b6e73c)), closes [#37876](https://github.com/angular/angular/issues/37876) [#37876](https://github.com/angular/angular/issues/37876) +* **core:** incorrectly validating properties on ng-content and ng-container ([#37773](https://github.com/angular/angular/issues/37773)) ([17ddab9](https://github.com/angular/angular/commit/17ddab9)) + + + + +## 10.0.4 (2020-07-15) + + +### Bug Fixes + +* **bazel:** ng_module rule does not expose flat module information in Ivy ([#36971](https://github.com/angular/angular/issues/36971)) ([b76a2dc](https://github.com/angular/angular/commit/b76a2dc)) +* **compiler:** check more cases for pipe usage inside host bindings ([#37883](https://github.com/angular/angular/issues/37883)) ([a94383f](https://github.com/angular/angular/commit/a94383f)), closes [#34655](https://github.com/angular/angular/issues/34655) [#37610](https://github.com/angular/angular/issues/37610) +* **language-service:** non-existent module format in package output ([#37778](https://github.com/angular/angular/issues/37778)) ([12f1773](https://github.com/angular/angular/commit/12f1773)) +* **language-service:** remove completion for string ([#37983](https://github.com/angular/angular/issues/37983)) ([387e838](https://github.com/angular/angular/commit/387e838)) +* **ngcc:** report a warning if ngcc tries to use a solution-style tsconfig ([#38003](https://github.com/angular/angular/issues/38003)) ([e3b8010](https://github.com/angular/angular/commit/e3b8010)), closes [#36386](https://github.com/angular/angular/issues/36386) +* **service-worker:** correctly handle relative base href ([#37922](https://github.com/angular/angular/issues/37922)) ([b186db7](https://github.com/angular/angular/commit/b186db7)), closes [#25055](https://github.com/angular/angular/issues/25055) [#25055](https://github.com/angular/angular/issues/25055) +* **service-worker:** correctly serve `ngsw/state` with a non-root SW scope ([#37922](https://github.com/angular/angular/issues/37922)) ([dc42c97](https://github.com/angular/angular/commit/dc42c97)), closes [#30505](https://github.com/angular/angular/issues/30505) + + +### Features + +* **bazel:** provide LinkablePackageInfo from ng_module ([#37778](https://github.com/angular/angular/issues/37778)) ([6cd10a1](https://github.com/angular/angular/commit/6cd10a1)), closes [/github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl#L144-L146](https://github.com//github.com/bazelbuild/rules_nodejs/blob/9a5de3728b05bf1647bbb87ad99f54e626604705/internal/linker/link_node_modules.bzl/issues/L144-L146) + + ## 10.0.3 (2020-07-08) @@ -447,12 +952,12 @@ https://github.com/microsoft/TypeScript/issues/38374 for more information and updates. If you used Closure Compiler with Angular in the past, you will likely -be better off consuming Angular packages built from sources directly +be better off consuming Angular packages built from sources directly rather than consuming the version we publish on npm, which is primarily optimized for Webpack/Rollup + Terser build pipeline. As a temporary workaround, you might consider using your current build -pipeline with Closure flag `--compilation_level=SIMPLE`. This flag +pipeline with Closure flag `--compilation_level=SIMPLE`. This flag will ensure that your build pipeline produces buildable and runnable artifacts, at the cost of increased payload size due to advanced optimizations being disabled. @@ -460,17 +965,17 @@ advanced optimizations being disabled. If you were affected by this change, please help us understand your needs by leaving a comment on https://github.com/angular/angular/issues/37234. -* **core:** make generic mandatory for ModuleWithProviders +* **core:** make generic mandatory for ModuleWithProviders A generic type parameter has always been required for the `ModuleWithProviders` pattern to work with Ivy, but prior to this commit, View Engine allowed the generic type to be omitted (though support was officially deprecated). -If you're using `ModuleWithProviders` without a generic type in your application code, a v10 migration will update your code for you. +If you're using `ModuleWithProviders` without a generic type in your application code, a v10 migration will update your code for you. However, if you are using View Engine and also depending on a library that omits the generic type, you will now get a build time error similar to: ``` error TS2314: Generic type 'ModuleWithProviders' requires 1 type argument(s). ``` - + In this case, ngcc won't help you (because it's Ivy-only) and the migration only covers application code. You should contact the library author to fix their library to provide a type parameter when they use this class. @@ -1798,7 +2303,7 @@ API surface going forward. * **core:** Injector.get now accepts abstract classes to return type-safe values. Previous implementation returned `any` through the deprecated implementation. -* Angular now compiles with Ivy by default ([#32219](https://github.com/angular/angular/issues/32219)) ([ec4381d](https://github.com/angular/angular/commit/ec4381d)). +* Angular now compiles with Ivy by default ([#32219](https://github.com/angular/angular/issues/32219)) ([ec4381d](https://github.com/angular/angular/commit/ec4381d)). If you aren't familiar with Ivy, read our [blog post about the Ivy preview](https://blog.angular.io/its-time-for-the-compatibility-opt-in-preview-of-ivy-38f3542a282f?gi=8bfeb44b05c) and see the list of changes [here](https://docs.google.com/document/d/1Dije0AsJ0PxL3NaeNPxpYDeapj30b_QC0xfeIvIIzgg/preview). diff --git a/WORKSPACE b/WORKSPACE index 291208ba84589..7054692cfbda9 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -8,8 +8,8 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # Fetch rules_nodejs so we can install our npm dependencies http_archive( name = "build_bazel_rules_nodejs", - sha256 = "84abf7ac4234a70924628baa9a73a5a5cbad944c4358cf9abdb4aab29c9a5b77", - urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/1.7.0/rules_nodejs-1.7.0.tar.gz"], + sha256 = "4952ef879704ab4ad6729a29007e7094aef213ea79e9f2e94cbe1c9a753e63ef", + urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/2.2.0/rules_nodejs-2.2.0.tar.gz"], ) # Check the rules_nodejs version and download npm dependencies @@ -17,7 +17,7 @@ http_archive( # assert on that. load("@build_bazel_rules_nodejs//:index.bzl", "check_rules_nodejs_version", "node_repositories", "yarn_install") -check_rules_nodejs_version(minimum_version_string = "1.7.0") +check_rules_nodejs_version(minimum_version_string = "2.2.0") # Setup the Node.js toolchain node_repositories( @@ -39,23 +39,18 @@ yarn_install( yarn_lock = "//:yarn.lock", ) -# Install all bazel dependencies of the @npm npm packages -load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies") - -install_bazel_dependencies() - # Load angular dependencies load("//packages/bazel:package.bzl", "rules_angular_dev_dependencies") rules_angular_dev_dependencies() # Load protractor dependencies -load("@npm_bazel_protractor//:package.bzl", "npm_bazel_protractor_dependencies") +load("@npm//@bazel/protractor:package.bzl", "npm_bazel_protractor_dependencies") npm_bazel_protractor_dependencies() # Load karma dependencies -load("@npm_bazel_karma//:package.bzl", "npm_bazel_karma_dependencies") +load("@npm//@bazel/karma:package.bzl", "npm_bazel_karma_dependencies") npm_bazel_karma_dependencies() @@ -68,11 +63,6 @@ load("//dev-infra/browsers:browser_repositories.bzl", "browser_repositories") browser_repositories() -# Setup the rules_typescript tooolchain -load("@npm_bazel_typescript//:index.bzl", "ts_setup_workspace") - -ts_setup_workspace() - # Setup the rules_sass toolchain load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories") @@ -91,14 +81,14 @@ rbe_autoconfig( # Need to specify a base container digest in order to ensure that we can use the checked-in # platform configurations for the "ubuntu16_04" image. Otherwise the autoconfig rule would # need to pull the image and run it in order determine the toolchain configuration. See: - # https://github.com/bazelbuild/bazel-toolchains/blob/3.2.0/configs/ubuntu16_04_clang/versions.bzl - base_container_digest = "sha256:5e750dd878df9fcf4e185c6f52b9826090f6e532b097f286913a428290622332", + # https://github.com/bazelbuild/bazel-toolchains/blob/3.6.0/configs/ubuntu16_04_clang/versions.bzl + base_container_digest = "sha256:f6568d8168b14aafd1b707019927a63c2d37113a03bcee188218f99bd0327ea1", # Note that if you change the `digest`, you might also need to update the # `base_container_digest` to make sure marketplace.gcr.io/google/rbe-ubuntu16-04-webtest: # and marketplace.gcr.io/google/rbe-ubuntu16-04: have # the same Clang and JDK installed. Clang is needed because of the dependency on # @com_google_protobuf. Java is needed for the Bazel's test executor Java tool. - digest = "sha256:f743114235a43355bf8324e2ba0fa6a597236fe06f7bc99aaa9ac703631c306b", + digest = "sha256:dddaaddbe07a61c2517f9b08c4977fc23c4968fcb6c0b8b5971e955d2de7a961", env = clang_env(), registry = "marketplace.gcr.io", # We can't use the default "ubuntu16_04" RBE image provided by the autoconfig because we need diff --git a/aio/README.md b/aio/README.md index 88177f89a6a74..3c8c851496551 100644 --- a/aio/README.md +++ b/aio/README.md @@ -6,6 +6,7 @@ Todo en esta carpeta es parte del proyecto de documentación. Esto incluye: * La configuración de dgeni para convertir los archivos de origen a archivos renderizados que se pueden vizualizar en el sitio web. * Las herramientas para establecer ejemplos para el desarrollo; y generar archivos en tiempo real y archivos zip desde los ejemplos. + ## Tareas de desarrollador Nosotros usamos [Yarn](https://yarnpkg.com) para gestionar las dependencias y crear tareas de compilación. @@ -35,8 +36,9 @@ Aquí están las tareas más importantes que podrías necesitar usar: * `yarn boilerplate:add` - generar todo el código boilerplate para los ejemplos, para que puedan ejecutarse localmente. * `yarn boilerplate:add:viewengine` - igual que `boilerplate:add` pero también enciende el modo `ViewEngine` (pre-Ivy). - * `yarn boilerplate:remove` - eliminar todo el código boilerplate que fue añadido a través`yarn boilerplate:add`. +* `yarn create-example` - crear un nuevo directorio de ejemplo que contenga los archivos fuente iniciales. + * `yarn generate-stackblitz` - generar los archivos stackblitz que están usados por la etiqueta `live-example` en documentos. * `yarn generate-zips` - generar los archivos zip desde los ejemplos. Zip está disponible a través de la etiqueta `live-example` en los documentos. diff --git a/aio/aio-builds-setup/dockerbuild/scripts-js/lib/verify-setup/mock-external-apis.ts b/aio/aio-builds-setup/dockerbuild/scripts-js/lib/verify-setup/mock-external-apis.ts index 34875e22a0eb0..d32cee96bf10b 100644 --- a/aio/aio-builds-setup/dockerbuild/scripts-js/lib/verify-setup/mock-external-apis.ts +++ b/aio/aio-builds-setup/dockerbuild/scripts-js/lib/verify-setup/mock-external-apis.ts @@ -16,13 +16,6 @@ import {BuildNums, PrNums, SHA} from './constants'; const logger = new Logger('mock-external-apis'); -const log = (...args: any[]) => { - // Filter out non-matching URL checks - if (!/^matching.+: false$/.test(args[0])) { - logger.log(...args); - } -}; - const AIO_CIRCLE_CI_TOKEN = getEnvVar('AIO_CIRCLE_CI_TOKEN'); const AIO_GITHUB_TOKEN = getEnvVar('AIO_GITHUB_TOKEN'); @@ -91,8 +84,8 @@ const createArchive = (buildNum: number, prNum: number, sha: string) => { }; // Create request scopes -const circleCiApi = nock(CIRCLE_CI_API_HOST).log(log).persist(); -const githubApi = nock(GITHUB_API_HOST).log(log).persist().matchHeader('Authorization', `token ${AIO_GITHUB_TOKEN}`); +const circleCiApi = nock(CIRCLE_CI_API_HOST).persist(); +const githubApi = nock(GITHUB_API_HOST).persist().matchHeader('Authorization', `token ${AIO_GITHUB_TOKEN}`); ////////////////////////////// diff --git a/aio/aio-builds-setup/dockerbuild/scripts-js/package.json b/aio/aio-builds-setup/dockerbuild/scripts-js/package.json index 3d1533b926125..1f42dbc4ebf52 100644 --- a/aio/aio-builds-setup/dockerbuild/scripts-js/package.json +++ b/aio/aio-builds-setup/dockerbuild/scripts-js/package.json @@ -27,28 +27,28 @@ "body-parser": "^1.19.0", "delete-empty": "^3.0.0", "express": "^4.17.1", - "jasmine": "^3.5.0", - "nock": "^12.0.3", - "node-fetch": "^2.6.0", + "jasmine": "^3.6.1", + "nock": "^13.0.4", + "node-fetch": "^2.6.1", "shelljs": "^0.8.4", "source-map-support": "^0.5.19", - "tar-stream": "^2.1.2", - "tslib": "^1.11.1" + "tar-stream": "^2.1.3", + "tslib": "^2.0.1" }, "devDependencies": { "@types/body-parser": "^1.19.0", - "@types/express": "^4.17.6", - "@types/jasmine": "^3.5.10", + "@types/express": "^4.17.8", + "@types/jasmine": "^3.5.14", "@types/nock": "^11.1.0", - "@types/node": "^13.13.2", + "@types/node": "^14.6.4", "@types/node-fetch": "^2.5.7", - "@types/shelljs": "^0.8.7", - "@types/supertest": "^2.0.8", - "nodemon": "^2.0.3", + "@types/shelljs": "^0.8.8", + "@types/supertest": "^2.0.10", + "nodemon": "^2.0.4", "npm-run-all": "^4.1.5", "supertest": "^4.0.2", - "tslint": "^6.1.1", + "tslint": "^6.1.3", "tslint-jasmine-noSkipOrFocus": "^1.0.9", - "typescript": "^3.8.3" + "typescript": "^4.0.2" } } diff --git a/aio/aio-builds-setup/dockerbuild/scripts-js/test/common/github-api.spec.ts b/aio/aio-builds-setup/dockerbuild/scripts-js/test/common/github-api.spec.ts index 61df1ad4b77ab..71af2f379a4d2 100644 --- a/aio/aio-builds-setup/dockerbuild/scripts-js/test/common/github-api.spec.ts +++ b/aio/aio-builds-setup/dockerbuild/scripts-js/test/common/github-api.spec.ts @@ -214,23 +214,24 @@ describe('GithubApi', () => { }); - it('should call \'https.request()\' with the correct options', () => { + it('should call \'https.request()\' with the correct options', async () => { const requestHandler = nock('https://api.github.com') .intercept('/path', 'method') .reply(200); - (api as any).request('method', '/path'); + await (api as any).request('method', '/path'); requestHandler.done(); }); - it('should add the \'Authorization\' header containing the \'githubToken\'', () => { + it('should add the \'Authorization\' header containing the \'githubToken\'', async () => { const requestHandler = nock('https://api.github.com') .intercept('/path', 'method', undefined, { reqheaders: {Authorization: 'token 12345'}, }) .reply(200); - (api as any).request('method', '/path'); + + await (api as any).request('method', '/path'); requestHandler.done(); }); @@ -244,12 +245,13 @@ describe('GithubApi', () => { }); - it('should \'JSON.stringify\' and send the data along with the request', () => { + it('should \'JSON.stringify\' and send the data along with the request', async () => { const data = {key: 'value'}; const requestHandler = nock('https://api.github.com') .intercept('/path', 'method', JSON.stringify(data)) .reply(200); - (api as any).request('method', '/path', data); + + await (api as any).request('method', '/path', data); requestHandler.done(); }); diff --git a/aio/aio-builds-setup/dockerbuild/scripts-js/yarn.lock b/aio/aio-builds-setup/dockerbuild/scripts-js/yarn.lock index ac21400c64a0e..01b93fcb31c9a 100644 --- a/aio/aio-builds-setup/dockerbuild/scripts-js/yarn.lock +++ b/aio/aio-builds-setup/dockerbuild/scripts-js/yarn.lock @@ -23,6 +23,19 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@mrmlnc/readdir-enhanced@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" + integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g== + dependencies: + call-me-maybe "^1.0.1" + glob-to-regexp "^0.3.0" + +"@nodelib/fs.stat@^1.1.2": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" + integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== + "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -69,10 +82,10 @@ "@types/node" "*" "@types/range-parser" "*" -"@types/express@^4.17.6": - version "4.17.6" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.6.tgz#6bce49e49570507b86ea1b07b806f04697fac45e" - integrity sha512-n/mr9tZI83kd4azlPG5y997C/M4DNABK9yErhFM6hKdym4kkmd9j0vtsJyjFIwfRBxtrxZtAfGZCNRIBMFLK5w== +"@types/express@^4.17.8": + version "4.17.8" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.8.tgz#3df4293293317e61c60137d273a2e96cd8d5f27a" + integrity sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ== dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "*" @@ -86,10 +99,10 @@ "@types/minimatch" "*" "@types/node" "*" -"@types/jasmine@^3.5.10": - version "3.5.10" - resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.5.10.tgz#a1a41012012b5da9d4b205ba9eba58f6cce2ab7b" - integrity sha512-3F8qpwBAiVc5+HPJeXJpbrl+XjawGmciN5LgiO7Gv1pl1RHtjoMNqZpqEksaPJW05ViKe8snYInRs6xB25Xdew== +"@types/jasmine@^3.5.14": + version "3.5.14" + resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.5.14.tgz#f41a14e8ffa939062a71cf9722e5ee7d4e1f94af" + integrity sha512-Fkgk536sHPqcOtd+Ow+WiUNuk0TSo/BntKkF8wSvcd6M2FvPjeXcUE6Oz/bwDZiUZEaXLslAgw00Q94Pnx6T4w== "@types/mime@*": version "1.3.0" @@ -118,10 +131,10 @@ version "7.0.31" resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.31.tgz#80ea4d175599b2a00149c29a10a4eb2dff592e86" -"@types/node@^13.13.2": - version "13.13.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.2.tgz#160d82623610db590a64e8ca81784e11117e5a54" - integrity sha512-LB2R1Oyhpg8gu4SON/mfforE525+Hi/M1ineICEDftqNVTyFg1aRIeGuTvXAoWHc4nbrFncWtJgMmoyRvuGh7A== +"@types/node@^14.6.4": + version "14.6.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.4.tgz#a145cc0bb14ef9c4777361b7bbafa5cf8e3acb5a" + integrity sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ== "@types/qs@*": version "6.9.1" @@ -140,10 +153,10 @@ "@types/express-serve-static-core" "*" "@types/mime" "*" -"@types/shelljs@^0.8.7": - version "0.8.7" - resolved "https://registry.yarnpkg.com/@types/shelljs/-/shelljs-0.8.7.tgz#a2a606b185165abadf8b7995fea5e326e637088e" - integrity sha512-Mg2qGjLIJIieeJ1/NjswAOY9qXDShLeh6JwpD1NZsvUvI0hxdUCNDpnBXv9YQeugKi2EHU+BqkbUE4jpY4GKmQ== +"@types/shelljs@^0.8.8": + version "0.8.8" + resolved "https://registry.yarnpkg.com/@types/shelljs/-/shelljs-0.8.8.tgz#e439c69929b88a2c8123c1a55e09eb708315addf" + integrity sha512-lD3LWdg6j8r0VRBFahJVaxoW0SIcswxKaFUrmKl33RJVeeoNYQAz4uqCJ5Z6v4oIBOsC5GozX+I5SorIKiTcQA== dependencies: "@types/glob" "*" "@types/node" "*" @@ -154,10 +167,10 @@ dependencies: "@types/node" "*" -"@types/supertest@^2.0.8": - version "2.0.8" - resolved "https://registry.yarnpkg.com/@types/supertest/-/supertest-2.0.8.tgz#23801236e2b85204ed771a8e7c40febba7da2bda" - integrity sha512-wcax7/ip4XSSJRLbNzEIUVy2xjcBIZZAuSd2vtltQfRK7kxhx5WMHbLHkYdxN3wuQCrwpYrg86/9byDjPXoGMA== +"@types/supertest@^2.0.10": + version "2.0.10" + resolved "https://registry.yarnpkg.com/@types/supertest/-/supertest-2.0.10.tgz#630d79b4d82c73e043e43ff777a9ca98d457cab7" + integrity sha512-Xt8TbEyZTnD5Xulw95GLMOkmjGICrOQyJ2jqgkSjAUR3mm7pAIzSR0NFBaMcwlzVvlpCjNwbATcWWwjNiZiFrQ== dependencies: "@types/superagent" "*" @@ -223,6 +236,21 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + array-filter@~0.0.0: version "0.0.1" resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" @@ -239,10 +267,25 @@ array-reduce@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -252,6 +295,19 @@ base64-js@^1.0.2: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + binary-extensions@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" @@ -303,6 +359,22 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -331,6 +403,21 @@ bytes@3.1.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + cacheable-request@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" @@ -344,6 +431,11 @@ cacheable-request@^6.0.0: normalize-url "^4.1.0" responselike "^1.0.2" +call-me-maybe@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" + integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= + camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" @@ -394,6 +486,16 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + cli-boxes@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d" @@ -406,6 +508,14 @@ clone-response@^1.0.2: dependencies: mimic-response "^1.0.0" +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + color-convert@^1.9.0: version "1.9.2" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147" @@ -449,6 +559,11 @@ component-emitter@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -489,6 +604,11 @@ cookiejar@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -509,7 +629,7 @@ crypto-random-string@^2.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== -debug@2.6.9: +debug@2.6.9, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: @@ -541,6 +661,11 @@ debug@^4.1.0: dependencies: ms "^2.1.1" +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" @@ -563,6 +688,28 @@ define-properties@^1.1.2: dependencies: object-keys "^1.0.12" +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -671,6 +818,19 @@ etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + express@^4.17.1: version "4.17.1" resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" @@ -707,10 +867,61 @@ express@^4.17.1: utils-merge "1.0.1" vary "~1.1.2" +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + extend@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +fast-glob@^2.2.6: + version "2.2.7" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" + integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw== + dependencies: + "@mrmlnc/readdir-enhanced" "^2.2.1" + "@nodelib/fs.stat" "^1.1.2" + glob-parent "^3.1.0" + is-glob "^4.0.0" + merge2 "^1.2.3" + micromatch "^3.1.10" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -731,6 +942,11 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + form-data@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" @@ -757,6 +973,13 @@ forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" @@ -792,6 +1015,19 @@ get-stream@^5.1.0: dependencies: pump "^3.0.0" +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + glob-parent@~5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" @@ -799,6 +1035,11 @@ glob-parent@~5.1.0: dependencies: is-glob "^4.0.1" +glob-to-regexp@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" + integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= + glob@^7.0.0, glob@^7.0.5, glob@^7.1.1: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" @@ -810,18 +1051,6 @@ glob@^7.0.0, glob@^7.0.5, glob@^7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.4: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - global-dirs@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.0.1.tgz#acdf3bb6685bcd55cb35e8a052266569e9469201" @@ -859,6 +1088,37 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + has-yarn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" @@ -958,6 +1218,20 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -969,6 +1243,11 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + is-builtin-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" @@ -986,11 +1265,55 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + is-date-object@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" -is-extglob@^2.1.1: +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -1003,7 +1326,14 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-glob@^4.0.1, is-glob@~4.0.1: +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== @@ -1023,6 +1353,13 @@ is-npm@^4.0.0: resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d" integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig== +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -1038,6 +1375,13 @@ is-path-inside@^3.0.1: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg== +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + is-regex@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" @@ -1053,12 +1397,17 @@ is-typedarray@^1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + is-yarn-global@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== -isarray@~1.0.0: +isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -1066,18 +1415,30 @@ isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" -jasmine-core@~3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.5.0.tgz#132c23e645af96d85c8bca13c8758b18429fc1e4" - integrity sha512-nCeAiw37MIMA9w9IXso7bRaLl+c/ef3wnxsoSAlYrzS+Ot0zTG6nU8G/cIfGkqpkjX2wNaIW9RFG0TwIFnG6bA== +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" -jasmine@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-3.5.0.tgz#7101eabfd043a1fc82ac24e0ab6ec56081357f9e" - integrity sha512-DYypSryORqzsGoMazemIHUfMkXM7I7easFaxAvNM3Mr6Xz3Fy36TupTrAOxZWN8MVKEU5xECv22J4tUQf3uBzQ== +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +jasmine-core@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.6.0.tgz#491f3bb23941799c353ceb7a45b38a950ebc5a20" + integrity sha512-8uQYa7zJN8hq9z+g8z1bqCfdC8eoDAeVnM5sfqs7KHv9/ifoJ500m018fpFc7RDaO6SWCLCXwo/wPSNcdYTgcw== + +jasmine@^3.6.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-3.6.1.tgz#a20456b309a669b547a3c24bb2120f16f70cfc65" + integrity sha512-Jqp8P6ZWkTVFGmJwBK46p+kJNrZCdqkQ4GL+PGuBXZwK1fM4ST9BizkYgIwCFqYYqnTizAy6+XG2Ej5dFrej9Q== dependencies: - glob "^7.1.4" - jasmine-core "~3.5.0" + fast-glob "^2.2.6" + jasmine-core "~3.6.0" js-tokens@^4.0.0: version "4.0.0" @@ -1116,6 +1477,30 @@ keyv@^3.0.0: dependencies: json-buffer "3.0.0" +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + latest-version@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" @@ -1132,6 +1517,11 @@ load-json-file@^4.0.0: pify "^3.0.0" strip-bom "^3.0.0" +lodash.set@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" + integrity sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM= + lodash@^4.17.13: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" @@ -1158,6 +1548,18 @@ make-dir@^3.0.0: dependencies: semver "^6.0.0" +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -1170,10 +1572,34 @@ merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" +merge2@^1.2.3: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + methods@^1.1.1, methods@^1.1.2, methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" +micromatch@^3.1.10: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + mime-db@1.44.0: version "1.44.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" @@ -1220,6 +1646,14 @@ minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + mkdirp@^0.5.3: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" @@ -1241,6 +1675,23 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" @@ -1250,7 +1701,7 @@ nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" -nock@*, nock@^12.0.3: +nock@*: version "12.0.3" resolved "https://registry.yarnpkg.com/nock/-/nock-12.0.3.tgz#83f25076dbc4c9aa82b5cdf54c9604c7a778d1c9" integrity sha512-QNb/j8kbFnKCiyqi9C5DD0jH/FubFGj5rt9NQFONXwQm3IPB0CULECg/eS3AU1KgZb/6SwUa4/DTRKhVxkGABw== @@ -1260,15 +1711,25 @@ nock@*, nock@^12.0.3: lodash "^4.17.13" propagate "^2.0.0" -node-fetch@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" - integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== +nock@^13.0.4: + version "13.0.4" + resolved "https://registry.yarnpkg.com/nock/-/nock-13.0.4.tgz#9fb74db35d0aa056322e3c45be14b99105cd7510" + integrity sha512-alqTV8Qt7TUbc74x1pKRLSENzfjp4nywovcJgi/1aXDiUxXdt7TkruSTF5MDWPP7UoPVgea4F9ghVdmX0xxnSA== + dependencies: + debug "^4.1.0" + json-stringify-safe "^5.0.1" + lodash.set "^4.3.2" + propagate "^2.0.0" + +node-fetch@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== -nodemon@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.3.tgz#e9c64df8740ceaef1cb00e1f3da57c0a93ef3714" - integrity sha512-lLQLPS90Lqwc99IHe0U94rDgvjo+G9I4uEIxRG3evSLROcqQ9hwc0AxlSHKS4T1JW/IMj/7N5mthiN58NL/5kw== +nodemon@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.4.tgz#55b09319eb488d6394aa9818148c0c2d1c04c416" + integrity sha512-Ltced+hIfTmaS28Zjv1BM552oQ3dbwPqI4+zI0SLgq+wpJhSyqgYude/aZa/3i31VCQWMfXJVxvu86abcam3uQ== dependencies: chokidar "^3.2.2" debug "^3.2.6" @@ -1321,10 +1782,33 @@ npm-run-all@^4.1.5: shell-quote "^1.6.1" string.prototype.padend "^3.0.0" +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + object-keys@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" @@ -1364,6 +1848,16 @@ parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -1405,6 +1899,11 @@ pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + prepend-http@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" @@ -1525,6 +2024,14 @@ rechoir@^0.6.2: dependencies: resolve "^1.1.6" +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + registry-auth-token@^4.0.0: version "4.1.1" resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.1.1.tgz#40a33be1e82539460f94328b0f7f0f84c16d9479" @@ -1539,6 +2046,21 @@ registry-url@^5.0.0: dependencies: rc "^1.2.8" +repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + resolve@^1.1.6: version "1.3.3" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5" @@ -1558,6 +2080,11 @@ responselike@^1.0.2: dependencies: lowercase-keys "^1.0.0" +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + rimraf@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" @@ -1579,6 +2106,13 @@ safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + "safer-buffer@>= 2.1.2 < 3": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -1641,6 +2175,16 @@ serve-static@1.14.1: parseurl "~1.3.3" send "0.17.1" +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + setprototypeof@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" @@ -1679,6 +2223,47 @@ signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + source-map-support@^0.5.19: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" @@ -1687,6 +2272,16 @@ source-map-support@^0.5.19: buffer-from "^1.0.0" source-map "^0.6.0" +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + source-map@^0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" @@ -1713,10 +2308,25 @@ spdx-license-ids@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + "statuses@>= 1.5.0 < 2", statuses@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" @@ -1822,10 +2432,10 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -tar-stream@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.2.tgz#6d5ef1a7e5783a95ff70b69b97455a5968dc1325" - integrity sha512-UaF6FoJ32WqALZGOIAApXx+OdxhekNMChu6axLJR85zMMjXKWFGjbIRe+J6P4UnRGg9rAwWvbTT0oI7hD/Un7Q== +tar-stream@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.3.tgz#1e2022559221b7866161660f118255e20fa79e41" + integrity sha512-Z9yri56Dih8IaK8gncVPx4Wqt86NDmQTSh49XLZgjWpGZL9GK9HKParS2scqHCC4w6X9Gh2jwaU45V47XTKwVA== dependencies: bl "^4.0.1" end-of-stream "^1.4.1" @@ -1838,11 +2448,26 @@ term-size@^2.1.0: resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.0.tgz#1f16adedfe9bdc18800e1776821734086fcc6753" integrity sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw== +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + to-readable-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -1850,6 +2475,16 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + toidentifier@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" @@ -1861,15 +2496,20 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -tslib@^1.10.0, tslib@^1.11.1: - version "1.11.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" - integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== +tslib@^1.13.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" + integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== tslib@^1.8.1: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" +tslib@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e" + integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ== + tslint-jasmine-noSkipOrFocus@^1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/tslint-jasmine-noSkipOrFocus/-/tslint-jasmine-noSkipOrFocus-1.0.9.tgz#a562d3a6b3aa5c51e5ad29211a6eeb06ad1a082f" @@ -1877,10 +2517,10 @@ tslint-jasmine-noSkipOrFocus@^1.0.9: dependencies: rimraf "^2.6.1" -tslint@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.1.tgz#ac03fbd17f85bfefaae348b353b25a88efe10cde" - integrity sha512-kd6AQ/IgPRpLn6g5TozqzPdGNZ0q0jtXW4//hRcj10qLYBaa3mTUU2y2MCG+RXZm8Zx+KZi0eA+YCrMyNlF4UA== +tslint@^6.1.3: + version "6.1.3" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.3.tgz#5c23b2eccc32487d5523bd3a470e9aa31789d904" + integrity sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg== dependencies: "@babel/code-frame" "^7.0.0" builtin-modules "^1.1.1" @@ -1893,7 +2533,7 @@ tslint@^6.1.1: mkdirp "^0.5.3" resolve "^1.3.2" semver "^5.3.0" - tslib "^1.10.0" + tslib "^1.13.0" tsutils "^2.29.0" tsutils@^2.29.0: @@ -1923,10 +2563,10 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typescript@^3.8.3: - version "3.8.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061" - integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w== +typescript@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.2.tgz#7ea7c88777c723c681e33bf7988be5d008d05ac2" + integrity sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ== undefsafe@^2.0.2: version "2.0.2" @@ -1934,6 +2574,16 @@ undefsafe@^2.0.2: dependencies: debug "^2.2.0" +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + unique-string@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" @@ -1945,6 +2595,14 @@ unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + update-notifier@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.0.tgz#4866b98c3bc5b5473c020b1250583628f9a328f3" @@ -1964,6 +2622,11 @@ update-notifier@^4.0.0: semver-diff "^3.1.1" xdg-basedir "^4.0.0" +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" @@ -1971,6 +2634,11 @@ url-parse-lax@^3.0.0: dependencies: prepend-http "^2.0.0" +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" diff --git a/aio/aio-builds-setup/docs/image-config--environment-variables.md b/aio/aio-builds-setup/docs/image-config--environment-variables.md index 43ba7e70a542b..8d380ff70d108 100644 --- a/aio/aio-builds-setup/docs/image-config--environment-variables.md +++ b/aio/aio-builds-setup/docs/image-config--environment-variables.md @@ -22,7 +22,7 @@ you don't need to specify values for those. The domain name of the server. - `AIO_GITHUB_ORGANIZATION`: - The GitHub organization whose teams are whitelisted for accepting build artifacts. + The GitHub organization whose teams are trusted for accepting build artifacts. See also `AIO_GITHUB_TEAM_SLUGS`. - `AIO_GITHUB_REPO`: diff --git a/aio/aio-builds-setup/docs/overview--security-model.md b/aio/aio-builds-setup/docs/overview--security-model.md index 453ad412b9ff1..c26f2c1a3568b 100644 --- a/aio/aio-builds-setup/docs/overview--security-model.md +++ b/aio/aio-builds-setup/docs/overview--security-model.md @@ -98,7 +98,7 @@ This section describes how each of the aforementioned sub-tasks is accomplished: Such a label can only have been added by a maintainer (with the necessary rights) and designates that they have manually verified the PR contents. 2. We can verify (again using the GitHub API) the author's membership in one of the - whitelisted/trusted GitHub teams. For this operation, we need a Personal Access Token with the + trusted GitHub teams. For this operation, we need a Personal Access Token with the `read:org` scope issued by a user that can "see" the specified GitHub organization. Here too, we use the token by @mary-poppins. diff --git a/aio/content/examples/.gitignore b/aio/content/examples/.gitignore index 75300b0bdd5d0..6d98f0cc41e0a 100644 --- a/aio/content/examples/.gitignore +++ b/aio/content/examples/.gitignore @@ -17,6 +17,7 @@ **/e2e/tsconfig.e2e.json **/src/karma.conf.js **/.angular-cli.json +**/.browserslistrc **/.editorconfig **/.gitignore **/angular.json @@ -30,8 +31,9 @@ **/tslint.json **/karma-test-shim.js **/browser-test-shim.js -**/browserslist **/node_modules +**/yarn.lock +**/package-lock.json # built files *.map diff --git a/aio/content/examples/accessibility/e2e/src/app.e2e-spec.ts b/aio/content/examples/accessibility/e2e/src/app.e2e-spec.ts index f1bf72fb8f522..7da554198d197 100644 --- a/aio/content/examples/accessibility/e2e/src/app.e2e-spec.ts +++ b/aio/content/examples/accessibility/e2e/src/app.e2e-spec.ts @@ -12,7 +12,7 @@ describe('Accessibility example e2e tests', () => { it('should take a number and change progressbar width', () => { element(by.css('input')).sendKeys('16'); - expect(element(by.css('input')).getAttribute('value')).toEqual('016'); + expect(element(by.css('input')).getAttribute('value')).toEqual('16'); expect(element(by.css('app-example-progressbar div')).getCssValue('width')).toBe('48px'); }); diff --git a/aio/content/examples/accessibility/src/app/app.component.html b/aio/content/examples/accessibility/src/app/app.component.html index 4869298570260..eac0b319c10f6 100755 --- a/aio/content/examples/accessibility/src/app/app.component.html +++ b/aio/content/examples/accessibility/src/app/app.component.html @@ -3,7 +3,7 @@

Accessibility Example

diff --git a/aio/content/examples/accessibility/src/app/app.component.ts b/aio/content/examples/accessibility/src/app/app.component.ts index dd635acc9c14a..d9e6d230c9d16 100755 --- a/aio/content/examples/accessibility/src/app/app.component.ts +++ b/aio/content/examples/accessibility/src/app/app.component.ts @@ -7,4 +7,8 @@ import { Component } from '@angular/core'; }) export class AppComponent { progress = 0; + + setProgress($event: Event) { + this.progress = +($event.target as HTMLInputElement).value; + } } diff --git a/aio/content/examples/attribute-binding/src/app/app.component.html b/aio/content/examples/attribute-binding/src/app/app.component.html index 69f82857fdb43..7514b871c1cb7 100644 --- a/aio/content/examples/attribute-binding/src/app/app.component.html +++ b/aio/content/examples/attribute-binding/src/app/app.component.html @@ -3,8 +3,10 @@

Attribute, class, and style bindings

Attribute binding

+ +

Basic specificity

- -
Some text.
+ +
Some text.
- -
Some text.
+ +
Some text.

Source specificity

- +Some text. - +Some text.

Dynamic vs static

- -
Some text.
+ +
Some text.
- -
Some text.
+ +
Some text.
diff --git a/aio/content/examples/attribute-binding/src/app/app.component.ts b/aio/content/examples/attribute-binding/src/app/app.component.ts index ab35bb09a02f7..57c9f28718cb8 100644 --- a/aio/content/examples/attribute-binding/src/app/app.component.ts +++ b/aio/content/examples/attribute-binding/src/app/app.component.ts @@ -9,7 +9,7 @@ export class AppComponent { actionName = 'Go for it'; isSpecial = true; canSave = true; - classExpr = 'special clearance'; - styleExpr = 'color: red'; + classExpression = 'special clearance'; + styleExpression = 'color: red'; color = 'blue'; } diff --git a/aio/content/examples/attribute-binding/src/app/comp-with-host-binding.component.ts b/aio/content/examples/attribute-binding/src/app/comp-with-host-binding.component.ts index b93c478f6b2ff..b604e44454b74 100644 --- a/aio/content/examples/attribute-binding/src/app/comp-with-host-binding.component.ts +++ b/aio/content/examples/attribute-binding/src/app/comp-with-host-binding.component.ts @@ -11,6 +11,9 @@ export class CompWithHostBindingComponent { @HostBinding('style.color') color = 'green'; + // #docregion hostbinding @HostBinding('style.width') width = '200px'; + // #enddocregion hostbinding + } diff --git a/aio/content/examples/bootstrapping/src/app/app.module.ts b/aio/content/examples/bootstrapping/src/app/app.module.ts index 9b8a4fcaef0b2..3059978a826e9 100644 --- a/aio/content/examples/bootstrapping/src/app/app.module.ts +++ b/aio/content/examples/bootstrapping/src/app/app.module.ts @@ -21,11 +21,13 @@ import { ItemDirective } from './item.directive'; ItemDirective ], // #enddocregion declarations + // #docregion imports imports: [ BrowserModule, FormsModule, HttpClientModule ], + // #enddocregion imports providers: [], bootstrap: [AppComponent] }) diff --git a/aio/content/examples/comparing-observables/e2e/src/app.e2e-spec.ts b/aio/content/examples/comparing-observables/e2e/src/app.e2e-spec.ts new file mode 100644 index 0000000000000..ac89f882d0a62 --- /dev/null +++ b/aio/content/examples/comparing-observables/e2e/src/app.e2e-spec.ts @@ -0,0 +1,9 @@ +/* + * This example project is special in that it is not a cli app. To run tests appropriate for this + * project, the test command is overwritten in `aio/content/examples/observables/example-config.json`. + * + * This is an empty placeholder file to ensure that `aio/tools/examples/run-example-e2e.js` runs + * tests for this project. + * + * TODO: Fix our infrastructure/tooling, so that this hack is not necessary. + */ diff --git a/aio/content/examples/comparing-observables/example-config.json b/aio/content/examples/comparing-observables/example-config.json new file mode 100644 index 0000000000000..3aa2059b4d004 --- /dev/null +++ b/aio/content/examples/comparing-observables/example-config.json @@ -0,0 +1,12 @@ +{ + "tests": [ + { + "cmd": "yarn", + "args": ["tsc", "--project", "tsconfig.spec.json", "--module", "commonjs"] + }, + { + "cmd": "yarn", + "args": ["jasmine", "out-tsc/**/*.spec.js"] + } + ] +} diff --git a/aio/content/examples/comparing-observables/src/observables.spec.ts b/aio/content/examples/comparing-observables/src/observables.spec.ts new file mode 100644 index 0000000000000..e27ee9ced1a20 --- /dev/null +++ b/aio/content/examples/comparing-observables/src/observables.spec.ts @@ -0,0 +1,26 @@ +import { docRegionChain, docRegionObservable, docRegionUnsubscribe } from './observables'; + +describe('observables', () => { + it('should print 2', (doneFn: DoneFn) => { + const consoleLogSpy = spyOn(console, 'log'); + const observable = docRegionObservable(console); + observable.subscribe(() => { + expect(consoleLogSpy).toHaveBeenCalledTimes(1); + expect(consoleLogSpy).toHaveBeenCalledWith(2); + doneFn(); + }); + }); + + it('should close the subscription', () => { + const subscription = docRegionUnsubscribe(); + expect(subscription.closed).toBeTruthy(); + }); + + it('should chain an observable', (doneFn: DoneFn) => { + const observable = docRegionChain(); + observable.subscribe(value => { + expect(value).toBe(4); + doneFn(); + }); + }); +}); diff --git a/aio/content/examples/comparing-observables/src/observables.ts b/aio/content/examples/comparing-observables/src/observables.ts index f0e8c1a138f87..ffa1777279180 100644 --- a/aio/content/examples/comparing-observables/src/observables.ts +++ b/aio/content/examples/comparing-observables/src/observables.ts @@ -1,40 +1,72 @@ -import { map } from 'rxjs/operators'; +// #docplaster + import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; -// #docregion observable +export function docRegionObservable(console: Console) { + // #docregion observable -// declare a publishing operation -const observable = new Observable(observer => { - // Subscriber fn... -}); + // declare a publishing operation + const observable = new Observable(observer => { + // Subscriber fn... + // #enddocregion observable + // The below code is used for unit testing only + observer.next(2); + // #docregion observable + }); -// initiate execution -observable.subscribe(() => { - // observer handles notifications -}); + // initiate execution + observable.subscribe(value => { + // observer handles notifications + // #enddocregion observable + // The below code is used for unit testing only + console.log(value); + // #docregion observable + }); -// #enddocregion observable + // #enddocregion observable + return observable; +} -// #docregion unsubscribe +export function docRegionUnsubscribe() { + const observable = new Observable(() => { + // Subscriber fn... + }); + // #docregion unsubscribe -const subscription = observable.subscribe(() => { - // observer handles notifications -}); + const subscription = observable.subscribe(() => { + // observer handles notifications + }); -subscription.unsubscribe(); + subscription.unsubscribe(); -// #enddocregion unsubscribe + // #enddocregion unsubscribe + return subscription; +} -// #docregion error +export function docRegionError() { + const observable = new Observable(() => { + // Subscriber fn... + }); -observable.subscribe(() => { - throw Error('my error'); -}); + // #docregion error + observable.subscribe(() => { + throw new Error('my error'); + }); + // #enddocregion error +} -// #enddocregion error +export function docRegionChain() { + let observable = new Observable(observer => { + // Subscriber fn... + observer.next(2); + }); -// #docregion chain + observable = + // #docregion chain -observable.pipe(map(v => 2 * v)); + observable.pipe(map(v => 2 * v)); -// #enddocregion chain + // #enddocregion chain + return observable; +} diff --git a/aio/content/examples/comparing-observables/src/promises.spec.ts b/aio/content/examples/comparing-observables/src/promises.spec.ts new file mode 100644 index 0000000000000..9d10092f1dc23 --- /dev/null +++ b/aio/content/examples/comparing-observables/src/promises.spec.ts @@ -0,0 +1,23 @@ +import { docRegionError, docRegionPromise } from './promises'; + +describe('promises', () => { + it('should print 2', (doneFn: DoneFn) => { + const consoleLogSpy = spyOn(console, 'log'); + const pr = docRegionPromise(console, 2); + pr.then((value) => { + expect(consoleLogSpy).toHaveBeenCalledTimes(1); + expect(consoleLogSpy).toHaveBeenCalledWith(2); + expect(value).toBe(4); + doneFn(); + }); + }); + + it('should throw an error', (doneFn: DoneFn) => { + const promise = docRegionError(); + promise + .then(() => { + throw new Error('Promise should be rejected.'); + }, + () => doneFn()); + }); +}); diff --git a/aio/content/examples/comparing-observables/src/promises.ts b/aio/content/examples/comparing-observables/src/promises.ts index 0ad68d99dafa4..d24bba12ae4f6 100644 --- a/aio/content/examples/comparing-observables/src/promises.ts +++ b/aio/content/examples/comparing-observables/src/promises.ts @@ -1,25 +1,44 @@ -// #docregion promise -// initiate execution -const promise = new Promise((resolve, reject) => { - // Executer fn... -}); - -promise.then(value => { - // handle result here -}); - -// #enddocregion promise - -// #docregion chain - -promise.then(v => 2 * v); - -// #enddocregion chain - -// #docregion error - -promise.then(() => { - throw Error('my error'); -}); - -// #enddocregion error +// #docplaster + +export function docRegionPromise(console: Console, inputValue: number) { + // #docregion promise + // initiate execution + let promise = new Promise((resolve, reject) => { + // Executer fn... + // #enddocregion promise + // The below is used in the unit tests. + resolve(inputValue); + // #docregion promise + }); + // #enddocregion promise + promise = + // #docregion promise + promise.then(value => { + // handle result here + // #enddocregion promise + // The below is used in the unit tests. + console.log(value); + return value; + // #docregion promise + }); + // #enddocregion promise + promise = + // #docregion chain + promise.then(v => 2 * v); + // #enddocregion chain + + return promise; +} + +export function docRegionError() { + let promise = Promise.resolve(); + promise = + // #docregion error + + promise.then(() => { + throw new Error('my error'); + }); + + // #enddocregion error + return promise; +} diff --git a/aio/content/examples/component-interaction/e2e/src/app.e2e-spec.ts b/aio/content/examples/component-interaction/e2e/src/app.e2e-spec.ts index 903691f898312..d5727cc70c64a 100644 --- a/aio/content/examples/component-interaction/e2e/src/app.e2e-spec.ts +++ b/aio/content/examples/component-interaction/e2e/src/app.e2e-spec.ts @@ -1,12 +1,8 @@ -import { browser, element, by } from 'protractor'; +import { browser, by, element } from 'protractor'; describe('Component Communication Cookbook Tests', () => { - // Note: '?e2e' which app can read to know it is running in protractor - // e.g. `if (!/e2e/.test(location.search)) { ...` - beforeAll(() => { - browser.get('?e2e'); - }); + beforeEach(() => browser.get(browser.baseUrl)); describe('Parent-to-child communication', () => { // #docregion parent-to-child @@ -15,7 +11,7 @@ describe('Component Communication Cookbook Tests', () => { const masterName = 'Master'; it('should pass properties to children properly', () => { - const parent = element.all(by.tagName('app-hero-parent')).get(0); + const parent = element(by.tagName('app-hero-parent')); const heroes = parent.all(by.tagName('app-hero-child')); for (let i = 0; i < heroNames.length; i++) { @@ -35,7 +31,7 @@ describe('Component Communication Cookbook Tests', () => { it('should display trimmed, non-empty names', () => { const nonEmptyNameIndex = 0; const nonEmptyName = '"Dr IQ"'; - const parent = element.all(by.tagName('app-name-parent')).get(0); + const parent = element(by.tagName('app-name-parent')); const hero = parent.all(by.tagName('app-name-child')).get(nonEmptyNameIndex); const displayName = hero.element(by.tagName('h3')).getText(); @@ -45,7 +41,7 @@ describe('Component Communication Cookbook Tests', () => { it('should replace empty name with default name', () => { const emptyNameIndex = 1; const defaultName = '""'; - const parent = element.all(by.tagName('app-name-parent')).get(0); + const parent = element(by.tagName('app-name-parent')); const hero = parent.all(by.tagName('app-name-child')).get(emptyNameIndex); const displayName = hero.element(by.tagName('h3')).getText(); @@ -70,38 +66,36 @@ describe('Component Communication Cookbook Tests', () => { expect(actual.logs.get(0).getText()).toBe(initialLog); }); - it('should set expected values after clicking \'Minor\' twice', () => { + it('should set expected values after clicking \'Minor\' twice', async () => { const repoTag = element(by.tagName('app-version-parent')); const newMinorButton = repoTag.all(by.tagName('button')).get(0); - newMinorButton.click().then(() => { - newMinorButton.click().then(() => { - const actual = getActual(); + await newMinorButton.click(); + await newMinorButton.click(); + + const actual = getActual(); - const labelAfter2Minor = 'Version 1.25'; - const logAfter2Minor = 'minor changed from 24 to 25'; + const labelAfter2Minor = 'Version 1.25'; + const logAfter2Minor = 'minor changed from 24 to 25'; - expect(actual.label).toBe(labelAfter2Minor); - expect(actual.count).toBe(3); - expect(actual.logs.get(2).getText()).toBe(logAfter2Minor); - }); - }); + expect(actual.label).toBe(labelAfter2Minor); + expect(actual.count).toBe(3); + expect(actual.logs.get(2).getText()).toBe(logAfter2Minor); }); - it('should set expected values after clicking \'Major\' once', () => { + it('should set expected values after clicking \'Major\' once', async () => { const repoTag = element(by.tagName('app-version-parent')); const newMajorButton = repoTag.all(by.tagName('button')).get(1); - newMajorButton.click().then(() => { - const actual = getActual(); + await newMajorButton.click(); + const actual = getActual(); - const labelAfterMajor = 'Version 2.0'; - const logAfterMajor = 'major changed from 1 to 2, minor changed from 25 to 0'; + const labelAfterMajor = 'Version 2.0'; + const logAfterMajor = 'major changed from 1 to 2, minor changed from 23 to 0'; - expect(actual.label).toBe(labelAfterMajor); - expect(actual.count).toBe(4); - expect(actual.logs.get(3).getText()).toBe(logAfterMajor); - }); + expect(actual.label).toBe(labelAfterMajor); + expect(actual.count).toBe(2); + expect(actual.logs.get(1).getText()).toBe(logAfterMajor); }); function getActual() { @@ -118,110 +112,125 @@ describe('Component Communication Cookbook Tests', () => { } // ... // #enddocregion parent-to-child-onchanges - }); describe('Child-to-parent communication', () => { // #docregion child-to-parent // ... it('should not emit the event initially', () => { - const voteLabel = element(by.tagName('app-vote-taker')) - .element(by.tagName('h3')).getText(); - expect(voteLabel).toBe('Agree: 0, Disagree: 0'); + const voteLabel = element(by.tagName('app-vote-taker')).element(by.tagName('h3')); + expect(voteLabel.getText()).toBe('Agree: 0, Disagree: 0'); }); - it('should process Agree vote', () => { + it('should process Agree vote', async () => { + const voteLabel = element(by.tagName('app-vote-taker')).element(by.tagName('h3')); const agreeButton1 = element.all(by.tagName('app-voter')).get(0) .all(by.tagName('button')).get(0); - agreeButton1.click().then(() => { - const voteLabel = element(by.tagName('app-vote-taker')) - .element(by.tagName('h3')).getText(); - expect(voteLabel).toBe('Agree: 1, Disagree: 0'); - }); + + await agreeButton1.click(); + + expect(voteLabel.getText()).toBe('Agree: 1, Disagree: 0'); }); - it('should process Disagree vote', () => { + it('should process Disagree vote', async () => { + const voteLabel = element(by.tagName('app-vote-taker')).element(by.tagName('h3')); const agreeButton1 = element.all(by.tagName('app-voter')).get(1) .all(by.tagName('button')).get(1); - agreeButton1.click().then(() => { - const voteLabel = element(by.tagName('app-vote-taker')) - .element(by.tagName('h3')).getText(); - expect(voteLabel).toBe('Agree: 1, Disagree: 1'); - }); + + await agreeButton1.click(); + + expect(voteLabel.getText()).toBe('Agree: 0, Disagree: 1'); }); // ... // #enddocregion child-to-parent }); - // Can't run timer tests in protractor because - // interaction w/ zones causes all tests to freeze & timeout. - xdescribe('Parent calls child via local var', () => { - countDownTimerTests('countdown-parent-lv'); + describe('Parent calls child via local var', () => { + countDownTimerTests('app-countdown-parent-lv'); }); - xdescribe('Parent calls ViewChild', () => { - countDownTimerTests('countdown-parent-vc'); + describe('Parent calls ViewChild', () => { + countDownTimerTests('app-countdown-parent-vc'); }); function countDownTimerTests(parentTag: string) { // #docregion countdown-timer-tests // ... - it('timer and parent seconds should match', () => { + // The tests trigger periodic asynchronous operations (via `setInterval()`), which will prevent + // the app from stabilizing. See https://angular.io/api/core/ApplicationRef#is-stable-examples + // for more details. + // To allow the tests to complete, we will disable automatically waiting for the Angular app to + // stabilize. + beforeEach(() => browser.waitForAngularEnabled(false)); + afterEach(() => browser.waitForAngularEnabled(true)); + + it('timer and parent seconds should match', async () => { const parent = element(by.tagName(parentTag)); - const message = parent.element(by.tagName('app-countdown-timer')).getText(); - browser.sleep(10); // give `seconds` a chance to catchup with `message` - const seconds = parent.element(by.className('seconds')).getText(); - expect(message).toContain(seconds); + const startButton = parent.element(by.buttonText('Start')); + const seconds = parent.element(by.className('seconds')); + const timer = parent.element(by.tagName('app-countdown-timer')); + + await startButton.click(); + + // Wait for `` to be populated with any text. + await browser.wait(() => timer.getText(), 2000); + + expect(await timer.getText()).toContain(await seconds.getText()); }); - it('should stop the countdown', () => { + it('should stop the countdown', async () => { const parent = element(by.tagName(parentTag)); - const stopButton = parent.all(by.tagName('button')).get(1); + const startButton = parent.element(by.buttonText('Start')); + const stopButton = parent.element(by.buttonText('Stop')); + const timer = parent.element(by.tagName('app-countdown-timer')); + + await startButton.click(); + expect(await timer.getText()).not.toContain('Holding'); - stopButton.click().then(() => { - const message = parent.element(by.tagName('app-countdown-timer')).getText(); - expect(message).toContain('Holding'); - }); + await stopButton.click(); + expect(await timer.getText()).toContain('Holding'); }); // ... // #enddocregion countdown-timer-tests } - describe('Parent and children communicate via a service', () => { // #docregion bidirectional-service // ... - it('should announce a mission', () => { + it('should announce a mission', async () => { const missionControl = element(by.tagName('app-mission-control')); const announceButton = missionControl.all(by.tagName('button')).get(0); - announceButton.click().then(() => { - const history = missionControl.all(by.tagName('li')); - expect(history.count()).toBe(1); - expect(history.get(0).getText()).toMatch(/Mission.* announced/); - }); + const history = missionControl.all(by.tagName('li')); + + await announceButton.click(); + + expect(history.count()).toBe(1); + expect(history.get(0).getText()).toMatch(/Mission.* announced/); }); - it('should confirm the mission by Lovell', () => { - testConfirmMission(1, 2, 'Lovell'); + it('should confirm the mission by Lovell', async () => { + await testConfirmMission(1, 'Lovell'); }); - it('should confirm the mission by Haise', () => { - testConfirmMission(3, 3, 'Haise'); + it('should confirm the mission by Haise', async () => { + await testConfirmMission(3, 'Haise'); }); - it('should confirm the mission by Swigert', () => { - testConfirmMission(2, 4, 'Swigert'); + it('should confirm the mission by Swigert', async () => { + await testConfirmMission(2, 'Swigert'); }); - function testConfirmMission(buttonIndex: number, expectedLogCount: number, astronaut: string) { - const confirmedLog = ' confirmed the mission'; + async function testConfirmMission(buttonIndex: number, astronaut: string) { const missionControl = element(by.tagName('app-mission-control')); + const announceButton = missionControl.all(by.tagName('button')).get(0); const confirmButton = missionControl.all(by.tagName('button')).get(buttonIndex); - confirmButton.click().then(() => { - const history = missionControl.all(by.tagName('li')); - expect(history.count()).toBe(expectedLogCount); - expect(history.get(expectedLogCount - 1).getText()).toBe(astronaut + confirmedLog); - }); + const history = missionControl.all(by.tagName('li')); + + await announceButton.click(); + await confirmButton.click(); + + expect(history.count()).toBe(2); + expect(history.get(1).getText()).toBe(`${astronaut} confirmed the mission`); } // ... // #enddocregion bidirectional-service diff --git a/aio/content/examples/component-interaction/example-config.json b/aio/content/examples/component-interaction/example-config.json index 05e262817d211..e69de29bb2d1d 100644 --- a/aio/content/examples/component-interaction/example-config.json +++ b/aio/content/examples/component-interaction/example-config.json @@ -1,13 +0,0 @@ -{ - "tests": [ - { - "cmd": "yarn", - "args": [ - "e2e", - "--protractor-config=e2e/protractor-puppeteer.conf.js", - "--no-webdriver-update", - "--port={PORT}" - ] - } - ] -} diff --git a/aio/content/examples/component-interaction/src/app/app.component.html b/aio/content/examples/component-interaction/src/app/app.component.html index 907e0181fa617..88d05abdb1e40 100644 --- a/aio/content/examples/component-interaction/src/app/app.component.html +++ b/aio/content/examples/component-interaction/src/app/app.component.html @@ -30,22 +30,21 @@

Component Communication Cookbook

Back to Top -
+
Back to Top -
+
Back to Top -
+
Back to Top -
diff --git a/aio/content/examples/component-interaction/src/app/app.module.ts b/aio/content/examples/component-interaction/src/app/app.module.ts index d1b4570665ed5..caecee59e5d95 100644 --- a/aio/content/examples/component-interaction/src/app/app.module.ts +++ b/aio/content/examples/component-interaction/src/app/app.module.ts @@ -1,4 +1,4 @@ -import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; @@ -15,10 +15,17 @@ import { VersionParentComponent } from './version-parent.component'; import { VoterComponent } from './voter.component'; import { VoteTakerComponent } from './votetaker.component'; -const directives: any[] = [ + +@NgModule({ + imports: [ + BrowserModule, + ], + declarations: [ AppComponent, AstronautComponent, + CountdownLocalVarParentComponent, CountdownTimerComponent, + CountdownViewChildParentComponent, HeroChildComponent, HeroParentComponent, MissionControlComponent, @@ -27,28 +34,8 @@ const directives: any[] = [ VersionChildComponent, VersionParentComponent, VoterComponent, - VoteTakerComponent - ]; - -const schemas: any[] = []; - -// Include Countdown examples -// unless in e2e tests which they break. -if (!/e2e/.test(location.search)) { - console.log('adding countdown timer examples'); - directives.push(CountdownLocalVarParentComponent); - directives.push(CountdownViewChildParentComponent); -} else { - // In e2e test use CUSTOM_ELEMENTS_SCHEMA to suppress unknown element errors - schemas.push(CUSTOM_ELEMENTS_SCHEMA); -} - -@NgModule({ - imports: [ - BrowserModule + VoteTakerComponent, ], - declarations: directives, bootstrap: [ AppComponent ], - schemas }) export class AppModule { } diff --git a/aio/content/examples/component-interaction/src/app/countdown-timer.component.ts b/aio/content/examples/component-interaction/src/app/countdown-timer.component.ts index dcc88334d0201..cba4de07ac42a 100644 --- a/aio/content/examples/component-interaction/src/app/countdown-timer.component.ts +++ b/aio/content/examples/component-interaction/src/app/countdown-timer.component.ts @@ -1,19 +1,16 @@ // #docregion -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy } from '@angular/core'; @Component({ selector: 'app-countdown-timer', template: '

{{message}}

' }) -export class CountdownTimerComponent implements OnInit, OnDestroy { +export class CountdownTimerComponent implements OnDestroy { intervalId = 0; message = ''; seconds = 11; - clearTimer() { clearInterval(this.intervalId); } - - ngOnInit() { this.start(); } ngOnDestroy() { this.clearTimer(); } start() { this.countDown(); } @@ -22,6 +19,8 @@ export class CountdownTimerComponent implements OnInit, OnDestroy { this.message = `Holding at T-${this.seconds} seconds`; } + private clearTimer() { clearInterval(this.intervalId); } + private countDown() { this.clearTimer(); this.intervalId = window.setInterval(() => { diff --git a/aio/content/examples/component-overview/e2e/src/app.e2e-spec.ts b/aio/content/examples/component-overview/e2e/src/app.e2e-spec.ts new file mode 100644 index 0000000000000..c6047b3a6907d --- /dev/null +++ b/aio/content/examples/component-overview/e2e/src/app.e2e-spec.ts @@ -0,0 +1,13 @@ +import { browser, element, by } from 'protractor'; + +describe('Component Overview', () => { + + beforeAll(() => { + browser.get(''); + }); + + it('should display component overview works ', () => { + expect(element(by.css('p')).getText()).toEqual('component-overview works!'); + }); + +}); diff --git a/aio/content/examples/component-overview/example-config.json b/aio/content/examples/component-overview/example-config.json new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/aio/content/examples/component-overview/src/app/app.component.css b/aio/content/examples/component-overview/src/app/app.component.css new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/aio/content/examples/component-overview/src/app/app.component.html b/aio/content/examples/component-overview/src/app/app.component.html new file mode 100644 index 0000000000000..c940e3dc20710 --- /dev/null +++ b/aio/content/examples/component-overview/src/app/app.component.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/aio/content/examples/component-overview/src/app/app.component.spec.ts b/aio/content/examples/component-overview/src/app/app.component.spec.ts new file mode 100644 index 0000000000000..1ccf30def47e3 --- /dev/null +++ b/aio/content/examples/component-overview/src/app/app.component.spec.ts @@ -0,0 +1,31 @@ +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', () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.componentInstance; + expect(app).toBeTruthy(); + }); + + it(`should have as title 'component-overview'`, () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.componentInstance; + expect(app.title).toEqual('component-overview'); + }); + + it('should render title', () => { + const fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + const compiled = fixture.nativeElement; + expect(compiled.querySelector('.content span').textContent).toContain('component-overview app is running!'); + }); +}); diff --git a/aio/content/examples/component-overview/src/app/app.component.ts b/aio/content/examples/component-overview/src/app/app.component.ts new file mode 100644 index 0000000000000..29cfb38dc3768 --- /dev/null +++ b/aio/content/examples/component-overview/src/app/app.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.css'] +}) +export class AppComponent { + title = 'component-overview'; +} diff --git a/aio/content/examples/component-overview/src/app/app.module.ts b/aio/content/examples/component-overview/src/app/app.module.ts new file mode 100644 index 0000000000000..e22e3e1854dfd --- /dev/null +++ b/aio/content/examples/component-overview/src/app/app.module.ts @@ -0,0 +1,18 @@ +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; + +import { AppComponent } from './app.component'; +import { ComponentOverviewComponent } from './component-overview/component-overview.component'; + +@NgModule({ + declarations: [ + AppComponent, + ComponentOverviewComponent + ], + imports: [ + BrowserModule + ], + providers: [], + bootstrap: [AppComponent] +}) +export class AppModule { } diff --git a/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.1.ts b/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.1.ts new file mode 100644 index 0000000000000..3e6d5d1fd2716 --- /dev/null +++ b/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.1.ts @@ -0,0 +1,14 @@ +// #docplaster +import { Component } from '@angular/core'; + +// #docregion template +@Component({ + selector: 'app-component-overview', + template: '

Hello World!

', +}) +// #enddocregion template + +export class ComponentOverviewComponent { + +} + diff --git a/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.2.ts b/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.2.ts new file mode 100644 index 0000000000000..50153f8fbe5f9 --- /dev/null +++ b/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.2.ts @@ -0,0 +1,16 @@ +// #docplaster +import { Component } from '@angular/core'; + +// #docregion templatebacktick +@Component({ + selector: 'app-component-overview', + template: `

Hello World!

+

This template definition spans + multiple lines.

` +}) +// #enddocregion templatebacktick + +export class ComponentOverviewComponent { + +} + diff --git a/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.3.ts b/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.3.ts new file mode 100644 index 0000000000000..b1b8b3706cac9 --- /dev/null +++ b/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.3.ts @@ -0,0 +1,15 @@ +// #docplaster +import { Component } from '@angular/core'; + +// #docregion styles +@Component({ + selector: 'app-component-overview', + template: '

Hello World!

', + styles: ['h1 { font-weight: normal; }'] +}) +// #enddocregion styles + +export class ComponentOverviewComponent { + +} + diff --git a/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.css b/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.css new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.html b/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.html new file mode 100644 index 0000000000000..ffe09040176f1 --- /dev/null +++ b/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.html @@ -0,0 +1 @@ +

component-overview works!

diff --git a/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.spec.ts b/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.spec.ts new file mode 100644 index 0000000000000..61d3e433c64d6 --- /dev/null +++ b/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ComponentOverviewComponent } from './component-overview.component'; + +describe('ComponentOverviewComponent', () => { + let component: ComponentOverviewComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ComponentOverviewComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ComponentOverviewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.ts b/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.ts new file mode 100644 index 0000000000000..7e1e3597a120b --- /dev/null +++ b/aio/content/examples/component-overview/src/app/component-overview/component-overview.component.ts @@ -0,0 +1,22 @@ +// #docplaster +// #docregion import +import { Component } from '@angular/core'; +// #enddocregion import + +// #docregion decorator, decorator-skeleton, selector, templateUrl +@Component({ +// #enddocregion decorator-skeleton + selector: 'app-component-overview', +// #enddocregion selector + templateUrl: './component-overview.component.html', +// #enddocregion templateUrl + styleUrls: ['./component-overview.component.css'] +// #docregion decorator-skeleton, selector, templateUrl +}) +// #enddocregion decorator, decorator-skeleton, selector, templateUrl + +// #docregion class +export class ComponentOverviewComponent { + +} +// #enddocregion class diff --git a/aio/content/examples/component-overview/src/index.html b/aio/content/examples/component-overview/src/index.html new file mode 100644 index 0000000000000..743fd8d693afc --- /dev/null +++ b/aio/content/examples/component-overview/src/index.html @@ -0,0 +1,13 @@ + + + + + ComponentOverview + + + + + + + + diff --git a/aio/content/examples/component-overview/src/main.ts b/aio/content/examples/component-overview/src/main.ts new file mode 100644 index 0000000000000..c7b673cf44b38 --- /dev/null +++ b/aio/content/examples/component-overview/src/main.ts @@ -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)); diff --git a/aio/content/examples/component-overview/stackblitz.json b/aio/content/examples/component-overview/stackblitz.json new file mode 100644 index 0000000000000..865a94123aff6 --- /dev/null +++ b/aio/content/examples/component-overview/stackblitz.json @@ -0,0 +1,8 @@ +{ + "description": "Component Overview", + "files":[ + "!**/*.d.ts", + "!**/*.js" + ], + "tags":["overview", "component"] +} diff --git a/aio/content/examples/component-styles/src/app/quest-summary.component.ts b/aio/content/examples/component-styles/src/app/quest-summary.component.ts index 25765ed16ddd6..6d7b580582da6 100644 --- a/aio/content/examples/component-styles/src/app/quest-summary.component.ts +++ b/aio/content/examples/component-styles/src/app/quest-summary.component.ts @@ -13,8 +13,8 @@ import { Component, ViewEncapsulation } from '@angular/core'; export class QuestSummaryComponent { } // #enddocregion /* - // #docregion encapsulation.native + // #docregion encapsulation.shadow // warning: few browsers support shadow DOM encapsulation at this time - encapsulation: ViewEncapsulation.Native - // #enddocregion encapsulation.native + encapsulation: ViewEncapsulation.ShadowDom + // #enddocregion encapsulation.shadow */ diff --git a/aio/content/examples/http/src/app/uploader/uploader.service.ts b/aio/content/examples/http/src/app/uploader/uploader.service.ts index 8bc659f26f664..b461f6d87693f 100644 --- a/aio/content/examples/http/src/app/uploader/uploader.service.ts +++ b/aio/content/examples/http/src/app/uploader/uploader.service.ts @@ -24,7 +24,7 @@ export class UploaderService { // } upload(file: File) { - if (!file) { return; } + if (!file) { return of(); } // COULD HAVE WRITTEN: // return this.http.post('/upload/file', file, { diff --git a/aio/content/examples/i18n/doc-files/messages.fr.xlf.html b/aio/content/examples/i18n/doc-files/messages.fr.xlf.html index 03635103b746d..213dc74bb3799 100644 --- a/aio/content/examples/i18n/doc-files/messages.fr.xlf.html +++ b/aio/content/examples/i18n/doc-files/messages.fr.xlf.html @@ -41,7 +41,6 @@ - The author is L'auteur est diff --git a/aio/content/examples/observables-in-angular/src/main.ts b/aio/content/examples/observables-in-angular/src/main.ts index 0eaca6bc625eb..3c846a598f199 100644 --- a/aio/content/examples/observables-in-angular/src/main.ts +++ b/aio/content/examples/observables-in-angular/src/main.ts @@ -1,3 +1,4 @@ +// TODO: Add unit tests for this file. // tslint:disable: no-output-native // #docregion import { Component, Output, OnInit, EventEmitter, NgModule } from '@angular/core'; diff --git a/aio/content/examples/observables/example-config.json b/aio/content/examples/observables/example-config.json index c07fa9794c5b5..3aa2059b4d004 100644 --- a/aio/content/examples/observables/example-config.json +++ b/aio/content/examples/observables/example-config.json @@ -2,7 +2,11 @@ "tests": [ { "cmd": "yarn", - "args": [ "tsc", "--project", "./tsconfig.app.json" ] + "args": ["tsc", "--project", "tsconfig.spec.json", "--module", "commonjs"] + }, + { + "cmd": "yarn", + "args": ["jasmine", "out-tsc/**/*.spec.js"] } ] } diff --git a/aio/content/examples/observables/src/creating.spec.ts b/aio/content/examples/observables/src/creating.spec.ts new file mode 100644 index 0000000000000..e1718a9585ba0 --- /dev/null +++ b/aio/content/examples/observables/src/creating.spec.ts @@ -0,0 +1,55 @@ +import { docRegionFromEvent, docRegionSubscriber } from './creating'; + +describe('observables', () => { + it('should create an observable using the constructor', () => { + const console = {log: jasmine.createSpy('log')}; + docRegionSubscriber(console); + expect(console.log).toHaveBeenCalledTimes(4); + expect(console.log.calls.allArgs()).toEqual([ + [1], + [2], + [3], + ['Finished sequence'], + ]); + }); + + it('should listen to input changes', () => { + let triggerInputChange; + const input = { + value: 'Test', + addEventListener: jasmine + .createSpy('addEvent') + .and.callFake((eventName: string, cb: (e) => void) => { + if (eventName === 'keydown') { + triggerInputChange = cb; + } + }), + removeEventListener: jasmine.createSpy('removeEventListener'), + }; + + const document = { getElementById: () => input }; + docRegionFromEvent(document); + triggerInputChange({keyCode: 65}); + expect(input.value).toBe('Test'); + + triggerInputChange({keyCode: 27}); + expect(input.value).toBe(''); + }); + + it('should call removeEventListener when unsubscribing', (doneFn: DoneFn) => { + const input = { + addEventListener: jasmine.createSpy('addEvent'), + removeEventListener: jasmine + .createSpy('removeEvent') + .and.callFake((eventName: string, cb: (e) => void) => { + if (eventName === 'keydown') { + doneFn(); + } + }) + }; + + const document = { getElementById: () => input }; + const subscription = docRegionFromEvent(document); + subscription.unsubscribe(); + }); +}); diff --git a/aio/content/examples/observables/src/creating.ts b/aio/content/examples/observables/src/creating.ts index 83003b99bfecf..7a673228cc8fe 100644 --- a/aio/content/examples/observables/src/creating.ts +++ b/aio/content/examples/observables/src/creating.ts @@ -1,38 +1,39 @@ +// #docplaster import { Observable } from 'rxjs'; -// #docregion subscriber - -// This function runs when subscribe() is called -function sequenceSubscriber(observer) { - // synchronously deliver 1, 2, and 3, then complete - observer.next(1); - observer.next(2); - observer.next(3); - observer.complete(); +export function docRegionSubscriber(console) { + // #docregion subscriber + // This function runs when subscribe() is called + function sequenceSubscriber(observer) { + // synchronously deliver 1, 2, and 3, then complete + observer.next(1); + observer.next(2); + observer.next(3); + observer.complete(); + + // unsubscribe function doesn't need to do anything in this + // because values are delivered synchronously + return {unsubscribe() {}}; + } + + // Create a new Observable that will deliver the above sequence + const sequence = new Observable(sequenceSubscriber); + + // execute the Observable and print the result of each notification + sequence.subscribe({ + next(num) { console.log(num); }, + complete() { console.log('Finished sequence'); } + }); - // unsubscribe function doesn't need to do anything in this - // because values are delivered synchronously - return {unsubscribe() {}}; + // Logs: + // 1 + // 2 + // 3 + // Finished sequence + // #enddocregion subscriber } -// Create a new Observable that will deliver the above sequence -const sequence = new Observable(sequenceSubscriber); - -// execute the Observable and print the result of each notification -sequence.subscribe({ - next(num) { console.log(num); }, - complete() { console.log('Finished sequence'); } -}); - -// Logs: -// 1 -// 2 -// 3 -// Finished sequence - -// #enddocregion subscriber - // #docregion fromevent function fromEvent(target, eventName) { @@ -51,16 +52,18 @@ function fromEvent(target, eventName) { // #enddocregion fromevent -// #docregion fromevent_use +export function docRegionFromEvent(document) { + // #docregion fromevent_use -const ESC_KEY = 27; -const nameInput = document.getElementById('name') as HTMLInputElement; + const ESC_KEY = 27; + const nameInput = document.getElementById('name') as HTMLInputElement; -const subscription = fromEvent(nameInput, 'keydown') - .subscribe((e: KeyboardEvent) => { + const subscription = fromEvent(nameInput, 'keydown').subscribe((e: KeyboardEvent) => { if (e.keyCode === ESC_KEY) { nameInput.value = ''; } }); + // #enddocregion fromevent_use + return subscription; +} -// #enddocregion fromevent_use diff --git a/aio/content/examples/observables/src/geolocation.ts b/aio/content/examples/observables/src/geolocation.ts index 841fea556e451..e1f0a2e40f6ad 100644 --- a/aio/content/examples/observables/src/geolocation.ts +++ b/aio/content/examples/observables/src/geolocation.ts @@ -1,5 +1,5 @@ +// TODO: Add unit tests for this file. import { Observable } from 'rxjs'; - // #docregion // Create an Observable that will start listening to geolocation updates diff --git a/aio/content/examples/observables/src/multicasting.spec.ts b/aio/content/examples/observables/src/multicasting.spec.ts new file mode 100644 index 0000000000000..90bab9615110f --- /dev/null +++ b/aio/content/examples/observables/src/multicasting.spec.ts @@ -0,0 +1,48 @@ +import { docRegionDelaySequence, docRegionMulticastSequence } from './multicasting'; + +describe('multicasting', () => { + let console; + beforeEach(() => { + jasmine.clock().install(); + console = {log: jasmine.createSpy('log')}; + }); + + afterEach(() => { + jasmine.clock().uninstall(); + }); + + it('should create an observable and emit in sequence', () => { + docRegionDelaySequence(console); + jasmine.clock().tick(10000); + expect(console.log).toHaveBeenCalledTimes(12); + expect(console.log.calls.allArgs()).toEqual([ + [1], + ['1st subscribe: 1'], + ['2nd subscribe: 1'], + [2], + ['1st subscribe: 2'], + ['2nd subscribe: 2'], + [3], + ['Finished sequence'], + ['1st subscribe: 3'], + ['1st sequence finished.'], + ['2nd subscribe: 3'], + ['2nd sequence finished.'] + ]); + }); + + it('should create an observable and multicast the emissions', () => { + docRegionMulticastSequence(console); + jasmine.clock().tick(10000); + expect(console.log).toHaveBeenCalledTimes(7); + expect(console.log.calls.allArgs()).toEqual([ + ['1st subscribe: 1'], + ['1st subscribe: 2'], + ['2nd subscribe: 2'], + ['1st subscribe: 3'], + ['2nd subscribe: 3'], + ['1st sequence finished.'], + ['2nd sequence finished.'] + ]); + }); +}); diff --git a/aio/content/examples/observables/src/multicasting.ts b/aio/content/examples/observables/src/multicasting.ts index 2d622e41ff2ac..fe821edd2a8e5 100644 --- a/aio/content/examples/observables/src/multicasting.ts +++ b/aio/content/examples/observables/src/multicasting.ts @@ -1,155 +1,160 @@ +// #docplaster import { Observable } from 'rxjs'; -// #docregion delay_sequence +export function docRegionDelaySequence(console) { + // #docregion delay_sequence + function sequenceSubscriber(observer) { + const seq = [1, 2, 3]; + let timeoutId; + + // Will run through an array of numbers, emitting one value + // per second until it gets to the end of the array. + function doInSequence(arr, idx) { + timeoutId = setTimeout(() => { + observer.next(arr[idx]); + if (idx === arr.length - 1) { + observer.complete(); + } else { + doInSequence(arr, ++idx); + } + }, 1000); + } -function sequenceSubscriber(observer) { - const seq = [1, 2, 3]; - let timeoutId; + doInSequence(seq, 0); - // Will run through an array of numbers, emitting one value - // per second until it gets to the end of the array. - function doInSequence(arr, idx) { - timeoutId = setTimeout(() => { - observer.next(arr[idx]); - if (idx === arr.length - 1) { - observer.complete(); - } else { - doInSequence(arr, ++idx); + // Unsubscribe should clear the timeout to stop execution + return { + unsubscribe() { + clearTimeout(timeoutId); } - }, 1000); + }; } - doInSequence(seq, 0); + // Create a new Observable that will deliver the above sequence + const sequence = new Observable(sequenceSubscriber); - // Unsubscribe should clear the timeout to stop execution - return {unsubscribe() { - clearTimeout(timeoutId); - }}; -} - -// Create a new Observable that will deliver the above sequence -const sequence = new Observable(sequenceSubscriber); - -sequence.subscribe({ - next(num) { console.log(num); }, - complete() { console.log('Finished sequence'); } -}); - -// Logs: -// (at 1 second): 1 -// (at 2 seconds): 2 -// (at 3 seconds): 3 -// (at 3 seconds): Finished sequence + sequence.subscribe({ + next(num) { console.log(num); }, + complete() { console.log('Finished sequence'); } + }); -// #enddocregion delay_sequence + // Logs: + // (at 1 second): 1 + // (at 2 seconds): 2 + // (at 3 seconds): 3 + // (at 3 seconds): Finished sequence -// #docregion subscribe_twice + // #enddocregion delay_sequence -// Subscribe starts the clock, and will emit after 1 second -sequence.subscribe({ - next(num) { console.log('1st subscribe: ' + num); }, - complete() { console.log('1st sequence finished.'); } -}); + // #docregion subscribe_twice -// After 1/2 second, subscribe again. -setTimeout(() => { + // Subscribe starts the clock, and will emit after 1 second sequence.subscribe({ - next(num) { console.log('2nd subscribe: ' + num); }, - complete() { console.log('2nd sequence finished.'); } + next(num) { console.log('1st subscribe: ' + num); }, + complete() { console.log('1st sequence finished.'); } }); -}, 500); - -// Logs: -// (at 1 second): 1st subscribe: 1 -// (at 1.5 seconds): 2nd subscribe: 1 -// (at 2 seconds): 1st subscribe: 2 -// (at 2.5 seconds): 2nd subscribe: 2 -// (at 3 seconds): 1st subscribe: 3 -// (at 3 seconds): 1st sequence finished -// (at 3.5 seconds): 2nd subscribe: 3 -// (at 3.5 seconds): 2nd sequence finished - -// #enddocregion subscribe_twice - -// #docregion multicast_sequence - -function multicastSequenceSubscriber() { - const seq = [1, 2, 3]; - // Keep track of each observer (one for every active subscription) - const observers = []; - // Still a single timeoutId because there will only ever be one - // set of values being generated, multicasted to each subscriber - let timeoutId; - - // Return the subscriber function (runs when subscribe() - // function is invoked) - return (observer) => { - observers.push(observer); - // When this is the first subscription, start the sequence - if (observers.length === 1) { - timeoutId = doSequence({ - next(val) { - // Iterate through observers and notify all subscriptions - observers.forEach(obs => obs.next(val)); - }, - complete() { - // Notify all complete callbacks - observers.slice(0).forEach(obs => obs.complete()); - } - }, seq, 0); - } - return { - unsubscribe() { - // Remove from the observers array so it's no longer notified - observers.splice(observers.indexOf(observer), 1); - // If there's no more listeners, do cleanup - if (observers.length === 0) { - clearTimeout(timeoutId); - } - } - }; - }; + // After 1/2 second, subscribe again. + setTimeout(() => { + sequence.subscribe({ + next(num) { console.log('2nd subscribe: ' + num); }, + complete() { console.log('2nd sequence finished.'); } + }); + }, 500); + + // Logs: + // (at 1 second): 1st subscribe: 1 + // (at 1.5 seconds): 2nd subscribe: 1 + // (at 2 seconds): 1st subscribe: 2 + // (at 2.5 seconds): 2nd subscribe: 2 + // (at 3 seconds): 1st subscribe: 3 + // (at 3 seconds): 1st sequence finished + // (at 3.5 seconds): 2nd subscribe: 3 + // (at 3.5 seconds): 2nd sequence finished + + // #enddocregion subscribe_twice } -// Run through an array of numbers, emitting one value -// per second until it gets to the end of the array. -function doSequence(observer, arr, idx) { - return setTimeout(() => { - observer.next(arr[idx]); - if (idx === arr.length - 1) { - observer.complete(); - } else { - doSequence(observer, arr, ++idx); - } - }, 1000); -} +export function docRegionMulticastSequence(console) { + // #docregion multicast_sequence + function multicastSequenceSubscriber() { + const seq = [1, 2, 3]; + // Keep track of each observer (one for every active subscription) + const observers = []; + // Still a single timeoutId because there will only ever be one + // set of values being generated, multicasted to each subscriber + let timeoutId; + + // Return the subscriber function (runs when subscribe() + // function is invoked) + return observer => { + observers.push(observer); + // When this is the first subscription, start the sequence + if (observers.length === 1) { + timeoutId = doSequence({ + next(val) { + // Iterate through observers and notify all subscriptions + observers.forEach(obs => obs.next(val)); + }, + complete() { + // Notify all complete callbacks + observers.slice(0).forEach(obs => obs.complete()); + } + }, seq, 0); + } + + return { + unsubscribe() { + // Remove from the observers array so it's no longer notified + observers.splice(observers.indexOf(observer), 1); + // If there's no more listeners, do cleanup + if (observers.length === 0) { + clearTimeout(timeoutId); + } + } + }; + }; + } -// Create a new Observable that will deliver the above sequence -const multicastSequence = new Observable(multicastSequenceSubscriber()); + // Run through an array of numbers, emitting one value + // per second until it gets to the end of the array. + function doSequence(observer, arr, idx) { + return setTimeout(() => { + observer.next(arr[idx]); + if (idx === arr.length - 1) { + observer.complete(); + } else { + doSequence(observer, arr, ++idx); + } + }, 1000); + } -// Subscribe starts the clock, and begins to emit after 1 second -multicastSequence.subscribe({ - next(num) { console.log('1st subscribe: ' + num); }, - complete() { console.log('1st sequence finished.'); } -}); + // Create a new Observable that will deliver the above sequence + const multicastSequence = new Observable(multicastSequenceSubscriber()); -// After 1 1/2 seconds, subscribe again (should "miss" the first value). -setTimeout(() => { + // Subscribe starts the clock, and begins to emit after 1 second multicastSequence.subscribe({ - next(num) { console.log('2nd subscribe: ' + num); }, - complete() { console.log('2nd sequence finished.'); } + next(num) { console.log('1st subscribe: ' + num); }, + complete() { console.log('1st sequence finished.'); } }); -}, 1500); - -// Logs: -// (at 1 second): 1st subscribe: 1 -// (at 2 seconds): 1st subscribe: 2 -// (at 2 seconds): 2nd subscribe: 2 -// (at 3 seconds): 1st subscribe: 3 -// (at 3 seconds): 1st sequence finished -// (at 3 seconds): 2nd subscribe: 3 -// (at 3 seconds): 2nd sequence finished - -// #enddocregion multicast_sequence + + // After 1 1/2 seconds, subscribe again (should "miss" the first value). + setTimeout(() => { + multicastSequence.subscribe({ + next(num) { console.log('2nd subscribe: ' + num); }, + complete() { console.log('2nd sequence finished.'); } + }); + }, 1500); + + // Logs: + // (at 1 second): 1st subscribe: 1 + // (at 2 seconds): 1st subscribe: 2 + // (at 2 seconds): 2nd subscribe: 2 + // (at 3 seconds): 1st subscribe: 3 + // (at 3 seconds): 1st sequence finished + // (at 3 seconds): 2nd subscribe: 3 + // (at 3 seconds): 2nd sequence finished + + // #enddocregion multicast_sequence +} diff --git a/aio/content/examples/observables/src/subscribing.spec.ts b/aio/content/examples/observables/src/subscribing.spec.ts new file mode 100644 index 0000000000000..43d0307e5da1e --- /dev/null +++ b/aio/content/examples/observables/src/subscribing.spec.ts @@ -0,0 +1,19 @@ +import { docRegionObserver } from './subscribing'; + +describe('subscribing', () => { + it('should subscribe and emit', () => { + const console = {log: jasmine.createSpy('log')}; + docRegionObserver(console); + expect(console.log).toHaveBeenCalledTimes(8); + expect(console.log.calls.allArgs()).toEqual([ + ['Observer got a next value: 1'], + ['Observer got a next value: 2'], + ['Observer got a next value: 3'], + ['Observer got a complete notification'], + ['Observer got a next value: 1'], + ['Observer got a next value: 2'], + ['Observer got a next value: 3'], + ['Observer got a complete notification'], + ]); + }); +}); diff --git a/aio/content/examples/observables/src/subscribing.ts b/aio/content/examples/observables/src/subscribing.ts index 06a21575d1cfe..47677b5d9e2ef 100644 --- a/aio/content/examples/observables/src/subscribing.ts +++ b/aio/content/examples/observables/src/subscribing.ts @@ -1,32 +1,35 @@ +// #docplaster +import { of } from 'rxjs'; -import { Observable, of } from 'rxjs'; +export function docRegionObserver(console) { + // #docregion observer -// #docregion observer + // Create simple observable that emits three values + const myObservable = of(1, 2, 3); -// Create simple observable that emits three values -const myObservable = of(1, 2, 3); + // Create observer object + const myObserver = { + next: x => console.log('Observer got a next value: ' + x), + error: err => console.error('Observer got an error: ' + err), + complete: () => console.log('Observer got a complete notification'), + }; -// Create observer object -const myObserver = { - next: x => console.log('Observer got a next value: ' + x), - error: err => console.error('Observer got an error: ' + err), - complete: () => console.log('Observer got a complete notification'), -}; + // Execute with the observer object + myObservable.subscribe(myObserver); -// Execute with the observer object -myObservable.subscribe(myObserver); -// Logs: -// Observer got a next value: 1 -// Observer got a next value: 2 -// Observer got a next value: 3 -// Observer got a complete notification + // Logs: + // Observer got a next value: 1 + // Observer got a next value: 2 + // Observer got a next value: 3 + // Observer got a complete notification -// #enddocregion observer + // #enddocregion observer -// #docregion sub_fn -myObservable.subscribe( - x => console.log('Observer got a next value: ' + x), - err => console.error('Observer got an error: ' + err), - () => console.log('Observer got a complete notification') -); -// #enddocregion sub_fn + // #docregion sub_fn + myObservable.subscribe( + x => console.log('Observer got a next value: ' + x), + err => console.error('Observer got an error: ' + err), + () => console.log('Observer got a complete notification') + ); + // #enddocregion sub_fn +} diff --git a/aio/content/examples/practical-observable-usage/example-config.json b/aio/content/examples/practical-observable-usage/example-config.json index c07fa9794c5b5..3aa2059b4d004 100644 --- a/aio/content/examples/practical-observable-usage/example-config.json +++ b/aio/content/examples/practical-observable-usage/example-config.json @@ -2,7 +2,11 @@ "tests": [ { "cmd": "yarn", - "args": [ "tsc", "--project", "./tsconfig.app.json" ] + "args": ["tsc", "--project", "tsconfig.spec.json", "--module", "commonjs"] + }, + { + "cmd": "yarn", + "args": ["jasmine", "out-tsc/**/*.spec.js"] } ] } diff --git a/aio/content/examples/practical-observable-usage/src/backoff.spec.ts b/aio/content/examples/practical-observable-usage/src/backoff.spec.ts new file mode 100644 index 0000000000000..0390a476d1346 --- /dev/null +++ b/aio/content/examples/practical-observable-usage/src/backoff.spec.ts @@ -0,0 +1,70 @@ +import { interval } from 'rxjs'; +import { tap } from 'rxjs/operators'; +import { backoff } from './backoff'; + +describe('backoff()', () => { + beforeEach(() => jasmine.clock().install()); + afterEach(() => jasmine.clock().uninstall()); + + it('should retry in case of error', () => { + const mockConsole = {log: jasmine.createSpy('log')}; + const source = interval(10).pipe( + tap(i => { + if (i > 0) { + throw new Error('Test error'); + } + }), + backoff(3, 100), + ); + source.subscribe({ + next: v => mockConsole.log(`Emitted: ${v}`), + error: e => mockConsole.log(`Errored: ${e.message || e}`), + complete: () => mockConsole.log('Completed'), + }); + + // Initial try: + // Errors on second emission and schedules retrying (with delay). + jasmine.clock().tick(10); + expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]); + + jasmine.clock().tick(10); + expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]); + mockConsole.log.calls.reset(); + + // First re-attempt after 100ms: + // Errors again on second emission and schedules retrying (with larger delay). + jasmine.clock().tick(100); + expect(mockConsole.log).not.toHaveBeenCalled(); + + jasmine.clock().tick(10); + expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]); + + jasmine.clock().tick(10); + expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]); + mockConsole.log.calls.reset(); + + // Second re-attempt after 400ms: + // Errors again on second emission and schedules retrying (with even larger delay). + jasmine.clock().tick(400); + expect(mockConsole.log).not.toHaveBeenCalled(); + + jasmine.clock().tick(10); + expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]); + + jasmine.clock().tick(10); + expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]); + mockConsole.log.calls.reset(); + + // Third re-attempt after 900ms: + // Errors again on second emission and gives up (no retrying). + jasmine.clock().tick(900); + expect(mockConsole.log).not.toHaveBeenCalled(); + + jasmine.clock().tick(10); + expect(mockConsole.log.calls.allArgs()).toEqual([['Emitted: 0']]); + mockConsole.log.calls.reset(); + + jasmine.clock().tick(10); + expect(mockConsole.log.calls.allArgs()).toEqual([['Errored: Test error']]); + }); +}); diff --git a/aio/content/examples/practical-observable-usage/src/backoff.ts b/aio/content/examples/practical-observable-usage/src/backoff.ts index e9e88e7cb20bc..68d724d0972ca 100644 --- a/aio/content/examples/practical-observable-usage/src/backoff.ts +++ b/aio/content/examples/practical-observable-usage/src/backoff.ts @@ -1,23 +1,32 @@ - -import { pipe, range, timer, zip } from 'rxjs'; +// #docplaster +// #docregion +import { of, pipe, range, throwError, timer, zip } from 'rxjs'; import { ajax } from 'rxjs/ajax'; -import { retryWhen, map, mergeMap } from 'rxjs/operators'; +import { map, mergeMap, retryWhen } from 'rxjs/operators'; -function backoff(maxTries, ms) { - return pipe( - retryWhen(attempts => zip(range(1, maxTries), attempts) - .pipe( - map(([i]) => i * i), - mergeMap(i => timer(i * ms)) - ) - ) - ); +export function backoff(maxTries, delay) { + return pipe( + retryWhen(attempts => + zip(range(1, maxTries + 1), attempts).pipe( + mergeMap(([i, err]) => (i > maxTries) ? throwError(err) : of(i)), + map(i => i * i), + mergeMap(v => timer(v * delay)), + ), + ), + ); } +// #enddocregion +/* + This function declaration is necessary to ensure that it does not get called + when running the unit tests. It will not get rendered into the docs. + The indentation needs to start in the leftmost level position as well because of how + the docplaster combines the different regions together. +*/ +function docRegionAjaxCall() { +// #docregion ajax('/api/endpoint') .pipe(backoff(3, 250)) - .subscribe(data => handleData(data)); - -function handleData(data) { - // ... + .subscribe(function handleData(data) { /* ... */ }); +// #enddocregion } diff --git a/aio/content/examples/practical-observable-usage/src/typeahead.spec.ts b/aio/content/examples/practical-observable-usage/src/typeahead.spec.ts new file mode 100644 index 0000000000000..285dd7e12e302 --- /dev/null +++ b/aio/content/examples/practical-observable-usage/src/typeahead.spec.ts @@ -0,0 +1,72 @@ +import { of } from 'rxjs'; +import { docRegionTypeahead } from './typeahead'; + +describe('typeahead', () => { + let document; + let ajax; + let triggertInputChange; + + beforeEach(() => { + jasmine.clock().install(); + const input = { + addEventListener: jasmine + .createSpy('addEvent') + .and.callFake((eventName: string, cb: (e) => void) => { + if (eventName === 'input') { + triggertInputChange = cb; + } + }), + removeEventListener: jasmine.createSpy('removeEvent'), + }; + + document = { getElementById: (id: string) => input }; + ajax = jasmine.createSpy('ajax').and.callFake((url: string) => of('foo bar')); + }); + + afterEach(() => { + jasmine.clock().uninstall(); + }); + + it('should make an ajax call to the corrent endpoint', () => { + docRegionTypeahead(document, ajax); + triggertInputChange({ target: { value: 'foo' } }); + jasmine.clock().tick(11); + expect(ajax).toHaveBeenCalledWith('/api/endpoint?search=foo'); + }); + + it('should not make an ajax call, when the input length < 3', () => { + docRegionTypeahead(document, ajax); + triggertInputChange({ target: { value: '' } }); + jasmine.clock().tick(11); + expect(ajax).not.toHaveBeenCalled(); + triggertInputChange({ target: { value: 'fo' } }); + jasmine.clock().tick(11); + expect(ajax).not.toHaveBeenCalled(); + }); + + it('should not make an ajax call for intermediate values when debouncing', () => { + docRegionTypeahead(document, ajax); + triggertInputChange({ target: { value: 'foo' } }); + jasmine.clock().tick(9); + triggertInputChange({ target: { value: 'bar' } }); + jasmine.clock().tick(9); + triggertInputChange({ target: { value: 'baz' } }); + jasmine.clock().tick(9); + triggertInputChange({ target: { value: 'qux' } }); + expect(ajax).not.toHaveBeenCalled(); + jasmine.clock().tick(10); + expect(ajax).toHaveBeenCalledTimes(1); + expect(ajax).toHaveBeenCalledWith('/api/endpoint?search=qux'); + }); + + it('should not make an ajax call, when the input value has not changed', () => { + docRegionTypeahead(document, ajax); + triggertInputChange({ target: { value: 'foo' } }); + jasmine.clock().tick(11); + expect(ajax).toHaveBeenCalled(); + ajax.calls.reset(); + triggertInputChange({ target: { value: 'foo' } }); + jasmine.clock().tick(11); + expect(ajax).not.toHaveBeenCalled(); + }); +}); diff --git a/aio/content/examples/practical-observable-usage/src/typeahead.ts b/aio/content/examples/practical-observable-usage/src/typeahead.ts index 153ab7f23ed5c..adbddd66c4468 100644 --- a/aio/content/examples/practical-observable-usage/src/typeahead.ts +++ b/aio/content/examples/practical-observable-usage/src/typeahead.ts @@ -1,18 +1,32 @@ -import { fromEvent } from 'rxjs'; -import { ajax } from 'rxjs/ajax'; -import { debounceTime, distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators'; +/* + Because of how the code is merged together using the doc regions, + we need to indent the imports with the function below. +*/ +// #docplaster +// #docregion + import { fromEvent } from 'rxjs'; + import { ajax } from 'rxjs/ajax'; + import { debounceTime, distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators'; +// #enddocregion +/* tslint:disable:no-shadowed-variable */ +/* tslint:disable:align */ +export function docRegionTypeahead(document, ajax) { + // #docregion + const searchBox = document.getElementById('search-box'); -const searchBox = document.getElementById('search-box'); + const typeahead = fromEvent(searchBox, 'input').pipe( + map((e: KeyboardEvent) => (e.target as HTMLInputElement).value), + filter(text => text.length > 2), + debounceTime(10), + distinctUntilChanged(), + switchMap(searchTerm => ajax(`/api/endpoint?search=${searchTerm}`)) + ); -const typeahead = fromEvent(searchBox, 'input').pipe( - map((e: KeyboardEvent) => (e.target as HTMLInputElement).value), - filter(text => text.length > 2), - debounceTime(10), - distinctUntilChanged(), - switchMap(() => ajax('/api/endpoint')) -); + typeahead.subscribe(data => { + // Handle the data from the API + }); -typeahead.subscribe(data => { - // Handle the data from the API -}); + // #enddocregion + return typeahead; +} diff --git a/aio/content/examples/property-binding/src/app/app.component.ts b/aio/content/examples/property-binding/src/app/app.component.ts index cfe9abe4ddaaf..5b58a8c6b3ef5 100644 --- a/aio/content/examples/property-binding/src/app/app.component.ts +++ b/aio/content/examples/property-binding/src/app/app.component.ts @@ -7,9 +7,15 @@ import { Component } from '@angular/core'; styleUrls: ['./app.component.css'] }) export class AppComponent { + // #docregion item-image itemImageUrl = '../assets/phone.png'; + // #enddocregion item-image + // #docregion boolean isUnchanged = true; + // #enddocregion boolean + // #docregion directive-property classes = 'special'; + // #enddocregion directive-property // #docregion parent-data-type parentItem = 'lamp'; // #enddocregion parent-data-type diff --git a/aio/content/examples/rx-library/example-config.json b/aio/content/examples/rx-library/example-config.json index c07fa9794c5b5..3aa2059b4d004 100644 --- a/aio/content/examples/rx-library/example-config.json +++ b/aio/content/examples/rx-library/example-config.json @@ -2,7 +2,11 @@ "tests": [ { "cmd": "yarn", - "args": [ "tsc", "--project", "./tsconfig.app.json" ] + "args": ["tsc", "--project", "tsconfig.spec.json", "--module", "commonjs"] + }, + { + "cmd": "yarn", + "args": ["jasmine", "out-tsc/**/*.spec.js"] } ] } diff --git a/aio/content/examples/rx-library/src/error-handling.spec.ts b/aio/content/examples/rx-library/src/error-handling.spec.ts new file mode 100644 index 0000000000000..9dc82b45e8c9d --- /dev/null +++ b/aio/content/examples/rx-library/src/error-handling.spec.ts @@ -0,0 +1,46 @@ +import { Subject, throwError } from 'rxjs'; +import { docRegionDefault } from './error-handling'; + +describe('error-handling', () => { + let mockConsole; + let ajaxSubject; + let ajax; + + beforeEach(() => { + mockConsole = {log: jasmine.createSpy('log')}; + ajaxSubject = new Subject(); + ajax = jasmine + .createSpy('ajax') + .and.callFake((url: string) => ajaxSubject); + }); + + afterEach(() => ajaxSubject.unsubscribe()); + + it('should return the response object', () => { + docRegionDefault(mockConsole, ajax); + + ajaxSubject.next({response: {foo: 'bar'}}); + expect(mockConsole.log.calls.allArgs()).toEqual([ + ['data: ', {foo: 'bar'}] + ]); + }); + + it('should return an empty array when using an object without a `response` property', () => { + docRegionDefault(mockConsole, ajax); + + ajaxSubject.next({foo: 'bar'}); + expect(mockConsole.log.calls.allArgs()).toEqual([ + ['data: ', []] + ]); + }); + + it('should return an empty array when the ajax observable errors', () => { + ajax.and.returnValue(throwError('Test Error')); + + docRegionDefault(mockConsole, ajax); + + expect(mockConsole.log.calls.allArgs()).toEqual([ + ['data: ', []] + ]); + }); +}); diff --git a/aio/content/examples/rx-library/src/error-handling.ts b/aio/content/examples/rx-library/src/error-handling.ts index c7b6c2dc9ff35..4daca5de8fce9 100644 --- a/aio/content/examples/rx-library/src/error-handling.ts +++ b/aio/content/examples/rx-library/src/error-handling.ts @@ -1,25 +1,36 @@ - -import { of } from 'rxjs'; - +// #docplaster +/* + Because of how the code is merged together using the doc regions, + we need to indent the imports with the function below. +*/ +/* tslint:disable:no-shadowed-variable */ +/* tslint:disable:align */ // #docregion + import { of } from 'rxjs'; + import { ajax } from 'rxjs/ajax'; + import { map, catchError } from 'rxjs/operators'; -import { ajax } from 'rxjs/ajax'; -import { map, catchError } from 'rxjs/operators'; -// Return "response" from the API. If an error happens, -// return an empty array. -const apiData = ajax('/api/data').pipe( - map(res => { - if (!res.response) { - throw new Error('Value expected!'); - } - return res.response; - }), - catchError(err => of([])) -); +// #enddocregion -apiData.subscribe({ - next(x) { console.log('data: ', x); }, - error(err) { console.log('errors already caught... will not run'); } -}); +export function docRegionDefault(console, ajax) { + // #docregion + // Return "response" from the API. If an error happens, + // return an empty array. + const apiData = ajax('/api/data').pipe( + map((res: any) => { + if (!res.response) { + throw new Error('Value expected!'); + } + return res.response; + }), + catchError(err => of([])) + ); -// #enddocregion + apiData.subscribe({ + next(x) { console.log('data: ', x); }, + error(err) { console.log('errors already caught... will not run'); } + }); + + // #enddocregion + return apiData; +} diff --git a/aio/content/examples/rx-library/src/operators.1.spec.ts b/aio/content/examples/rx-library/src/operators.1.spec.ts new file mode 100644 index 0000000000000..04fb0b8de0537 --- /dev/null +++ b/aio/content/examples/rx-library/src/operators.1.spec.ts @@ -0,0 +1,14 @@ +import { docRegionDefault } from './operators.1'; + +describe('squareOdd - operators.1.ts', () => { + it('should return square odds', () => { + const console = {log: jasmine.createSpy('log')}; + docRegionDefault(console); + expect(console.log).toHaveBeenCalledTimes(3); + expect(console.log.calls.allArgs()).toEqual([ + [1], + [9], + [25], + ]); + }); +}); diff --git a/aio/content/examples/rx-library/src/operators.1.ts b/aio/content/examples/rx-library/src/operators.1.ts index be37217d9dbf1..1ed029309878c 100644 --- a/aio/content/examples/rx-library/src/operators.1.ts +++ b/aio/content/examples/rx-library/src/operators.1.ts @@ -1,23 +1,30 @@ -import { of, pipe } from 'rxjs'; - +// #docplaster +/* + Because of how the code is merged together using the doc regions, + we need to indent the imports with the function below. +*/ +/* tslint:disable:align */ // #docregion + import { of, pipe } from 'rxjs'; + import { filter, map } from 'rxjs/operators'; -import { filter, map } from 'rxjs/operators'; - -const nums = of(1, 2, 3, 4, 5); - -// Create a function that accepts an Observable. -const squareOddVals = pipe( - filter((n: number) => n % 2 !== 0), - map(n => n * n) -); +// #enddocregion -// Create an Observable that will run the filter and map functions -const squareOdd = squareOddVals(nums); +export function docRegionDefault(console) { + // #docregion + const nums = of(1, 2, 3, 4, 5); -// Subscribe to run the combined functions -squareOdd.subscribe(x => console.log(x)); + // Create a function that accepts an Observable. + const squareOddVals = pipe( + filter((n: number) => n % 2 !== 0), + map(n => n * n) + ); -// #enddocregion + // Create an Observable that will run the filter and map functions + const squareOdd = squareOddVals(nums); + // Subscribe to run the combined functions + squareOdd.subscribe(x => console.log(x)); + // #enddocregion +} diff --git a/aio/content/examples/rx-library/src/operators.2.spec.ts b/aio/content/examples/rx-library/src/operators.2.spec.ts new file mode 100644 index 0000000000000..f9d1d14103c96 --- /dev/null +++ b/aio/content/examples/rx-library/src/operators.2.spec.ts @@ -0,0 +1,14 @@ +import { docRegionDefault } from './operators.2'; + +describe('squareOdd - operators.2.ts', () => { + it('should return square odds', () => { + const console = {log: jasmine.createSpy('log')}; + docRegionDefault(console); + expect(console.log).toHaveBeenCalledTimes(3); + expect(console.log.calls.allArgs()).toEqual([ + [1], + [9], + [25], + ]); + }); +}); diff --git a/aio/content/examples/rx-library/src/operators.2.ts b/aio/content/examples/rx-library/src/operators.2.ts index 9559ea8525bba..fd792bff99eb5 100644 --- a/aio/content/examples/rx-library/src/operators.2.ts +++ b/aio/content/examples/rx-library/src/operators.2.ts @@ -1,16 +1,25 @@ -import { Observable, of } from 'rxjs'; - +// #docplaster +/* + Because of how the code is merged together using the doc regions, + we need to indent the imports with the function below. +*/ +/* tslint:disable:align */ // #docregion + import { of } from 'rxjs'; + import { filter, map } from 'rxjs/operators'; -import { filter, map } from 'rxjs/operators'; +// #enddocregion -const squareOdd = of(1, 2, 3, 4, 5) - .pipe( - filter(n => n % 2 !== 0), - map(n => n * n) - ); +export function docRegionDefault(console) { + // #docregion + const squareOdd = of(1, 2, 3, 4, 5) + .pipe( + filter(n => n % 2 !== 0), + map(n => n * n) + ); -// Subscribe to get values -squareOdd.subscribe(x => console.log(x)); + // Subscribe to get values + squareOdd.subscribe(x => console.log(x)); -// #enddocregion + // #enddocregion +} diff --git a/aio/content/examples/rx-library/src/operators.spec.ts b/aio/content/examples/rx-library/src/operators.spec.ts new file mode 100644 index 0000000000000..2842d7680693c --- /dev/null +++ b/aio/content/examples/rx-library/src/operators.spec.ts @@ -0,0 +1,14 @@ +import { docRegionDefault } from './operators'; + +describe('squaredNums - operators.ts', () => { + it('should return square odds', () => { + const console = {log: jasmine.createSpy('log')}; + docRegionDefault(console); + expect(console.log).toHaveBeenCalledTimes(3); + expect(console.log.calls.allArgs()).toEqual([ + [1], + [4], + [9], + ]); + }); +}); diff --git a/aio/content/examples/rx-library/src/operators.ts b/aio/content/examples/rx-library/src/operators.ts index 461482a4bc62b..d650413c3cfff 100644 --- a/aio/content/examples/rx-library/src/operators.ts +++ b/aio/content/examples/rx-library/src/operators.ts @@ -1,20 +1,28 @@ - -import { Observable, of } from 'rxjs'; - +// #docplaster +/* + Because of how the code is merged together using the doc regions, + we need to indent the imports with the function below. +*/ +/* tslint:disable:align */ // #docregion + import { of } from 'rxjs'; + import { map } from 'rxjs/operators'; -import { map } from 'rxjs/operators'; +// #enddocregion -const nums = of(1, 2, 3); +export function docRegionDefault(console) { + // #docregion + const nums = of(1, 2, 3); -const squareValues = map((val: number) => val * val); -const squaredNums = squareValues(nums); + const squareValues = map((val: number) => val * val); + const squaredNums = squareValues(nums); -squaredNums.subscribe(x => console.log(x)); + squaredNums.subscribe(x => console.log(x)); -// Logs -// 1 -// 4 -// 9 + // Logs + // 1 + // 4 + // 9 -// #enddocregion + // #enddocregion +} diff --git a/aio/content/examples/rx-library/src/retry-on-error.spec.ts b/aio/content/examples/rx-library/src/retry-on-error.spec.ts new file mode 100644 index 0000000000000..89b9f3145a899 --- /dev/null +++ b/aio/content/examples/rx-library/src/retry-on-error.spec.ts @@ -0,0 +1,69 @@ +import { of, throwError } from 'rxjs'; +import { mergeMap, tap } from 'rxjs/operators'; +import { docRegionDefault } from './retry-on-error'; + +describe('retry-on-error', () => { + let mockConsole; + beforeEach(() => mockConsole = { log: jasmine.createSpy('log') }); + + it('should return the response object', () => { + const ajax = () => of({ response: { foo: 'bar' } }); + + docRegionDefault(mockConsole, ajax); + expect(mockConsole.log.calls.allArgs()).toEqual([ + ['data: ', { foo: 'bar' }], + ]); + }); + + it('should return an empty array after 3 retries + 1 initial request', () => { + const ajax = () => { + return of({ noresponse: true }).pipe(tap(() => mockConsole.log('Subscribed to AJAX'))); + }; + + docRegionDefault(mockConsole, ajax); + expect(mockConsole.log.calls.allArgs()).toEqual([ + ['Subscribed to AJAX'], + ['Error occurred.'], + ['Subscribed to AJAX'], + ['Error occurred.'], + ['Subscribed to AJAX'], + ['Error occurred.'], + ['Subscribed to AJAX'], + ['Error occurred.'], + ['data: ', []], + ]); + }); + + it('should return the response if the request succeeds upon retrying', () => { + // Fail on the first two requests, but succeed from the 3rd onwards. + let failCount = 2; + const ajax = () => of(null).pipe( + tap(() => mockConsole.log('Subscribed to AJAX')), + // Fail on the first 2 requests, but succeed from the 3rd onwards. + mergeMap(() => { + if (failCount > 0) { + failCount--; + return throwError('Test error'); + } + return of({ response: { foo: 'bar' } }); + }), + ); + + docRegionDefault(mockConsole, ajax); + expect(mockConsole.log.calls.allArgs()).toEqual([ + ['Subscribed to AJAX'], // Initial request | 1st attempt overall + ['Subscribed to AJAX'], // 1st retry attempt | 2nd attempt overall + ['Subscribed to AJAX'], // 2nd retry attempt | 3rd attempt overall + ['data: ', { foo: 'bar' }], + ]); + }); + + it('should return an empty array when the ajax observable throws an error', () => { + const ajax = () => throwError('Test Error'); + + docRegionDefault(mockConsole, ajax); + expect(mockConsole.log.calls.allArgs()).toEqual([ + ['data: ', []], + ]); + }); +}); diff --git a/aio/content/examples/rx-library/src/retry-on-error.ts b/aio/content/examples/rx-library/src/retry-on-error.ts index b1a5389c1b146..eaa8539379d36 100644 --- a/aio/content/examples/rx-library/src/retry-on-error.ts +++ b/aio/content/examples/rx-library/src/retry-on-error.ts @@ -1,26 +1,35 @@ - -import { Observable, of } from 'rxjs'; - - +// #docplaster +/* + Because of how the code is merged together using the doc regions, + we need to indent the imports with the function below. +*/ +/* tslint:disable:no-shadowed-variable */ +/* tslint:disable:align */ // #docregion + import { of } from 'rxjs'; + import { ajax } from 'rxjs/ajax'; + import { map, retry, catchError } from 'rxjs/operators'; -import { ajax } from 'rxjs/ajax'; -import { map, retry, catchError } from 'rxjs/operators'; +// #enddocregion -const apiData = ajax('/api/data').pipe( - retry(3), // Retry up to 3 times before failing - map(res => { - if (!res.response) { - throw new Error('Value expected!'); - } - return res.response; - }), - catchError(err => of([])) -); +export function docRegionDefault(console, ajax) { + // #docregion + const apiData = ajax('/api/data').pipe( + map((res: any) => { + if (!res.response) { + console.log('Error occurred.'); + throw new Error('Value expected!'); + } + return res.response; + }), + retry(3), // Retry up to 3 times before failing + catchError(err => of([])) + ); -apiData.subscribe({ - next(x) { console.log('data: ', x); }, - error(err) { console.log('errors already caught... will not run'); } -}); + apiData.subscribe({ + next(x) { console.log('data: ', x); }, + error(err) { console.log('errors already caught... will not run'); } + }); -// #enddocregion + // #enddocregion +} diff --git a/aio/content/examples/rx-library/src/simple-creation.1.spec.ts b/aio/content/examples/rx-library/src/simple-creation.1.spec.ts new file mode 100644 index 0000000000000..8c2944dd44fdb --- /dev/null +++ b/aio/content/examples/rx-library/src/simple-creation.1.spec.ts @@ -0,0 +1,14 @@ +import { of } from 'rxjs'; +import { docRegionPromise } from './simple-creation.1'; + +describe('simple-creation.1', () => { + it('should create a promise from an observable and return an empty object', () => { + const console = {log: jasmine.createSpy('log')}; + const fetch = () => of({foo: 42}); + docRegionPromise(console, fetch); + expect(console.log.calls.allArgs()).toEqual([ + [{foo: 42}], + ['Completed'], + ]); + }); +}); diff --git a/aio/content/examples/rx-library/src/simple-creation.1.ts b/aio/content/examples/rx-library/src/simple-creation.1.ts new file mode 100644 index 0000000000000..6388b18cc0250 --- /dev/null +++ b/aio/content/examples/rx-library/src/simple-creation.1.ts @@ -0,0 +1,24 @@ +// #docplaster +/* + Because of how the code is merged together using the doc regions, + we need to indent the imports with the function below. +*/ +/* tslint:disable:align */ +// #docregion promise + import { from } from 'rxjs'; + +// #enddocregion promise + +export function docRegionPromise(console, fetch) { + // #docregion promise + // Create an Observable out of a promise + const data = from(fetch('/api/endpoint')); + // Subscribe to begin listening for async result + data.subscribe({ + next(response) { console.log(response); }, + error(err) { console.error('Error: ' + err); }, + complete() { console.log('Completed'); } + }); + + // #enddocregion promise +} diff --git a/aio/content/examples/rx-library/src/simple-creation.2.spec.ts b/aio/content/examples/rx-library/src/simple-creation.2.spec.ts new file mode 100644 index 0000000000000..4716482a48d86 --- /dev/null +++ b/aio/content/examples/rx-library/src/simple-creation.2.spec.ts @@ -0,0 +1,21 @@ +import { docRegionInterval } from './simple-creation.2'; + +describe('simple-creation.2', () => { + beforeEach(() => jasmine.clock().install()); + afterEach(() => jasmine.clock().uninstall()); + + it('should create an Observable that will publish a value on an interval', () => { + const console = {log: jasmine.createSpy('log')}; + const subscription = docRegionInterval(console); + jasmine.clock().tick(1000); + expect(console.log).toHaveBeenCalledWith('It\'s been 1 seconds since subscribing!'); + console.log.calls.reset(); + + jasmine.clock().tick(999); + expect(console.log).not.toHaveBeenCalled(); + + jasmine.clock().tick(1); + expect(console.log).toHaveBeenCalledWith('It\'s been 2 seconds since subscribing!'); + subscription.unsubscribe(); + }); +}); diff --git a/aio/content/examples/rx-library/src/simple-creation.2.ts b/aio/content/examples/rx-library/src/simple-creation.2.ts new file mode 100644 index 0000000000000..fb186d693b4ab --- /dev/null +++ b/aio/content/examples/rx-library/src/simple-creation.2.ts @@ -0,0 +1,22 @@ +// #docplaster +/* + Because of how the code is merged together using the doc regions, + we need to indent the imports with the function below. +*/ +/* tslint:disable:align */ +// #docregion interval + import { interval } from 'rxjs'; + +// #enddocregion interval + +export function docRegionInterval(console) { + // #docregion interval + // Create an Observable that will publish a value on an interval + const secondsCounter = interval(1000); + // Subscribe to begin publishing values + const subscription = secondsCounter.subscribe(n => + console.log(`It's been ${n + 1} seconds since subscribing!`)); + + // #enddocregion interval + return subscription; +} diff --git a/aio/content/examples/rx-library/src/simple-creation.3.spec.ts b/aio/content/examples/rx-library/src/simple-creation.3.spec.ts new file mode 100644 index 0000000000000..7c1ed586a4e96 --- /dev/null +++ b/aio/content/examples/rx-library/src/simple-creation.3.spec.ts @@ -0,0 +1,53 @@ +import { docRegionEvent } from './simple-creation.3'; + +describe('simple-creation.3', () => { + let triggerMousemove; + let mockConsole; + let input; + let mockDocument; + + beforeEach(() => { + mockConsole = {log: jasmine.createSpy('log')}; + input = { + addEventListener: jasmine + .createSpy('addEventListener') + .and.callFake((eventName, cb) => { + if (eventName === 'mousemove') { + triggerMousemove = cb; + } + }), + removeEventListener: jasmine.createSpy('removeEventListener'), + }; + mockDocument = { getElementById: () => input }; + }); + + it('should log coords when subscribing', () => { + docRegionEvent(mockConsole, mockDocument); + + expect(mockConsole.log).not.toHaveBeenCalled(); + + triggerMousemove({ clientX: 50, clientY: 50 }); + triggerMousemove({ clientX: 30, clientY: 50 }); + triggerMousemove({ clientX: 50, clientY: 30 }); + expect(mockConsole.log).toHaveBeenCalledTimes(3); + expect(mockConsole.log.calls.allArgs()).toEqual([ + ['Coords: 50 X 50'], + ['Coords: 30 X 50'], + ['Coords: 50 X 30'] + ]); + }); + + it('should call unsubscribe when clientX and clientY are below < 40 ', () => { + docRegionEvent(mockConsole, mockDocument); + + expect(mockConsole.log).not.toHaveBeenCalled(); + + // Ensure that we have unsubscribed. + triggerMousemove({ clientX: 30, clientY: 30 }); + expect(input.removeEventListener).toHaveBeenCalledWith('mousemove', triggerMousemove, undefined); + mockConsole.log.calls.reset(); + + triggerMousemove({ clientX: 50, clientY: 50 }); + expect(mockConsole.log).not.toHaveBeenCalled(); + }); +}); diff --git a/aio/content/examples/rx-library/src/simple-creation.3.ts b/aio/content/examples/rx-library/src/simple-creation.3.ts new file mode 100644 index 0000000000000..63a36517273f4 --- /dev/null +++ b/aio/content/examples/rx-library/src/simple-creation.3.ts @@ -0,0 +1,32 @@ +// #docplaster +/* + Because of how the code is merged together using the doc regions, + we need to indent the imports with the function below. +*/ +/* tslint:disable:align */ +// #docregion event + import { fromEvent } from 'rxjs'; + +// #enddocregion event + +export function docRegionEvent(console, document) { + // #docregion event + const el = document.getElementById('my-element'); + + // Create an Observable that will publish mouse movements + const mouseMoves = fromEvent(el, 'mousemove'); + + // Subscribe to start listening for mouse-move events + const subscription = mouseMoves.subscribe((evt: MouseEvent) => { + // Log coords of mouse movements + console.log(`Coords: ${evt.clientX} X ${evt.clientY}`); + + // When the mouse is over the upper-left of the screen, + // unsubscribe to stop listening for mouse movements + if (evt.clientX < 40 && evt.clientY < 40) { + subscription.unsubscribe(); + } + }); + + // #enddocregion event +} diff --git a/aio/content/examples/rx-library/src/simple-creation.spec.ts b/aio/content/examples/rx-library/src/simple-creation.spec.ts new file mode 100644 index 0000000000000..8de9a846e2730 --- /dev/null +++ b/aio/content/examples/rx-library/src/simple-creation.spec.ts @@ -0,0 +1,14 @@ +import { of } from 'rxjs'; +import { docRegionAjax } from './simple-creation'; + +describe('ajax', () => { + it('should make a request and console log the status and response', () => { + const console = {log: jasmine.createSpy('log')}; + const ajax = jasmine.createSpy('ajax').and.callFake((url: string) => { + return of({status: 200, response: 'foo bar'}); + }); + + docRegionAjax(console, ajax); + expect(console.log).toHaveBeenCalledWith(200, 'foo bar'); + }); +}); diff --git a/aio/content/examples/rx-library/src/simple-creation.ts b/aio/content/examples/rx-library/src/simple-creation.ts index ef83631dbaeb9..bc2ef499943e2 100644 --- a/aio/content/examples/rx-library/src/simple-creation.ts +++ b/aio/content/examples/rx-library/src/simple-creation.ts @@ -1,65 +1,19 @@ - -// #docregion promise - -import { from } from 'rxjs'; - -// Create an Observable out of a promise -const data = from(fetch('/api/endpoint')); -// Subscribe to begin listening for async result -data.subscribe({ - next(response) { console.log(response); }, - error(err) { console.error('Error: ' + err); }, - complete() { console.log('Completed'); } -}); - -// #enddocregion promise - -// #docregion interval - -import { interval } from 'rxjs'; - -// Create an Observable that will publish a value on an interval -const secondsCounter = interval(1000); -// Subscribe to begin publishing values -secondsCounter.subscribe(n => - console.log(`It's been ${n} seconds since subscribing!`)); - -// #enddocregion interval - - -// #docregion event - -import { fromEvent } from 'rxjs'; - -const el = document.getElementById('my-element'); - -// Create an Observable that will publish mouse movements -const mouseMoves = fromEvent(el, 'mousemove'); - -// Subscribe to start listening for mouse-move events -const subscription = mouseMoves.subscribe((evt: MouseEvent) => { - // Log coords of mouse movements - console.log(`Coords: ${evt.clientX} X ${evt.clientY}`); - - // When the mouse is over the upper-left of the screen, - // unsubscribe to stop listening for mouse movements - if (evt.clientX < 40 && evt.clientY < 40) { - subscription.unsubscribe(); - } -}); - -// #enddocregion event - - +// #docplaster +/* + Because of how the code is merged together using the doc regions, + we need to indent the imports with the function below. +*/ +/* tslint:disable:no-shadowed-variable */ +/* tslint:disable:align */ // #docregion ajax - -import { ajax } from 'rxjs/ajax'; + import { ajax } from 'rxjs/ajax'; // Create an Observable that will create an AJAX request -const apiData = ajax('/api/data'); -// Subscribe to create the request -apiData.subscribe(res => console.log(res.status, res.response)); - // #enddocregion ajax - - +export function docRegionAjax(console, ajax) { + // #docregion ajax + const apiData = ajax('/api/data'); + // Subscribe to create the request + apiData.subscribe(res => console.log(res.status, res.response)); + // #enddocregion ajax +} diff --git a/aio/content/examples/service-worker-getting-started/src/app/handle-unrecoverable-state.service.ts b/aio/content/examples/service-worker-getting-started/src/app/handle-unrecoverable-state.service.ts new file mode 100644 index 0000000000000..2754fa052a158 --- /dev/null +++ b/aio/content/examples/service-worker-getting-started/src/app/handle-unrecoverable-state.service.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@angular/core'; +import { SwUpdate } from '@angular/service-worker'; + +function notifyUser(message: string): void { } + +// #docregion sw-unrecoverable-state +@Injectable() +export class HandleUnrecoverableStateService { + constructor(updates: SwUpdate) { + updates.unrecoverable.subscribe(event => { + notifyUser( + `An error occurred that we cannot recover from:\n${event.reason}\n\n` + + 'Please reload the page.'); + }); + } +} +// #enddocregion sw-unrecoverable-state diff --git a/aio/content/examples/styleguide/src/05-17/app/heroes/hero-list/hero-list.component.avoid.ts b/aio/content/examples/styleguide/src/05-17/app/heroes/hero-list/hero-list.component.avoid.ts index f0075129494d7..0b704d2b8787a 100644 --- a/aio/content/examples/styleguide/src/05-17/app/heroes/hero-list/hero-list.component.avoid.ts +++ b/aio/content/examples/styleguide/src/05-17/app/heroes/hero-list/hero-list.component.avoid.ts @@ -10,8 +10,8 @@ import { Hero } from '../shared/hero.model'; template: `
Our list of heroes: - - + + Total powers: {{totalPowers}}
Average power: {{totalPowers / heroes.length}}
diff --git a/aio/content/examples/testing/src/app/demo/demo.testbed.spec.ts b/aio/content/examples/testing/src/app/demo/demo.testbed.spec.ts index a6bbd1aafc030..9510eb8f51c64 100644 --- a/aio/content/examples/testing/src/app/demo/demo.testbed.spec.ts +++ b/aio/content/examples/testing/src/app/demo/demo.testbed.spec.ts @@ -28,7 +28,7 @@ import { ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync } from '@angular/core/testing'; -import { addMatchers, newEvent, click } from '../../testing'; +import { addMatchers, click } from '../../testing'; export class NotProvided extends ValueService { /* example below */ } beforeEach(addMatchers); @@ -274,9 +274,11 @@ describe('demo (with TestBed):', () => { expect(comp.name).toBe(expectedOrigName, `comp.name should still be ${expectedOrigName} after value change, before binding happens`); - // dispatch a DOM event so that Angular learns of input value change. + // Dispatch a DOM event so that Angular learns of input value change. // then wait while ngModel pushes input.box value to comp.name - input.dispatchEvent(newEvent('input')); + // In older browsers, such as IE, you might need a CustomEvent instead. See + // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill + input.dispatchEvent(new Event('input')); return fixture.whenStable(); }) .then(() => { @@ -312,9 +314,11 @@ describe('demo (with TestBed):', () => { expect(comp.name).toBe(expectedOrigName, `comp.name should still be ${expectedOrigName} after value change, before binding happens`); - // dispatch a DOM event so that Angular learns of input value change. + // Dispatch a DOM event so that Angular learns of input value change. // then wait a tick while ngModel pushes input.box value to comp.name - input.dispatchEvent(newEvent('input')); + // In older browsers, such as IE, you might need a CustomEvent instead. See + // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill + input.dispatchEvent(new Event('input')); tick(); expect(comp.name).toBe(expectedNewName, `After ngModel updates the model, comp.name should be ${expectedNewName} `); @@ -335,10 +339,12 @@ describe('demo (with TestBed):', () => { // simulate user entering new name in input input.value = inputText; - // dispatch a DOM event so that Angular learns of input value change. + // Dispatch a DOM event so that Angular learns of input value change. // then wait a tick while ngModel pushes input.box value to comp.text // and Angular updates the output span - input.dispatchEvent(newEvent('input')); + // In older browsers, such as IE, you might need a CustomEvent instead. See + // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill + input.dispatchEvent(new Event('input')); tick(); fixture.detectChanges(); expect(span.textContent).toBe(expectedText, 'output span'); diff --git a/aio/content/examples/testing/src/app/hero/hero-detail.component.spec.ts b/aio/content/examples/testing/src/app/hero/hero-detail.component.spec.ts index 0015c96d5225e..8f4ee4f6d7e11 100644 --- a/aio/content/examples/testing/src/app/hero/hero-detail.component.spec.ts +++ b/aio/content/examples/testing/src/app/hero/hero-detail.component.spec.ts @@ -3,7 +3,7 @@ import { ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync } from import { Router } from '@angular/router'; import { - ActivatedRoute, ActivatedRouteStub, asyncData, click, newEvent + ActivatedRoute, ActivatedRouteStub, asyncData, click } from '../../testing'; import { Hero } from '../model/hero'; @@ -99,7 +99,10 @@ function overrideSetup() { const newName = 'New Name'; page.nameInput.value = newName; - page.nameInput.dispatchEvent(newEvent('input')); // tell Angular + + // In older browsers, such as IE, you might need a CustomEvent instead. See + // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill + page.nameInput.dispatchEvent(new Event('input')); // tell Angular expect(component.hero.name).toBe(newName, 'component hero has new name'); expect(hdsSpy.testHero.name).toBe(origName, 'service hero unchanged before save'); @@ -197,9 +200,10 @@ function heroModuleSetup() { // simulate user entering a new name into the input box nameInput.value = 'quick BROWN fOx'; - // dispatch a DOM event so that Angular learns of input value change. - // use newEvent utility function (not provided by Angular) for better browser compatibility - nameInput.dispatchEvent(newEvent('input')); + // Dispatch a DOM event so that Angular learns of input value change. + // In older browsers, such as IE, you might need a CustomEvent instead. See + // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill + nameInput.dispatchEvent(new Event('input')); // Tell Angular to update the display binding through the title pipe fixture.detectChanges(); diff --git a/aio/content/examples/testing/src/app/hero/hero-list.component.spec.ts b/aio/content/examples/testing/src/app/hero/hero-list.component.spec.ts index b8c0278bf6428..b65eaada82aa8 100644 --- a/aio/content/examples/testing/src/app/hero/hero-list.component.spec.ts +++ b/aio/content/examples/testing/src/app/hero/hero-list.component.spec.ts @@ -6,7 +6,7 @@ import { DebugElement } from '@angular/core'; import { Router } from '@angular/router'; -import { addMatchers, newEvent } from '../../testing'; +import { addMatchers } from '../../testing'; import { HeroService } from '../model/hero.service'; import { getTestHeroes, TestHeroService } from '../model/testing/test-hero.service'; @@ -53,7 +53,10 @@ describe('HeroListComponent', () => { it('should select hero on click', fakeAsync(() => { const expectedHero = HEROES[1]; const li = page.heroRows[1]; - li.dispatchEvent(newEvent('click')); + + // In older browsers, such as IE, you might need a CustomEvent instead. See + // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill + li.dispatchEvent(new Event('click')); tick(); // `.toEqual` because selectedHero is clone of expectedHero; see FakeHeroService expect(comp.selectedHero).toEqual(expectedHero); @@ -62,7 +65,10 @@ describe('HeroListComponent', () => { it('should navigate to selected hero detail on click', fakeAsync(() => { const expectedHero = HEROES[1]; const li = page.heroRows[1]; - li.dispatchEvent(newEvent('click')); + + // In older browsers, such as IE, you might need a CustomEvent instead. See + // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill + li.dispatchEvent(new Event('click')); tick(); // should have navigated diff --git a/aio/content/examples/testing/src/app/shared/highlight.directive.spec.ts b/aio/content/examples/testing/src/app/shared/highlight.directive.spec.ts index bd068c5c685ba..1ab8d68a6c7aa 100644 --- a/aio/content/examples/testing/src/app/shared/highlight.directive.spec.ts +++ b/aio/content/examples/testing/src/app/shared/highlight.directive.spec.ts @@ -3,7 +3,6 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { HighlightDirective } from './highlight.directive'; -import { newEvent } from '../../testing'; // #docregion test-component @Component({ @@ -59,9 +58,12 @@ describe('HighlightDirective', () => { const input = des[2].nativeElement as HTMLInputElement; expect(input.style.backgroundColor).toBe('cyan', 'initial backgroundColor'); - // dispatch a DOM event so that Angular responds to the input value change. input.value = 'green'; - input.dispatchEvent(newEvent('input')); + + // Dispatch a DOM event so that Angular responds to the input value change. + // In older browsers, such as IE, you might need a CustomEvent instead. See + // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill + input.dispatchEvent(new Event('input')); fixture.detectChanges(); expect(input.style.backgroundColor).toBe('green', 'changed backgroundColor'); diff --git a/aio/content/examples/testing/src/testing/index.ts b/aio/content/examples/testing/src/testing/index.ts index e9e139a9064b2..bcea4482a219b 100644 --- a/aio/content/examples/testing/src/testing/index.ts +++ b/aio/content/examples/testing/src/testing/index.ts @@ -14,18 +14,6 @@ export function advance(f: ComponentFixture): void { f.detectChanges(); } -/** - * Create custom DOM event the old fashioned way - * - * https://developer.mozilla.org/en-US/docs/Web/API/Event/initEvent - * Although officially deprecated, some browsers (phantom) don't accept the preferred "new Event(eventName)" - */ -export function newEvent(eventName: string, bubbles = false, cancelable = false) { - const evt = document.createEvent('CustomEvent'); // MUST be 'CustomEvent' - evt.initCustomEvent(eventName, bubbles, cancelable, null); - return evt; -} - // See https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button // #docregion click-event /** Button events to pass to `DebugElement.triggerEventHandler` for RouterLink event handler */ diff --git a/aio/content/examples/toh-pt6/src/app/hero-detail/hero-detail.component.ts b/aio/content/examples/toh-pt6/src/app/hero-detail/hero-detail.component.ts index 6bcb8f014d0e1..8c3eab261ae52 100644 --- a/aio/content/examples/toh-pt6/src/app/hero-detail/hero-detail.component.ts +++ b/aio/content/examples/toh-pt6/src/app/hero-detail/hero-detail.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, Input } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Location } from '@angular/common'; @@ -11,7 +11,7 @@ import { HeroService } from '../hero.service'; styleUrls: [ './hero-detail.component.css' ] }) export class HeroDetailComponent implements OnInit { - @Input() hero: Hero; + hero: Hero; constructor( private route: ActivatedRoute, diff --git a/aio/content/examples/tslint.json b/aio/content/examples/tslint.json index bf1abc0372d71..4cfd9cae6bebd 100644 --- a/aio/content/examples/tslint.json +++ b/aio/content/examples/tslint.json @@ -1,5 +1,8 @@ { "extends": "tslint:recommended", + "rulesDirectory": [ + "codelyzer" + ], "rules": { "align": { "options": [ @@ -13,22 +16,6 @@ "deprecation": { "severity": "warning" }, - "component-class-suffix": true, - "component-selector": [ - true, - "element", - // TODO: Fix the code and change the prefix to `"app"` (or whatever makes sense). - "", - "kebab-case" - ], - "contextual-lifecycle": true, - "directive-class-suffix": true, - "directive-selector": [ - true, - "attribute", - ["app", "toh"], - "camelCase" - ], "eofline": true, "import-blacklist": [ true, @@ -56,6 +43,8 @@ ] } ], + // TODO(gkalpak): Fix the code and enable this. + // "no-any": true, "no-console": [ true, "debug", @@ -95,6 +84,11 @@ "named": "never" } }, + // TODO(gkalpak): Fix the code and enable this. + // "typedef": [ + // true, + // "call-signature" + // ], "typedef-whitespace": { "options": [ { @@ -130,6 +124,9 @@ "check-typecast" ] }, + "component-class-suffix": true, + "contextual-lifecycle": true, + "directive-class-suffix": true, "no-conflicting-lifecycle": true, "no-host-metadata-property": true, "no-input-rename": true, @@ -141,9 +138,19 @@ "template-banana-in-box": true, "template-no-negated-async": true, "use-lifecycle-interface": true, - "use-pipe-transform-interface": true - }, - "rulesDirectory": [ - "codelyzer" - ] + "use-pipe-transform-interface": true, + "directive-selector": [ + true, + "attribute", + ["app", "toh"], + "camelCase" + ], + "component-selector": [ + true, + "element", + // TODO: Fix the code and change the prefix to `"app"` (or whatever makes sense). + "", + "kebab-case" + ] + } } diff --git a/aio/content/examples/upgrade-lazy-load-ajs/src/app/angularjs-app/index.ts b/aio/content/examples/upgrade-lazy-load-ajs/src/app/angularjs-app/index.ts index 4d43a7fa09e8c..51eed5229c196 100644 --- a/aio/content/examples/upgrade-lazy-load-ajs/src/app/angularjs-app/index.ts +++ b/aio/content/examples/upgrade-lazy-load-ajs/src/app/angularjs-app/index.ts @@ -1,9 +1,7 @@ import * as angular from 'angular'; import 'angular-route'; -const appName = 'myApp'; - -angular.module(appName, [ +const appModule = angular.module('myApp', [ 'ngRoute' ]) .config(['$routeProvider', '$locationProvider', @@ -25,5 +23,5 @@ angular.module(appName, [ ); export function bootstrap(el: HTMLElement) { - return angular.bootstrap(el, [appName]); + return angular.bootstrap(el, [appModule.name]); } diff --git a/aio/content/guide/angular-compiler-options.md b/aio/content/guide/angular-compiler-options.md index 90101d8eff210..390147cc1dd6c 100644 --- a/aio/content/guide/angular-compiler-options.md +++ b/aio/content/guide/angular-compiler-options.md @@ -31,7 +31,7 @@ For example: ```json { - "extends": "../tsconfig.base.json", + "extends": "../tsconfig.json", "compilerOptions": { "experimentalDecorators": true, ... diff --git a/aio/content/guide/aot-compiler.md b/aio/content/guide/aot-compiler.md index df846a9209d31..9e8a7f67c8217 100644 --- a/aio/content/guide/aot-compiler.md +++ b/aio/content/guide/aot-compiler.md @@ -62,7 +62,7 @@ In the following example, the `@Component()` metadata object and the class const @Component({ selector: 'app-typical', template: '
A typical component for {{data.name}}
' -)} +}) export class TypicalComponent { @Input() data: TypicalData; constructor(private someService: SomeService) { ... } diff --git a/aio/content/guide/architecture-components.md b/aio/content/guide/architecture-components.md index bedc446a511cf..df3de2d587296 100644 --- a/aio/content/guide/architecture-components.md +++ b/aio/content/guide/architecture-components.md @@ -89,7 +89,7 @@ This example from the `HeroListComponent` template uses three of these forms. -* The `{{hero.name}}` [*interpolation*](guide/displaying-data#interpolation) +* The `{{hero.name}}` [*interpolation*](guide/interpolation) displays the component's `hero.name` property value within the `
  • ` element. * The `[hero]` [*property binding*](guide/property-binding) passes the value of @@ -166,8 +166,8 @@ The example template uses two built-in structural directives to add application -* [`*ngFor`](guide/displaying-data#ngFor) is an iterative; it tells Angular to stamp out one `
  • ` per hero in the `heroes` list. -* [`*ngIf`](guide/displaying-data#ngIf) is a conditional; it includes the `HeroDetail` component only if a selected hero exists. +* [`*ngFor`](guide/structural-directives#inside-ngfor) is an iterative; it tells Angular to stamp out one `
  • ` per hero in the `heroes` list. +* [`*ngIf`](guide/structural-directives#ngif-case-study) is a conditional; it includes the `HeroDetail` component only if a selected hero exists. #### Attribute directives diff --git a/aio/content/guide/binding-syntax.md b/aio/content/guide/binding-syntax.md index 0bd41cf77d7ce..d5f4747cdff1c 100644 --- a/aio/content/guide/binding-syntax.md +++ b/aio/content/guide/binding-syntax.md @@ -154,7 +154,7 @@ Attributes can be changed by `setAttribute()`, which re-initializes correspondin For more information, see the [MDN Interfaces documentation](https://developer.mozilla.org/en-US/docs/Web/API#Interfaces) which has API docs for all the standard DOM elements and their properties. -Comparing the [`
  • - - - - - @@ -185,7 +174,7 @@ These are the polyfills required to run an Angular application on each supported - - - - - - - -
    One-Two
    ` attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td) attributes to the [`` properties](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement) provides a helpful example for differentiation. +Comparing the [`` attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td) to the [`` properties](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement) provides a helpful example for differentiation. In particular, you can navigate from the attributes page to the properties via "DOM interface" link, and navigate the inheritance hierarchy up to `HTMLTableCellElement`. @@ -195,7 +195,7 @@ To control the state of the button, set the `disabled` *property*,
    -Though you could technically set the `[attr.disabled]` attribute binding, the values are different in that the property binding requires to a boolean value, while its corresponding attribute binding relies on whether the value is `null` or not. Consider the following: +Though you could technically set the `[attr.disabled]` attribute binding, the values are different in that the property binding requires to be a boolean value, while its corresponding attribute binding relies on whether the value is `null` or not. Consider the following: ```html diff --git a/aio/content/guide/browser-support.md b/aio/content/guide/browser-support.md index b4e315b97b2aa..a26ce9bab418d 100644 --- a/aio/content/guide/browser-support.md +++ b/aio/content/guide/browser-support.md @@ -53,18 +53,7 @@ Angular supports most recent browsers. This includes the following specific vers IE
    -
    11, 10*, 9* ("compatibility view" mode not supported)
    -
    *deprecated in v10, see the {@link guide/deprecations#ie-9-10-and-mobile deprecations guide}.
    -
    - IE Mobile* - - 11 -
    *deprecated in v10, see the {@link guide/deprecations#ie-9-10-and-mobile deprecations guide}.
    +
    11
    Chrome, Firefox, Edge,
    - Safari, Android, IE 10+ + Safari, Android, IE 11
    @@ -196,20 +185,6 @@ These are the polyfills required to run an Angular application on each supported
    - IE 9 - - - ES2015
    [classList](guide/browser-support#classlist) - -
    @@ -272,30 +247,7 @@ Some features of Angular may require additional polyfills. - IE 10, IE 11 - - - - - - - - - [Http](guide/http) when sending and receiving binary data - - - - - [Typed Array](guide/browser-support#typedarray)
    - - [Blob](guide/browser-support#blob)
    - - [FormData](guide/browser-support#formdata) - - - - - IE 9 + IE 11 @@ -437,60 +389,6 @@ The following polyfills are used to test the framework itself. They are a good s - - - - - Typed Array - - - - - MIT - - - - 4KB - - - - - - - - - Blob - - - - - MIT - - - - 1.3KB - - - - - - - - - FormData - - - - - MIT - - - - 0.4KB - - - - diff --git a/aio/content/guide/built-in-directives.md b/aio/content/guide/built-in-directives.md index d1a954169d11f..987939144b0ef 100644 --- a/aio/content/guide/built-in-directives.md +++ b/aio/content/guide/built-in-directives.md @@ -194,7 +194,7 @@ which explains the following: * Using [``](guide/structural-directives#ngcontainer "") to group elements when there is no suitable host element for the directive. * How to write your own structural directive. -* That you can only apply [one structural directive](guide/structural-directives#one-per-element "one per host element") to an element. +* Why you [can only apply one structural directive](guide/structural-directives#one-per-element "one per host element") to an element. @@ -281,7 +281,7 @@ You define a block of HTML that defines how a single item should be displayed and then you tell Angular to use that block as a template for rendering each item in the list. The text assigned to `*ngFor` is the instruction that guides the repeater process. -The following example shows `NgFor` applied to a simple `
    `. (Don't forget the asterisk (`*`) in front of `ngFor`.) +The following example shows `NgFor` applied to a simple `
    `. diff --git a/aio/content/guide/component-overview.md b/aio/content/guide/component-overview.md new file mode 100644 index 0000000000000..a0ecb998dddd9 --- /dev/null +++ b/aio/content/guide/component-overview.md @@ -0,0 +1,182 @@ +# Angular Components Overview + +Components are the main building block for Angular applications. Each component consists of: + +* An HTML template that declares what renders on the page +* A Typescript class that defines behavior +* A CSS selector that defines how the component is used in a template +* Optionally, CSS styles applied to the template + +This topic describes how to create and configure an Angular component. + +
    + +To view or download the example code used in this topic, see the . + +
    + +## Prerequisites + +To create a component, verify that you have met the following prerequisites: + +1. Install the Angular CLI. +1. Create an Angular project. + If you don't have a project, you can create one using `ng new `, where `` is the name of your Angular application. + +## Creating a component + +The easiest way to create a component is with the Angular CLI. You can also create a component manually. + +### Creating a component using the Angular CLI + +To create a component using the Angular CLI: + +1. From a terminal window, navigate to the directory containing your application. +1. Run the `ng generate component ` command, where `` is the name of your new component. + +By default, this command creates the following: + +* A folder named after the component +* A component file, `.component.ts` +* A template file, `.component.ts` +* A CSS file, `.component.css` +* A testing specification file, `.component.spec.ts` + +Where `` is the name of your component. + +
    + +You can change how `ng generate component` creates new components. +For more information, see [ng generate component](cli/generate#component-command) in the Angular CLI documentation. + +
    + +### Creating a component manually + +Although the Angular CLI is the easiest way to create an Angular component, you can also create a component manually. +This section describes how to create the core component file within an existing Angular project. + +To create a new component manually: + +1. Navigate to your Angular project directory. +1. Create a new file, `.component.ts`. +1. At the top of the file, add the following import statement. + + + + +1. After the `import` statement, add a `@Component` decorator. + + + + +1. Choose a CSS selector for the component. + + + + + For more information on choosing a selector, see [Specifying a component's selector](#specifying-a-components-css-selector). + +1. Define the HTML template that the component uses to display information. + In most cases, this template is a separate HTML file. + + + + + For more information on defining a component's template, see [Defining a component's template](#defining-a-components-template). + +1. Select the styles for the component's template. + In most cases, you define the styles for you component's template in a separate file. + + + + +1. Add a `class` statement that includes the code for the component. + + + + +## Specifying a component's CSS selector + +Every component requires a CSS _selector_. A selector instructs Angular to instantiate this component wherever it finds the corresponding tag in template HTML. For example, consider a component, `hello-world.component.ts` that defines its selector as `app-hello-world`. This selector instructs angular to instantiate this component any time the tag, `` in a template. + +To specify a component's selector, add a `selector` statement to the `@Component` decorator. + + + + +## Defining a component's template + +A template is a block of HTML that tells Angular how to render the component in your application. +You can define a template for your component in one of two ways: by referencing an external file, or directly within the component. + +To define a template as an external file, add a `templateUrl` property to the `@Component` decorator. + + + + +To define a template within the component, add a `template` property to the `@Component` decorator that contains the HTML you want to use. + + + + +If your want your template to span multiple lines, you can use backticks ( ` ). +For example: + + + + +
    + +An Angular component requires a template defined using `template` or `templateUrl`. You cannot have both statements in a component. + +
    + +## Declaring a component's styles + +You can declare component styles uses for its template in one of two ways: by referencing an external file, or directly within the component. + +To declare the styles for a component in a separate file, add a `stylesUrls` property to the `@Component` decorator. + + + + +To select the styles within the component, add a `styles` property to the `@Component` decorator that contains the styles you want to use. + + + + +The `styles` property takes an array of strings that contain the CSS rule declarations. + + +## Next steps + +* For an archictural overview of components, see [Introduction to components and templates](guide/architecture-components). +* For additional options you can use when creating a component, see [Component](api/core/Component) in the API Reference. +* For more information on styling components, see [Component styles](guide/component-styles). +* For more information on templates, see [Template syntax](guide/template-syntax). + diff --git a/aio/content/guide/component-styles.md b/aio/content/guide/component-styles.md index 03677ce0ce8c8..dc7b1b9f77fe7 100644 --- a/aio/content/guide/component-styles.md +++ b/aio/content/guide/component-styles.md @@ -119,13 +119,13 @@ The `/deep/` combinator also has the aliases `>>>`, and `::ng-deep`. Use `/deep/`, `>>>` and `::ng-deep` only with *emulated* view encapsulation. Emulated is the default and most commonly used view encapsulation. For more information, see the -[Controlling view encapsulation](guide/component-styles#view-encapsulation) section. +[View Encapsulation](guide/view-encapsulation) section.
    -The shadow-piercing descendant combinator is deprecated and [support is being removed from major browsers](https://www.chromestatus.com/features/6750456638341120) and tools. +The shadow-piercing descendant combinator is deprecated and [support is being removed from major browsers](https://www.chromestatus.com/feature/6750456638341120) and tools. As such we plan to drop support in Angular (for all 3 of `/deep/`, `>>>` and `::ng-deep`). Until then `::ng-deep` should be preferred for a broader compatibility with the tools. @@ -267,89 +267,3 @@ as explained in the [CLI wiki](https://github.com/angular/angular-cli/wiki/stori Style strings added to the `@Component.styles` array _must be written in CSS_ because the CLI cannot apply a preprocessor to inline styles.
    - -{@a view-encapsulation} - -## View encapsulation - -As discussed earlier, component CSS styles are encapsulated into the component's view and don't -affect the rest of the application. - -To control how this encapsulation happens on a *per -component* basis, you can set the *view encapsulation mode* in the component metadata. -Choose from the following modes: - -* `ShadowDom` view encapsulation uses the browser's native shadow DOM implementation (see - [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Shadow_DOM) - on the [MDN](https://developer.mozilla.org) site) - to attach a shadow DOM to the component's host element, and then puts the component - view inside that shadow DOM. The component's styles are included within the shadow DOM. - -* `Native` view encapsulation uses a now deprecated version of the browser's native shadow DOM implementation - [learn about the changes](https://hayato.io/2016/shadowdomv1/). - -* `Emulated` view encapsulation (the default) emulates the behavior of shadow DOM by preprocessing - (and renaming) the CSS code to effectively scope the CSS to the component's view. - For details, see [Inspecting generated CSS](guide/component-styles#inspect-generated-css) below. - -* `None` means that Angular does no view encapsulation. - Angular adds the CSS to the global styles. - The scoping rules, isolations, and protections discussed earlier don't apply. - This is essentially the same as pasting the component's styles into the HTML. - -To set the components encapsulation mode, use the `encapsulation` property in the component metadata: - - - -`ShadowDom` view encapsulation only works on browsers that have native support -for shadow DOM (see [Shadow DOM v1](https://caniuse.com/#feat=shadowdomv1) on the -[Can I use](http://caniuse.com) site). The support is still limited, -which is why `Emulated` view encapsulation is the default mode and recommended -in most cases. - -{@a inspect-generated-css} - -## Inspecting generated CSS - -When using emulated view encapsulation, Angular preprocesses -all component styles so that they approximate the standard shadow CSS scoping rules. - -In the DOM of a running Angular application with emulated view -encapsulation enabled, each DOM element has some extra attributes -attached to it: - - - <hero-details _nghost-pmm-5> - <h2 _ngcontent-pmm-5>Mister Fantastic</h2> - <hero-team _ngcontent-pmm-5 _nghost-pmm-6> - <h3 _ngcontent-pmm-6>Team</h3> - </hero-team> - </hero-detail> - - - -There are two kinds of generated attributes: - -* An element that would be a shadow DOM host in native encapsulation has a - generated `_nghost` attribute. This is typically the case for component host elements. -* An element within a component's view has a `_ngcontent` attribute -that identifies to which host's emulated shadow DOM this element belongs. - -The exact values of these attributes aren't important. They are automatically -generated and you never refer to them in application code. But they are targeted -by the generated component styles, which are in the `` section of the DOM: - - - [_nghost-pmm-5] { - display: block; - border: 1px solid black; - } - - h3[_ngcontent-pmm-6] { - background-color: white; - border: 1px solid #777; - } - - -These styles are post-processed so that each selector is augmented -with `_nghost` or `_ngcontent` attribute selectors. -These extra selectors enable the scoping rules described in this page. diff --git a/aio/content/guide/creating-libraries.md b/aio/content/guide/creating-libraries.md index f35ac775835c9..7370486f9958a 100644 --- a/aio/content/guide/creating-libraries.md +++ b/aio/content/guide/creating-libraries.md @@ -26,7 +26,7 @@ The `ng generate` command creates the `projects/my-lib` folder in your workspace
    -When you generate a new library, the workspace configuration file, `angular.json`, is updated with a project of type 'library'. +When you generate a new library, the workspace configuration file, `angular.json`, is updated with a project of type `library`. "projects": { @@ -109,7 +109,7 @@ If you want a dropdown that would contain different passed-in values each time, Suppose you want to read a configuration file and then generate a form based on that configuration. If that form will need additional customization by the developer who is using your library, it might work best as a schematic. -However, if the forms will always be the same and not need much customization by developers, then you could create a dynamic component that takes the configuration and generates the form. +However, if the form will always be the same and not need much customization by developers, then you could create a dynamic component that takes the configuration and generates the form. In general, the more complex the customization, the more useful the schematic approach. To learn more, see [Schematics Overview](guide/schematics) and [Schematics for Libraries](guide/schematics-for-libraries). @@ -156,7 +156,7 @@ The library must be rebuilt on every change. When linking a library, make sure that the build step runs in watch mode, and that the library's `package.json` configuration points at the correct entry points. For example, `main` should point at a JavaScript file, not a TypeScript file. -## Use TypeScript path mapping for peer dependencies +### Use TypeScript path mapping for peer dependencies Angular libraries should list all `@angular/*` dependencies as peer dependencies. This ensures that when modules ask for Angular, they all get the exact same module. diff --git a/aio/content/guide/deployment.md b/aio/content/guide/deployment.md index 0bdbef63e40a3..f3e1432723963 100644 --- a/aio/content/guide/deployment.md +++ b/aio/content/guide/deployment.md @@ -97,7 +97,7 @@ For the simplest deployment, create a production build and copy the output direc -2. Copy _everything_ within the output folder (`dist/` by default) to a folder on the server. +2. Copy _everything_ within the output folder (`dist/project-name/` by default) to a folder on the server. 3. Configure the server to redirect requests for missing files to `index.html`. Learn more about server-side redirects [below](#fallback). @@ -211,11 +211,11 @@ modified to serve `index.html`: # . # -- server.rb # -- public - # |-- dist + # |-- project-name # |-- index.html get '/' do - folderDir = settings.public_folder + '/dist' # ng build output folder + folderDir = settings.public_folder + '/project-name' # ng build output folder send_file File.join(folderDir, 'index.html') end ``` @@ -383,11 +383,11 @@ Build your app for production _including the source maps_ -List the generated bundles in the `dist/` folder. +List the generated bundles in the `dist/project-name/` folder. - ls dist/*.bundle.js + ls dist/project-name/*.js @@ -396,7 +396,7 @@ The following example displays the graph for the _main_ bundle. - node_modules/.bin/source-map-explorer dist/main.*.bundle.js + node_modules/.bin/source-map-explorer dist/project-name/main* @@ -511,9 +511,9 @@ Each script tag has a `type="module"` or `nomodule` attribute. Browsers with nat To include differential loading in your application builds, you must configure the Browserslist and TypeScript configuration files in your application project. -The following examples show a `browserlistrc` and `tsconfig.json` file for a newly created Angular application. In this configuration, legacy browsers such as IE 9-11 are ignored, and the compilation target is ES2015. +The following examples show a `.browserslistrc` and `tsconfig.json` file for a newly created Angular application. In this configuration, legacy browsers such as IE 9-11 are ignored, and the compilation target is ES2015. - + # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. # For additional information regarding the format and rule options, please see: # https://github.com/browserslist/browserslist#queries @@ -527,10 +527,10 @@ The following examples show a `browserlistrc` and `tsconfig.json` file for a new last 1 Chrome version last 1 Firefox version last 2 Edge major versions -last 2 Safari major version +last 2 Safari major versions last 2 iOS major versions Firefox ESR -not IE 9-11 # For IE 9-11 support, remove 'not'. +not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. diff --git a/aio/content/guide/deprecations.md b/aio/content/guide/deprecations.md index d4e2320411bfb..2a2c04d720589 100644 --- a/aio/content/guide/deprecations.md +++ b/aio/content/guide/deprecations.md @@ -38,18 +38,14 @@ v9 - v12 | `@angular/bazel` | [`Bazel builder and schematics`](#bazelbuilder) | v10 | | `@angular/common` | [`ReflectiveInjector`](#reflectiveinjector) | v11 | | `@angular/common` | [`CurrencyPipe` - `DEFAULT_CURRENCY_CODE`](api/common/CurrencyPipe#currency-code-deprecation) | v11 | -| `@angular/core` | [`CollectionChangeRecord`](#core) | v11 | | `@angular/core` | [`DefaultIterableDiffer`](#core) | v11 | | `@angular/core` | [`ReflectiveKey`](#core) | v11 | | `@angular/core` | [`RenderComponentType`](#core) | v11 | -| `@angular/core` | [`ViewEncapsulation.Native`](#core) | v11 | | `@angular/core` | [`WrappedValue`](#core) | v12 | | `@angular/forms` | [`ngModel` with reactive forms](#ngmodel-reactive) | v11 | -| `@angular/router` | [`preserveQueryParams`](#router) | v11 | | `@angular/upgrade` | [`@angular/upgrade`](#upgrade) | v11 | | `@angular/upgrade` | [`getAngularLib`](#upgrade-static) | v11 | | `@angular/upgrade` | [`setAngularLib`](#upgrade-static) | v11 | -| `@angular/platform-webworker` | [All entry points](api/platform-webworker) | v11 | | template syntax | [`](#template-tag) | v11 | | polyfills | [reflect-metadata](#reflect-metadata) | v11 | | npm package format | [`esm5` and `fesm5` entry-points in @angular/* npm packages](guide/deprecations#esm5-fesm5) | v11 | @@ -61,7 +57,6 @@ v9 - v12 | `@angular/core/testing` | [`async`](#testing) | v12 | | `@angular/router` | [`ActivatedRoute` params and `queryParams` properties](#activatedroute-props) | unspecified | | template syntax | [`/deep/`, `>>>`, and `::ng-deep`](#deep-component-style-selector) | unspecified | -| browser support | [`IE 9 and 10, IE mobile`](#ie-9-10-and-mobile) | v11 | For information about Angular CDK and Angular Material deprecations, see the [changelog](https://github.com/angular/components/blob/master/CHANGELOG.md). @@ -89,11 +84,9 @@ Tip: In the [API reference section](api) of this doc site, deprecated APIs are i | API | Replacement | Deprecation announced | Notes | | --- | ----------- | --------------------- | ----- | -| [`CollectionChangeRecord`](api/core/CollectionChangeRecord) | [`IterableChangeRecord`](api/core/IterableChangeRecord) | v4 | none | | [`DefaultIterableDiffer`](api/core/DefaultIterableDiffer) | n/a | v4 | Not part of public API. | | [`ReflectiveInjector`](api/core/ReflectiveInjector) | [`Injector.create`](api/core/Injector#create) | v5 | See [`ReflectiveInjector`](#reflectiveinjector) | | [`ReflectiveKey`](api/core/ReflectiveKey) | none | v5 | none | -| [`ViewEncapsulation.Native`](api/core/ViewEncapsulation#Native) | [`ViewEncapsulation.ShadowDom`](api/core/ViewEncapsulation#ShadowDom) | v6 | Use the native encapsulation mechanism of the renderer. See [view.ts](https://github.com/angular/angular/blob/3e992e18ebf51d6036818f26c3d77b52d3ec48eb/packages/core/src/metadata/view.ts#L32). | [`defineInjectable`](api/core/defineInjectable) | `ɵɵdefineInjectable` | v8 | Used only in generated code. No source code should depend on this API. | | [`entryComponents`](api/core/NgModule#entryComponents) | none | v9 | See [`entryComponents`](#entryComponents) | | [`ANALYZE_FOR_ENTRY_COMPONENTS`](api/core/ANALYZE_FOR_ENTRY_COMPONENTS) | none | v9 | See [`ANALYZE_FOR_ENTRY_COMPONENTS`](#entryComponents) | @@ -119,26 +112,6 @@ Tip: In the [API reference section](api) of this doc site, deprecated APIs are i | --- | ----------- | --------------------- | ----- | | [`ngModel` with reactive forms](#ngmodel-reactive) | [`FormControlDirective`](api/forms/FormControlDirective) | v6 | none | -{@a router} -### @angular/router - -| API | Replacement | Deprecation announced | Notes | -| --- | ----------- | --------------------- | ----- | -| [`preserveQueryParams`](api/router/NavigationExtras#preserveQueryParams) | [`queryParamsHandling`](api/router/NavigationExtras#queryParamsHandling) | v4 | none | - -{@a platform-webworker} -### @angular/platform-webworker - -| API | Replacement | Deprecation announced | Notes | -| --- | ----------- | --------------------- | ----- | -| [All entry points](api/platform-webworker) | none | v8 | See [platform-webworker](#webworker-apps). | - -{@a platform-webworker-dynamic} -### @angular/platform-webworker-dynamic - -| API | Replacement | Deprecation announced | Notes | -| --- | ----------- | --------------------- | ----- | -| [All entry points](api/platform-webworker-dynamic) | none | v8 | See [platform-webworker](#webworker-apps). | {@a upgrade} ### @angular/upgrade @@ -394,28 +367,6 @@ These two properties have subtle differences, so switching to `textContent` unde All of the `wtf*` APIs are deprecated and will be removed in a future version. -{@a webworker-apps} -### Running Angular applications in platform-webworker - -The `@angular/platform-*` packages enable Angular to be run in different contexts. For examples, -`@angular/platform-server` enables Angular to be run on the server, and `@angular/platform-browser` -enables Angular to be run in a web browser. - -`@angular/platform-webworker` was introduced in Angular version 2 as an experiment in leveraging -Angular's rendering architecture to run an entire web application in a -[web worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API). We've learned a lot -from this experiment and have come to the conclusion that running the entire application in a web -worker is not the best strategy for most applications. - -Going forward, we will focus our efforts related to web workers around their primary use case of -offloading CPU-intensive, non-critical work needed for initial rendering (such as in-memory search -and image processing). Learn more in the -[guide to Using Web Workers with the Angular CLI](guide/web-worker). - -As of Angular version 8, all `platform-webworker` APIs are deprecated. -This includes both packages: `@angular/platform-webworker` and -`@angular/platform-webworker-dynamic`. - {@a entryComponents} ### `entryComponents` and `ANALYZE_FOR_ENTRY_COMPONENTS` no longer required Previously, the `entryComponents` array in the `NgModule` definition was used to tell the compiler which components would be created and inserted dynamically. With Ivy, this isn't a requirement anymore and the `entryComponents` array can be removed from existing module declarations. The same applies to the `ANALYZE_FOR_ENTRY_COMPONENTS` injection token. @@ -464,20 +415,6 @@ export class MyModule { } ``` - -{@a ie-9-10-and-mobile} -### IE 9, 10, and IE mobile support - -Support for IE 9 and 10 has been deprecated, as well as support for IE Mobile. These will be dropped in a future version. -Supporting outdated browsers like these increases bundle size, code complexity, and test load, and also requires time and effort that could be spent on improvements to the framework. -For example, fixing issues can be more difficult, as a straightforward fix for modern browsers could break old ones that have quirks due to not receiving updates from vendors. - -The final decision was made on three key points: -* __Vendor support__: Microsoft dropped support of IE 9 and 10 on 1/12/16, meaning they no longer provide security updates or technical support. Additionally, Microsoft dropped support for Windows 10 Mobile in December 2019. -* __Usage statistics__: We looked at usage trends for IE 9 and 10 (as well as IE Mobile) from various sources and all indicated that usage percentages were extremely small (fractions of 1%). -* __Feedback from partners__: We also reached out to some of our Angular customers and none expressed concern about dropping IE 9, 10, nor IE Mobile support. - - {@a wrapped-value} ### `WrappedValue` @@ -544,15 +481,13 @@ This section contains a complete list all of the currently deprecated CLI flags. {@a removed} ## Removed APIs -The following APIs have been removed starting with version 10.0.0*: +The following APIs have been removed starting with version 11.0.0*: | Package | API | Replacement | Notes | | ---------------- | -------------- | ----------- | ----- | -| `@angular/core` | Undecorated base classes that use Angular features | Add Angular decorator | See [migration guide](guide/migration-undecorated-classes) for more info | -| `@angular/core` | `ModuleWithProviders` without a generic | `ModuleWithProviders` with a generic | See [migration guide](guide/migration-module-with-providers) for more info | -| `@angular/core` | Style Sanitization | no action needed | See [style sanitization API removal](#style-sanitization) for more info +| `@angular/router` | `preserveQueryParams` | [`queryParamsHandling`](api/router/UrlCreationOptions#queryParamsHandling) | | -*To see APIs removed in version 9, check out this guide on the [version 9 docs site](https://v9.angular.io/guide/deprecations#removed). +*To see APIs removed in version 10, check out this guide on the [version 10 docs site](https://v10.angular.io/guide/deprecations#removed). {@a esm5-fesm5} @@ -603,18 +538,6 @@ In practical terms, the `package.json` of all `@angular` packages has changed in For more information about the npm package format, see the [Angular Package Format spec](https://goo.gl/jB3GVv). -{@a removed} -## Removed APIs - -The following APIs have been removed starting with version 10.0.0*: - -| Package | API | Replacement | Notes | -| ---------------- | -------------- | ----------- | ----- | -| `@angular/core` | Undecorated base classes that use Angular features | Add Angular decorator | See [migration guide](guide/migration-undecorated-classes) for more info | -| `@angular/core` | `ModuleWithProviders` without a generic | `ModuleWithProviders` with a generic | See [migration guide](guide/migration-module-with-providers) for more info | - -*To see APIs removed in version 9, check out this guide on the [version 9 docs site](https://v9.angular.io/guide/deprecations#removed). - {@a style-sanitization} ### Style Sanitization for `[style]` and `[style.prop]` bindings Angular used to sanitize `[style]` and `[style.prop]` bindings to prevent malicious code from being inserted through `javascript:` expressions in CSS `url()` entries. However, most modern browsers no longer support the usage of these expressions, so sanitization was only maintained for the sake of IE 6 and 7. Given that Angular does not support either IE 6 or 7 and sanitization has a performance cost, we will no longer sanitize style bindings as of version 10 of Angular. diff --git a/aio/content/guide/displaying-data.md b/aio/content/guide/displaying-data.md deleted file mode 100644 index e7e78b1bf5b3b..0000000000000 --- a/aio/content/guide/displaying-data.md +++ /dev/null @@ -1,312 +0,0 @@ -# Displaying data in views - -Angular [components](guide/glossary#component) form the data structure of your application. -The HTML [template](guide/glossary#template) associated with a component provides the means to display that data in the context of a web page. -Together, a component's class and template form a [view](guide/glossary#view) of your application data. - -The process of combining data values with their representation on the page is called [data binding](guide/glossary#data-binding). -You display your data to a user (and collect data from the user) by *binding* controls in the HTML template to the data properties of the component class. - -In addition, you can add logic to the template by including [directives](guide/glossary#directive), which tell Angular how to modify the page as it is rendered. - -Angular defines a *template language* that expands HTML notation with syntax that allows you to define various kinds of data binding and logical directives. -When the page is rendered, Angular interprets the template syntax to update the HTML according to your logic and current data state. -Before you read the complete [template syntax guide](guide/template-syntax), the exercises on this page give you a quick demonstration of how template syntax works. - -In this demo, you'll create a component with a list of heroes. -You'll display the list of hero names and conditionally show a message below the list. -The final UI looks like this: - - - -
    - -The demonstrates all of the syntax and code snippets described in this page. - -
    - -{@a interpolation} - -## Showing component properties with interpolation -The easiest way to display a component property is to bind the property name through interpolation. -With interpolation, you put the property name in the view template, enclosed in double curly braces: `{{myHero}}`. - -Use the CLI command [`ng new displaying-data`](cli/new) to create a workspace and app named `displaying-data`. - -Delete the app.component.html file. It is not needed for this example. - -Then modify the app.component.ts file by -changing the template and the body of the component. - -When you're done, it should look like this: - - - -You added two properties to the formerly empty component: `title` and `myHero`. - -The template displays the two component properties using double curly brace -interpolation: - - - -
    - -The template is a multi-line string within ECMAScript 2015 backticks (\`). -The backtick (\`)—which is *not* the same character as a single -quote (`'`)—allows you to compose a string over several lines, which makes the -HTML more readable. - -
    - -Angular automatically pulls the value of the `title` and `myHero` properties from the component and -inserts those values into the browser. Angular updates the display -when these properties change. - -
    - -More precisely, the redisplay occurs after some kind of asynchronous event related to -the view, such as a keystroke, a timer completion, or a response to an HTTP request. - -
    - -Notice that you don't call **new** to create an instance of the `AppComponent` class. -Angular is creating an instance for you. How? - -The CSS `selector` in the `@Component` decorator specifies an element named ``. -That element is a placeholder in the body of your `index.html` file: - - - -When you bootstrap with the `AppComponent` class (in main.ts), Angular looks for a `` -in the `index.html`, finds it, instantiates an instance of `AppComponent`, and renders it -inside the `` tag. - -Now run the app. It should display the title and hero name: - - - -The next few sections review some of the coding choices in the app. - - -## Choosing the template source - -The `@Component` metadata tells Angular where to find the component's template. -You can store your component's template in one of two places. - -* You can define the template *inline* using the `template` property of the `@Component` decorator. An inline template is useful for a small demo or test. -* Alternatively, you can define the template in a separate HTML file and link to that file in the `templateUrl` property of the `@Component` decorator. This configuration is typical for anything more complex than a small test or demo, and is the default when you generate a new component. - -In either style, the template data bindings have the same access to the component's properties. -Here the app uses inline HTML because the template is small and the demo is simpler without the additional HTML file. - -
    - - By default, the Angular CLI command [`ng generate component`](cli/generate) generates components with a template file. - You can override that by adding the "-t" (short for `inlineTemplate=true`) option: - - - ng generate component hero -t - - -
    - - -## Initialization - -The following example uses variable assignment to initialize the components. - - - - You could instead declare and initialize the properties using a constructor. - This app uses more terse "variable assignment" style simply for brevity. - - -{@a ngFor} - -## Add logic to loop through data - -The `*ngFor` directive (predefined by Angular) lets you loop through data. The following example uses the directive to show all of the values in an array property. - -To display a list of heroes, begin by adding an array of hero names to the component and redefine `myHero` to be the first name in the array. - - - - - -Now use the Angular `ngFor` directive in the template to display each item in the `heroes` list. - - - - - -This UI uses the HTML unordered list with `
      ` and `
    • ` tags. The `*ngFor` -in the `
    • ` element is the Angular "repeater" directive. -It marks that `
    • ` element (and its children) as the "repeater template": - - - - -
      - -Don't forget the leading asterisk (\*) in `*ngFor`. It is an essential part of the syntax. -Read more about `ngFor` and `*` in the [ngFor section](guide/built-in-directives#ngfor) of the [Built-in directives](guide/built-in-directives) page. - -
      - -Notice the `hero` in the `ngFor` double-quoted instruction; -it is an example of a template input variable. Read -more about template input variables in the [microsyntax](guide/built-in-directives#microsyntax) section of -the [Built-in directives](guide/built-in-directives) page. - -Angular duplicates the `
    • ` for each item in the list, setting the `hero` variable -to the item (the hero) in the current iteration. Angular uses that variable as the -context for the interpolation in the double curly braces. - -
      - -In this case, `ngFor` is displaying an array, but `ngFor` can -repeat items for any [iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) object. - -
      - -Now the heroes appear in an unordered list. - - - - -## Creating a class for the data - -The app's code defines the data directly inside the component, which isn't best practice. -In a simple demo, however, it's fine. - -At the moment, the binding is to an array of strings. -In real applications, most bindings are to more specialized objects. - -To convert this binding to use specialized objects, turn the array -of hero names into an array of `Hero` objects. For that you'll need a `Hero` class: - - - ng generate class hero - - -This command creates the following code. - - - - -You've defined a class with a constructor and two properties: `id` and `name`. - -It might not look like the class has properties, but it does. -The declaration of the constructor parameters takes advantage of a TypeScript shortcut. - -Consider the first parameter: - - - - -That brief syntax does a lot: - -* Declares a constructor parameter and its type. -* Declares a public property of the same name. -* Initializes that property with the corresponding argument when creating an instance of the class. - - -### Using the Hero class - -After importing the `Hero` class, the `AppComponent.heroes` property can return a _typed_ array -of `Hero` objects: - - - - - - -Next, update the template. -At the moment it displays the hero's `id` and `name`. -Fix that to display only the hero's `name` property. - - - - - -The display looks the same, but the code is clearer. - -{@a ngIf} - -## Conditional display with NgIf - -Sometimes an app needs to display a view or a portion of a view only under specific circumstances. - -Let's change the example to display a message if there are more than three heroes. - -The Angular `ngIf` directive inserts or removes an element based on a _truthy/falsy_ condition. -To see it in action, add the following paragraph at the bottom of the template: - - - - - -
      - -Don't forget the leading asterisk (\*) in `*ngIf`. It is an essential part of the syntax. -Read more about `ngIf` and `*` in the [ngIf section](guide/built-in-directives#ngIf) of the [Built-in directives](guide/built-in-directives) page. - -
      - - -The template expression inside the double quotes, -`*ngIf="heroes.length > 3"`, looks and behaves much like TypeScript. -When the component's list of heroes has more than three items, Angular adds the paragraph -to the DOM and the message appears. -If there are three or fewer items, Angular omits the paragraph, so no message appears. - -For more information, see [template expression operators](guide/interpolation#template-expressions). - - -
      - -Angular isn't showing and hiding the message. It is adding and removing the paragraph element from the DOM. That improves performance, especially in larger projects when conditionally including or excluding -big chunks of HTML with many data bindings. - -
      - -Try it out. Because the array has four items, the message should appear. -Go back into app.component.ts and delete or comment out one of the elements from the heroes array. -The browser should refresh automatically and the message should disappear. - - -## Summary -Now you know how to use: - -* **Interpolation** with double curly braces to display a component property. -* **ngFor** to display an array of items. -* A TypeScript class to shape the **model data** for your component and display properties of that model. -* **ngIf** to conditionally display a chunk of HTML based on a boolean expression. - -Here's the final code: - - - - - - - - - - - - - - - - - - - - diff --git a/aio/content/guide/elements.md b/aio/content/guide/elements.md index 7e84417df2037..28a2751f9d0a3 100644 --- a/aio/content/guide/elements.md +++ b/aio/content/guide/elements.md @@ -119,7 +119,14 @@ The recently-developed [custom elements](https://developer.mozilla.org/en-US/doc In browsers that support Custom Elements natively, the specification requires developers use ES2015 classes to define Custom Elements - developers can opt-in to this by setting the `target: "es2015"` property in their project's [TypeScript configuration file](/guide/typescript-configuration). As Custom Element and ES2015 support may not be available in all browsers, developers can instead choose to use a polyfill to support older browsers and ES5 code. -Use the [Angular CLI](cli) to automatically set up your project with the correct polyfill: `ng add @angular/elements --project=*your_project_name*`. +Use the [Angular CLI](cli) to automatically set up your project with the correct polyfill: + + + +ng add @angular/elements --project=*your_project_name* + + + - For more information about polyfills, see [polyfill documentation](https://www.webcomponents.org/polyfills). - For more information about Angular browser support, see [Browser Support](guide/browser-support). diff --git a/aio/content/guide/entry-components.md b/aio/content/guide/entry-components.md index fee65e466f855..fb73792aaa1ae 100644 --- a/aio/content/guide/entry-components.md +++ b/aio/content/guide/entry-components.md @@ -4,7 +4,7 @@ An entry component is any component that Angular loads imperatively, (which mean
      -To contrast the two types of components, there are components which are included in the template, which are declarative. Additionally, there are components which you load imperatively; that is, entry components. + To contrast the two types of components, there are components which are included in the template, which are declarative. Additionally, there are components which you load imperatively; that is, entry components.
      @@ -75,6 +75,11 @@ All router components must be entry components. Because this would require you t ## The `entryComponents` array +
      + + Since 9.0.0 with Ivy, the `entryComponents` property is no longer necessary. See [deprecations guide](guide/deprecations#entryComponents). + +
      Though the `@NgModule` decorator has an `entryComponents` array, most of the time you won't have to explicitly set any entry components because Angular adds components listed in `@NgModule.bootstrap` and those in route definitions to entry components automatically. Though these two mechanisms account for most entry components, if your app happens to bootstrap or dynamically load a component by type imperatively, diff --git a/aio/content/guide/event-binding.md b/aio/content/guide/event-binding.md index 40af4f6055ab7..dc17ec9b46955 100644 --- a/aio/content/guide/event-binding.md +++ b/aio/content/guide/event-binding.md @@ -99,7 +99,7 @@ in the `$event` variable. ## Template statements have side effects -Though [template expressions](guide/interpolation#template-expressions) shouldn't have [side effects](guide/property-binding#avoid-side-effects), template +Though [template expressions](guide/interpolation#template-expressions) shouldn't have [side effects](guide/property-binding-best-practices#avoid-side-effects), template statements usually do. The `deleteItem()` method does have a side effect: it deletes an item. diff --git a/aio/content/guide/feature-modules.md b/aio/content/guide/feature-modules.md index 0b8d5d137f34d..961c7915807c2 100644 --- a/aio/content/guide/feature-modules.md +++ b/aio/content/guide/feature-modules.md @@ -79,7 +79,7 @@ To incorporate the feature module into your app, you have to let the root module -Now the `AppModule` knows about the feature module. If you were to add any service providers to the feature module, `AppModule` would know about those too, as would any other feature modules. However, NgModules don’t expose their components. +Now the `AppModule` knows about the feature module. If you were to add any service providers to the feature module, `AppModule` would know about those too, as would any other feature modules. However, NgModules don’t expose their components by default. ## Rendering a feature module’s component template diff --git a/aio/content/guide/file-structure.md b/aio/content/guide/file-structure.md index e6ebea01673a9..6aad26517b3e0 100644 --- a/aio/content/guide/file-structure.md +++ b/aio/content/guide/file-structure.md @@ -40,8 +40,7 @@ The top level of the workspace contains workspace-wide configuration files, conf | `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. | | `src/` | Source files for the root-level application project. | | `node_modules/` | Provides [npm packages](guide/npm-packages) to the entire workspace. Workspace-wide `node_modules` dependencies are visible to all projects. | -| `tsconfig.json` | The `tsconfig.json` file is a ["Solution Style"](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#support-for-solution-style-tsconfigjson-files) TypeScript configuration file. Code editors and TypeScript’s language server use this file to improve development experience. Compilers do not use this file. | -| `tsconfig.base.json` | The base [TypeScript](https://www.typescriptlang.org/) configuration for projects in the workspace. All other configuration files inherit from this base file. For more information, see the [Configuration inheritance with extends](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#configuration-inheritance-with-extends) section of the TypeScript documentation.| +| `tsconfig.json` | The base [TypeScript](https://www.typescriptlang.org/) configuration for projects in the workspace. All other configuration files inherit from this base file. For more information, see the [Configuration inheritance with extends](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#configuration-inheritance-with-extends) section of the TypeScript documentation.| | `tslint.json` | Default [TSLint](https://palantir.github.io/tslint/) configuration for projects in the workspace. | @@ -96,14 +95,13 @@ Angular components, templates, and styles go here. | `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.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/package.json` | This file is generated only in applications created using `--strict` mode. This file is not used by package managers. It is used to tell the tools and bundlers whether the code under this directory is free of non-local [side-effects](guide/strict-mode#side-effect). | ### 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.base.json`, and project-specific [TSLint](https://palantir.github.io/tslint/) configuration files inherit from the workspace-wide `tslint.json`. +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 | | :--------------------- | :------------------------------------------| diff --git a/aio/content/guide/i18n.md b/aio/content/guide/i18n.md index 5d56815072c62..2a1b46901670a 100644 --- a/aio/content/guide/i18n.md +++ b/aio/content/guide/i18n.md @@ -766,8 +766,10 @@ The HTML `base` tag with the `href` attribute specifies the base URI, or URL, fo "i18n": { "sourceLocale": "en-US", "locales": { - "fr": "src/locale/messages.fr.xlf" - "baseHref": "" + "fr": { + "translation": "src/locale/messages.fr.xlf", + "baseHref": "" + } } }, "architect": { diff --git a/aio/content/guide/inputs-outputs.md b/aio/content/guide/inputs-outputs.md index 6841f7b7146b6..c1442c5c578c8 100644 --- a/aio/content/guide/inputs-outputs.md +++ b/aio/content/guide/inputs-outputs.md @@ -208,7 +208,7 @@ about the event and gives that data to the parent. The child's template has two controls. The first is an HTML `` with a [template reference variable](guide/template-reference-variables) , `#newItem`, where the user types in an item name. Whatever the user types -into the `` gets stored in the `#newItem` variable. +into the `` gets stored in the `value` property of the `#newItem` variable. @@ -218,7 +218,7 @@ an event binding because the part to the left of the equal sign is in parentheses, `(click)`. The `(click)` event is bound to the `addNewItem()` method in the child component class which -takes as its argument whatever the value of `#newItem` is. +takes as its argument whatever the value of `#newItem.value` property is. Now the child component has an `@Output()` for sending data to the parent and a method for raising an event. diff --git a/aio/content/guide/ivy-compatibility.md b/aio/content/guide/ivy-compatibility.md index ee4632316d5ec..025410c67f20b 100644 --- a/aio/content/guide/ivy-compatibility.md +++ b/aio/content/guide/ivy-compatibility.md @@ -11,11 +11,11 @@ That said, some applications will likely need to apply some manual updates. In version 10, [a few deprecated APIs have been removed](guide/updating-to-version-10#removals) and there are a [few breaking changes](guide/updating-to-version-10#breaking-changes) unrelated to Ivy. If you're seeing errors after updating to version 9, you'll first want to rule those changes out. -To do so, temporarily [turn off Ivy](guide/ivy#opting-out-of-angular-ivy) in your `tsconfig.base.json` and re-start your app. +To do so, temporarily [turn off Ivy](guide/ivy#opting-out-of-angular-ivy) in your `tsconfig.json` and re-start your app. If you're still seeing the errors, they are not specific to Ivy. In this case, you may want to consult the [general version 10 guide](guide/updating-to-version-10). If you've opted into any of the new, stricter type-checking settings, you may also want to check out the [template type-checking guide](guide/template-typecheck). -If the errors are gone, switch back to Ivy by removing the changes to the `tsconfig.base.json` and review the list of expected changes below. +If the errors are gone, switch back to Ivy by removing the changes to the `tsconfig.json` and review the list of expected changes below. {@a payload-size-debugging} ### Payload size debugging diff --git a/aio/content/guide/lazy-loading-ngmodules.md b/aio/content/guide/lazy-loading-ngmodules.md index 8931cf8b8e641..479c0a5567f34 100644 --- a/aio/content/guide/lazy-loading-ngmodules.md +++ b/aio/content/guide/lazy-loading-ngmodules.md @@ -87,7 +87,7 @@ To make one, enter the following command in the terminal, where `customers` is t ng generate module customers --route customers --module app.module -This creates a `customers` folder with the new lazy-loadable module `CustomersModule` defined in the `customers.module.ts` file. The command automatically declares the `CustomersComponent` inside the new feature module. +This creates a `customers` folder having the new lazy-loadable feature module `CustomersModule` defined in the `customers.module.ts` file and the routing module `CustomersRoutingModule` defined in the `customers-routing.module.ts` file. The command automatically declares the `CustomersComponent` and imports `CustomersRoutingModule` inside the new feature module. Because the new module is meant to be lazy-loaded, the command does NOT add a reference to the new feature module in the application's root module file, `app.module.ts`. Instead, it adds the declared route, `customers` to the `routes` array declared in the module provided as the `--module` option. diff --git a/aio/content/guide/lifecycle-hooks.md b/aio/content/guide/lifecycle-hooks.md index 68ce23394067a..be4695717a48c 100644 --- a/aio/content/guide/lifecycle-hooks.md +++ b/aio/content/guide/lifecycle-hooks.md @@ -62,6 +62,8 @@ Angular executes hook methods in the following sequence. You can use them to per Called before `ngOnInit()` and whenever one or more data-bound input properties change. + Note that if your component has no inputs or you use it without providing any inputs, the framework will not call `ngOnChanges()`. + diff --git a/aio/content/guide/lightweight-injection-tokens.md b/aio/content/guide/lightweight-injection-tokens.md index d8fc94dac4726..c401c6b917f53 100644 --- a/aio/content/guide/lightweight-injection-tokens.md +++ b/aio/content/guide/lightweight-injection-tokens.md @@ -141,7 +141,7 @@ Because the token is now an abstract class, and the injectable component impleme The implementation of the method (with all of its code overhead) resides in the injectable component that can be tree-shaken. This allows the parent to communicate with the child (if it is present) in a type-safe manner. -For example, the `LibCardComponent` now queries`LibHeaderToken` rather than `LibHeaderComponent`. +For example, the `LibCardComponent` now queries `LibHeaderToken` rather than `LibHeaderComponent`. The following example shows how the pattern allows `LibCardComponent` to communicate with the `LibHeaderComponent` without actually referring to `LibHeaderComponent`. ``` diff --git a/aio/content/guide/migration-solution-style-tsconfig.md b/aio/content/guide/migration-solution-style-tsconfig.md deleted file mode 100644 index 211ff5f98664a..0000000000000 --- a/aio/content/guide/migration-solution-style-tsconfig.md +++ /dev/null @@ -1,55 +0,0 @@ -# Solution-style `tsconfig.json` migration - -## What does this migration do? - -This migration adds support to existing projects for TypeScript's new ["solution-style" tsconfig feature](https://devblogs.microsoft.com/typescript/announcing-typescript-3-9/#solution-style-tsconfig). - -Support is added by making two changes: - -1. Renaming the workspace-level `tsconfig.json` to `tsconfig.base.json`. -All project [TypeScript configuration files](guide/typescript-configuration) will extend from this base which contains the common options used throughout the workspace. - -2. Adding the solution `tsconfig.json` file at the root of the workspace. -This `tsconfig.json` file will only contain references to project-level TypeScript configuration files and is only used by editors/IDEs. - -As an example, the solution `tsconfig.json` for a new project is as follows: -```json -// This is a "Solution Style" tsconfig.json file, and is used by editors and TypeScript’s language server to improve development experience. -// It is not intended to be used to perform a compilation. -{ - "files": [], - "references": [ - { - "path": "./tsconfig.app.json" - }, - { - "path": "./tsconfig.spec.json" - }, - { - "path": "./e2e/tsconfig.json" - } - ] -} -``` - -## Why is this migration necessary? - -Solution-style `tsconfig.json` files provide an improved editing experience and fix several long-standing defects when editing files in an IDE. -IDEs that leverage the TypeScript language service (for example, [Visual Studio Code](https://code.visualstudio.com)), will only use TypeScript configuration files that are named `tsconfig.json`. -In complex projects, there may be more than one compilation unit and each of these units may have different settings and options. - -With the Angular CLI, a project will have application code that will target a browser. -It will also have unit tests that should not be included within the built application and that also need additional type information present (`jasmine` in this case). -Both parts of the project also share some but not all of the code within the project. -As a result, two separate TypeScript configuration files (`tsconfig.app.json` and `tsconfig.spec.json`) are needed to ensure that each part of the application is configured properly and that the right types are used for each part. -Also if web workers are used within a project, an additional tsconfig (`tsconfig.worker.json`) is needed. -Web workers use similar but incompatible types to the main browser application. -This requires the additional configuration file to ensure that the web worker files use the appropriate types and will build successfully. - -While the Angular build system knows about all of these TypeScript configuration files, an IDE using TypeScript's language service does not. -Because of this, an IDE will not be able to properly analyze the code from each part of the project and may generate false errors or make suggestions that are incorrect for certain files. -By leveraging the new solution-style tsconfig, the IDE can now be aware of the configuration of each part of a project. -This allows each file to be treated appropriately based on its tsconfig. -IDE features such as error/warning reporting and auto-suggestion will operate more effectively as well. - -The TypeScript 3.9 release [blog post](https://devblogs.microsoft.com/typescript/announcing-typescript-3-9/#solution-style-tsconfig) also contains some additional information regarding this new feature. diff --git a/aio/content/guide/migration-update-module-and-target-compiler-options.md b/aio/content/guide/migration-update-module-and-target-compiler-options.md index 259f85d93a5fa..e5a2cd588b38c 100644 --- a/aio/content/guide/migration-update-module-and-target-compiler-options.md +++ b/aio/content/guide/migration-update-module-and-target-compiler-options.md @@ -9,7 +9,7 @@ This process helps ensure that intentional changes to the options are kept in pl TypeScript Configuration File(s) | Changed Property | Existing Value | New Value ------------- | ------------- | ------------- | ------------- | ------------- -`/tsconfig.base.json` | `"module"` | `"esnext"` | `"es2020"` +`/tsconfig.json` | `"module"` | `"esnext"` | `"es2020"` Used in `browser` builder options (`ng build` for applications) | `"module"` | `"esnext"` | `"es2020"` Used in `ng-packgr` builder options (`ng build` for libraries) | `"module"` | `"esnext"` | `"es2020"` Used in `karma` builder options (`ng test` for applications) | `"module"` | `"esnext"` | `"es2020"` diff --git a/aio/content/guide/ngmodule-faq.md b/aio/content/guide/ngmodule-faq.md index cc9c858776772..d8ccf16490480 100644 --- a/aio/content/guide/ngmodule-faq.md +++ b/aio/content/guide/ngmodule-faq.md @@ -101,7 +101,7 @@ should import `BrowserModule` from `@angular/platform-browser`. `BrowserModule` provides services that are essential to launch and run a browser app. `BrowserModule` also re-exports `CommonModule` from `@angular/common`, -which means that components in the `AppModule` module also have access to +which means that components in the `AppModule` also have access to the Angular directives every app needs, such as `NgIf` and `NgFor`. Do not import `BrowserModule` in any other module. @@ -140,7 +140,7 @@ declared in this NgModule. You _can_ export any declarable class—components, directives, and pipes—whether it's declared in this NgModule or in an imported NgModule. -You _can_ re-export entire imported NgModules, which effectively re-exports all of their exported classes. +You _can_ re-export entire imported NgModules, which effectively re-export all of their exported classes. An NgModule can even export a module that it doesn't import.
      @@ -192,7 +192,7 @@ Its only purpose is to add http service providers to the application as a whole. The `forRoot()` static method is a convention that makes it easy for developers to configure services and providers that are intended to be singletons. A good example of `forRoot()` is the `RouterModule.forRoot()` method. -Apps pass a `Routes` object to `RouterModule.forRoot()` in order to configure the app-wide `Router` service with routes. +Apps pass a `Routes` array to `RouterModule.forRoot()` in order to configure the app-wide `Router` service with routes. `RouterModule.forRoot()` returns a [ModuleWithProviders](api/core/ModuleWithProviders). You add that result to the `imports` list of the root `AppModule`. diff --git a/aio/content/guide/pipes.md b/aio/content/guide/pipes.md index 837765f5bbc52..f36ae52cd5900 100644 --- a/aio/content/guide/pipes.md +++ b/aio/content/guide/pipes.md @@ -397,7 +397,7 @@ The following code example binds an observable of message strings ## Caching HTTP requests To [communicate with backend services using HTTP](/guide/http "Communicating with backend services using HTTP"), the `HttpClient` service uses observables and offers the `HTTPClient.get()` method to fetch data from a server. -The aynchronous method sends an HTTP request, and returns an observable that emits the requested data for the response. +The asynchronous method sends an HTTP request, and returns an observable that emits the requested data for the response. As shown in the previous section, you can use the impure `AsyncPipe` to accept an observable as input and subscribe to the input automatically. You can also create an impure pipe to make and cache an HTTP request. diff --git a/aio/content/guide/property-binding-best-practices.md b/aio/content/guide/property-binding-best-practices.md new file mode 100644 index 0000000000000..8713d5d77b9f7 --- /dev/null +++ b/aio/content/guide/property-binding-best-practices.md @@ -0,0 +1,65 @@ +# Property binding best practices + +By following a few guidelines, you can use property binding in a way that helps you minimize bugs and keep your code readable. + +
      + +See the for a working example containing the code snippets in this guide. + +
      + +## Avoid side effects + +Evaluation of a template expression should have no visible side effects. +Use the syntax for template expressions to help avoid side effects. +In general, the correct syntax prevents you from assigning a value to anything in a property binding expression. +The syntax also prevents you from using increment and decrement operators. + +### An example of producing side effects + +If you had an expression that changed the value of something else that you were binding to, that change of value would be a side effect. +Angular might or might not display the changed value. +If Angular does detect the change, it throws an error. + +As a best practice, use only properties and methods that return values. + +## Return the proper type + +A template expression should evaluate to the type of value that the target property expects. +For example, return a string if the target property expects a string, a number if it expects a number, or an object if it expects an object. + +### Passing in a string + +In the following example, the `childItem` property of the `ItemDetailComponent` expects a string. + + + +You can confirm this expectation by looking in the `ItemDetailComponent` where the `@Input()` type is `string`: + + + +The `parentItem` in `AppComponent` is a string, which means that the expression, `parentItem` within `[childItem]="parentItem"`, evaluates to a string. + + + +If `parentItem` were some other type, you would need to specify `childItem` `@Input()` as that type as well. + +### Passing in an object + +In this example, `ItemListComponent` is a child component of `AppComponent` and the `items` property expects an array of objects. + + + +In the `ItemListComponent` the `@Input()`, `items`, has a type of `Item[]`. + + + +Notice that `Item` is an object that it has two properties; an `id` and a `name`. + + + +In `app.component.ts`, `currentItems` is an array of objects in the same shape as the `Item` object in `items.ts`, with an `id` and a `name`. + + + +By supplying an object in the same shape, you satisfy the expectations of `items` when Angular evaluates the expression `currentItems`. diff --git a/aio/content/guide/property-binding.md b/aio/content/guide/property-binding.md index 673be0e3dcf9d..c9240da7aec44 100644 --- a/aio/content/guide/property-binding.md +++ b/aio/content/guide/property-binding.md @@ -1,8 +1,8 @@ -# Property binding `[property]` +# Property binding -Use property binding to _set_ properties of target elements or -directive `@Input()` decorators. +Property binding in Angular helps you set values for properties of HTML elements or directives. +With property binding, you can do things such as toggle button functionality, set paths programatically, and share values between components.
      @@ -10,219 +10,194 @@ See the for a working example containing the code
      -## One-way in +## Prerequisites -Property binding flows a value in one direction, -from a component's property into a target element property. +To get the most out of property binding, you should be familiar with the following: -You can't use property -binding to read or pull values out of target elements. Similarly, you cannot use -property binding to call a method on the target element. -If the element raises events, you can listen to them with an [event binding](guide/event-binding). +* [Basics of components](guide/architecture-components) +* [Basics of templates](guide/glossary#template) +* [Binding syntax](guide/binding-syntax) -If you must read a target element property or call one of its methods, -see the API reference for [ViewChild](api/core/ViewChild) and -[ContentChild](api/core/ContentChild). +
      -## Examples +## Understanding the flow of data -The most common property binding sets an element property to a component -property value. An example is -binding the `src` property of an image element to a component's `itemImageUrl` property: +Property binding moves a value in one direction, from a component's property into a target element property. - +
      -Here's an example of binding to the `colSpan` property. Notice that it's not `colspan`, -which is the attribute, spelled with a lowercase `s`. +For more information on listening for events, see [Event binding](guide/event-binding). - +
      -For more details, see the [MDN HTMLTableCellElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement) documentation. +To read a target element property or call one of its methods, see the API reference for [ViewChild](api/core/ViewChild) and [ContentChild](api/core/ContentChild). -For more information about `colSpan` and `colspan`, see the [Attribute binding](guide/attribute-binding#colspan) guide. +## Binding to a property -Another example is disabling a button when the component says that it `isUnchanged`: +To bind to an element's property, enclose it in square brackets, `[]`, which identifies the property as a target property. +A target property is the DOM property to which you want to assign a value. +For example, the target property in the following code is the image element's `src` property. - + -Another is setting a property of a directive: - +In most cases, the target name is the name of a property, even when it appears to be the name of an attribute. +In this example, `src` is the name of the `` element property. -Yet another is setting the model property of a custom component—a great way -for parent and child components to communicate: +The brackets, `[]`, cause Angular to evaluate the right-hand side of the assignment as a dynamic expression. +Without the brackets, Angular treats the the right-hand side as a string literal and sets the property to that static value. - + -## Binding targets +Omitting the brackets renders the string `parentItem`, not the value of `parentItem`. -An element property between enclosing square brackets identifies the target property. -The target property in the following code is the image element's `src` property. +## Setting an element property to a component property value + +To bind the `src` property of an `` element to a component's property, place the target, `src`, in square brackets followed by an equal sign and then the property. +The property here is `itemImageUrl`. -There's also the `bind-` prefix alternative: +Declare the `itemImageUrl` property in the class, in this case `AppComponent`. - + +{@a colspan} -In most cases, the target name is the name of a property, even -when it appears to be the name of an attribute. -So in this case, `src` is the name of the `` element property. +#### `colspan` and `colSpan` -Element properties may be the more common targets, -but Angular looks first to see if the name is a property of a known directive, -as it is in the following example: +A common point of confusion is between the attribute, `colspan`, and the property, `colSpan`. +Notice that these two names differ by only a single letter. - +If you wrote something like this: -Technically, Angular is matching the name to a directive `@Input()`, -one of the property names listed in the directive's `inputs` array -or a property decorated with `@Input()`. -Such inputs map to the directive's own properties. + + <tr><td colspan="{{1 + 1}}">Three-Four</td></tr> + -If the name fails to match a property of a known directive or element, Angular reports an “unknown directive” error. +You'd get this error: -
      + + Template parse errors: + Can't bind to 'colspan' since it isn't a known native property + -Though the target name is usually the name of a property, -there is an automatic attribute-to-property mapping in Angular for -several common attributes. These include `class`/`className`, `innerHtml`/`innerHTML`, and -`tabindex`/`tabIndex`. +As the message says, the `` element does not have a `colspan` property. This is true +because `colspan` is an attribute—`colSpan`, with a capital `S`, is the +corresponding property. Interpolation and property binding can set only *properties*, not attributes. -
      +Instead, you'd use property binding and write it like this: + -## Avoid side effects -Evaluation of a template expression should have no visible side effects. -The expression language itself, or the way you write template expressions, -helps to a certain extent; -you can't assign a value to anything in a property binding expression -nor use the increment and decrement operators. +Another example is disabling a button when the component says that it `isUnchanged`: -For example, you could have an expression that invoked a property or method that had -side effects. The expression could call something like `getFoo()` where only you -know what `getFoo()` does. If `getFoo()` changes something -and you happen to be binding to that something, -Angular may or may not display the changed value. Angular may detect the -change and throw a warning error. -As a best practice, stick to properties and to methods that return -values and avoid side effects. + -## Return the proper type +Another is setting a property of a directive: -The template expression should evaluate to the type of value -that the target property expects. -Return a string if the target property expects a string, a number if it -expects a number, an object if it expects an object, and so on. + -In the following example, the `childItem` property of the `ItemDetailComponent` expects a string, which is exactly what you're sending in the property binding: +Yet another is setting the model property of a custom component—a great way +for parent and child components to communicate: -You can confirm this by looking in the `ItemDetailComponent` where the `@Input` type is set to a string: - - -As you can see here, the `parentItem` in `AppComponent` is a string, which the `ItemDetailComponent` expects: - - -### Passing in an object -The previous simple example showed passing in a string. To pass in an object, -the syntax and thinking are the same. +## Toggling button functionality -In this scenario, `ItemListComponent` is nested within `AppComponent` and the `items` property expects an array of objects. +To disable a button's functionality depending on a Boolean value, bind the DOM `disabled` property to a property in the class that is `true` or `false`. - + -The `items` property is declared in the `ItemListComponent` with a type of `Item` and decorated with `@Input()`: +Because the value of the property `isUnchanged` is `true` in the `AppComponent`, Angular disables the button. - + -In this sample app, an `Item` is an object that has two properties; an `id` and a `name`. - +## Setting a directive property -While a list of items exists in another file, `mock-items.ts`, you can -specify a different item in `app.component.ts` so that the new item will render: +To set a property of a directive, place the directive within square brackets , such as `[ngClass]`, followed by an equal sign and the property. +Here, the property is `classes`. - + -You just have to make sure, in this case, that you're supplying an array of objects because that's the type of `Item` and is what the nested component, `ItemListComponent`, expects. +To use the property, you must declare it in the class, which in this example is `AppComponent`. +The value of `classes` is `special`. -In this example, `AppComponent` specifies a different `item` object -(`currentItems`) and passes it to the nested `ItemListComponent`. `ItemListComponent` was able to use `currentItems` because it matches what an `Item` object is according to `item.ts`. The `item.ts` file is where -`ItemListComponent` gets its definition of an `item`. + -## Remember the brackets +Angular applies the class `special` to the `

      ` element so that you can use `special` to apply CSS styles. -The brackets, `[]`, tell Angular to evaluate the template expression. -If you omit the brackets, Angular treats the string as a constant -and *initializes the target property* with that string: +## Bind values between components - +To set the model property of a custom component, place the target, here `childItem`, between square brackets `[]` followed by an equal sign and the property. +Here, the property is `parentItem`. + -Omitting the brackets will render the string -`parentItem`, not the value of `parentItem`. +To use the target and the property, you must declare them in their respective classes. -## One-time string initialization +Declare the target of `childItem` in its component class, in this case `ItemDetailComponent`. -You *should* omit the brackets when all of the following are true: +For example, the following code declares the target of `childItem` in its component class, in this case `ItemDetailComponent`. -* The target property accepts a string value. -* The string is a fixed value that you can put directly into the template. -* This initial value never changes. +Then, the code contains an `@Input()` decorator with the `childItem` property so data can flow into it. -You routinely initialize attributes this way in standard HTML, and it works -just as well for directive and component property initialization. -The following example initializes the `prefix` property of the `StringInitComponent` to a fixed string, -not a template expression. Angular sets it and forgets about it. + - +Next, the code declares the property of `parentItem` in its component class, in this case `AppComponent`. +In this example the type of `childItem` is `string`, so `parentItem` needs to be a string. +Here, `parentItem` has the string value of `lamp`. -The `[item]` binding, on the other hand, remains a live binding to the component's `currentItems` property. + -## Property binding vs. interpolation +With this configuration, the view of `` uses the value of `lamp` for `childItem`. -You often have a choice between interpolation and property binding. -The following binding pairs do the same thing: +## Property binding and security - +Property binding can help keep content secure. +For example, consider the following malicious content. -Interpolation is a convenient alternative to property binding in -many cases. When rendering data values as strings, there is no -technical reason to prefer one form to the other, though readability -tends to favor interpolation. However, *when setting an element -property to a non-string data value, you must use property binding*. + -## Content security +The component template interpolates the content as follows: -Imagine the following malicious content. + - +The browser doesn't process the HTML and instead displays it raw, as follows. -In the component template, the content might be used with interpolation: + +"Template <script>alert("evil never sleeps")</script> Syntax" is the interpolated evil title. + - -Fortunately, Angular data binding is on alert for dangerous HTML. In the above case, -the HTML displays as is, and the Javascript does not execute. Angular **does not** -allow HTML with script tags to leak into the browser, neither with interpolation -nor property binding. +Angular does not allow HTML with ` Syntax" is the interpolated evil title. -"Template alert("evil never sleeps")Syntax" is the property bound evil title. +"Template Syntax" is the property bound evil title. + +## Property binding and interpolation + +Often [interpolation](guide/interpolation) and property binding can achieve the same results. +The following binding pairs do the same thing. + + + +You can use either form when rendering data values as strings, though interpolation is preferable for readability. +However, when setting an element property to a non-string data value, you must use property binding. + +


      + +## What's next + +* [Property binding best practices](guide/property-binding-best-practices) diff --git a/aio/content/guide/reactive-forms.md b/aio/content/guide/reactive-forms.md index ca73e5fad4657..353b88bf65a18 100644 --- a/aio/content/guide/reactive-forms.md +++ b/aio/content/guide/reactive-forms.md @@ -180,7 +180,7 @@ A form group tracks the status and changes for each of its controls, so if one o -Note that just as a form group contains a group of controls, the *profile form* `FormGroup` is bound to the `form` element with the `FormGroup` directive, creating a communication layer between the model and the form containing the inputs. The `formControlName` input provided by the `FormControlName` directive binds each individual input to the form control defined in `FormGroup`. The form controls communicate with their respective elements. They also communicate changes to the form group instance, which provides the source of truth for the model value. +Note that just as a form group contains a group of controls, the *profileForm* `FormGroup` is bound to the `form` element with the `FormGroup` directive, creating a communication layer between the model and the form containing the inputs. The `formControlName` input provided by the `FormControlName` directive binds each individual input to the form control defined in `FormGroup`. The form controls communicate with their respective elements. They also communicate changes to the form group instance, which provides the source of truth for the model value. **Save form data** diff --git a/aio/content/guide/releases.md b/aio/content/guide/releases.md index 1a42c7c5dd147..e4b87b0c8f12d 100644 --- a/aio/content/guide/releases.md +++ b/aio/content/guide/releases.md @@ -94,7 +94,7 @@ All of our major releases are supported for 18 months. * 6 months of *active support*, during which regularly-scheduled updates and patches are released. -* 12 months of *long-term support (LTS)*, during which only critical fixes and security patches are released. +* 12 months of *long-term support (LTS)*, during which only [critical fixes and security patches](#lts-fixes) are released. The following table provides the status for Angular versions under support. @@ -102,11 +102,18 @@ The following table provides the status for Angular versions under support. Version | Status | Released | Active Ends | LTS Ends ------- | ------ | ------------ | ------------ | ------------ ^10.0.0 | Active | Jun 24, 2020 | Dec 24, 2020 | Dec 24, 2021 -^9.0.0 | Active | Feb 06, 2020 | Aug 06, 2020 | Aug 06, 2021 +^9.0.0 | LTS | Feb 06, 2020 | Aug 06, 2020 | Aug 06, 2021 ^8.0.0 | LTS | May 28, 2019 | Nov 28, 2019 | Nov 28, 2020 Angular versions ^4.0.0, ^5.0.0, ^6.0.0 and ^7.0.0 are no longer under support. +### LTS fixes + +As a general rule, a fix is considered for an LTS version if it resolves one of: + +* a newly identified security vulnerability, +* a regression, since the start of LTS, caused by a 3rd party change, such as a new browser version. + {@a deprecation} ## Deprecation practices diff --git a/aio/content/guide/router-tutorial-toh.md b/aio/content/guide/router-tutorial-toh.md index b802cf38b6230..110762effac28 100644 --- a/aio/content/guide/router-tutorial-toh.md +++ b/aio/content/guide/router-tutorial-toh.md @@ -1656,7 +1656,7 @@ _before_ the `AppRoutingModule`: -Remove the initial crisis center route from the `app-routing.module.ts` because now the `HeroesModule` and the `CrisisCenter` modules provide teh feature routes. +Remove the initial crisis center route from the `app-routing.module.ts` because now the `HeroesModule` and the `CrisisCenter` modules provide the feature routes. The `app-routing.module.ts` file retains the top-level application routes such as the default and wildcard routes. diff --git a/aio/content/guide/router.md b/aio/content/guide/router.md index abf916b369359..b7aea18a7bbef 100644 --- a/aio/content/guide/router.md +++ b/aio/content/guide/router.md @@ -2,10 +2,9 @@ In a single-page app, you change what the user sees by showing or hiding portions of the display that correspond to particular components, rather than going out to the server to get a new page. As users perform application tasks, they need to move between the different [views](guide/glossary#view "Definition of view") that you have defined. -To implement this kind of navigation within the single page of your app, you use the Angular **`Router`**. -To handle the navigation from one [view](guide/glossary#view) to the next, you use the Angular _router_. -The router enables navigation by interpreting a browser URL as an instruction to change the view. +To handle the navigation from one [view](guide/glossary#view) to the next, you use the Angular **`Router`**. +The **`Router`** enables navigation by interpreting a browser URL as an instruction to change the view. To explore a sample app featuring the router's primary features, see the . diff --git a/aio/content/guide/rx-library.md b/aio/content/guide/rx-library.md index 8aed26dccef71..c5462381f8364 100644 --- a/aio/content/guide/rx-library.md +++ b/aio/content/guide/rx-library.md @@ -15,11 +15,11 @@ RxJS provides an implementation of the `Observable` type, which is needed until RxJS offers a number of functions that can be used to create new observables. These functions can simplify the process of creating observables from things such as events, timers, promises, and so on. For example: - + - + - + @@ -53,7 +53,7 @@ RxJS provides many operators, but only a handful are used frequently. For a list | Area | Operators | | :------------| :----------| -| Creation | `from`,`fromEvent`, `of` | +| Creation | `from`, `fromEvent`, `of` | | Combination | `combineLatest`, `concat`, `merge`, `startWith` , `withLatestFrom`, `zip` | | Filtering | `debounceTime`, `distinctUntilChanged`, `filter`, `take`, `takeUntil` | | Transformation | `bufferTime`, `concatMap`, `map`, `mergeMap`, `scan`, `switchMap` | diff --git a/aio/content/guide/service-worker-communications.md b/aio/content/guide/service-worker-communications.md index 384803216b029..d38287973b572 100644 --- a/aio/content/guide/service-worker-communications.md +++ b/aio/content/guide/service-worker-communications.md @@ -67,6 +67,33 @@ Therefore, it is recommended to reload the page once the promise returned by `ac +### Handling an unrecoverable state + +In some cases, the version of the app used by the service worker to serve a client might be in a broken state that cannot be recovered from without a full page reload. + +For example, imagine the following scenario: +- A user opens the app for the first time and the service worker caches the latest version of the app. + Let's assume the app's cached assets include `index.html`, `main..js` and `lazy-chunk..js`. +- The user closes the app and does not open it for a while. +- After some time, a new version of the app is deployed to the server. + This newer version includes the files `index.html`, `main..js` and `lazy-chunk..js` (note that the hashes are different now, because the content of the files has changed). + The old version is no longer available on the server. +- In the meantime, the user's browser decides to evict `lazy-chunk..js` from its cache. + Browsers may decide to evict specific (or all) resources from a cache in order to reclaim disk space. +- The user opens the app again. + The service worker serves the latest version known to it at this point, namely the old version (`index.html` and `main..js`). +- At some later point, the app requests the lazy bundle, `lazy-chunk..js`. +- The service worker is unable to find the asset in the cache (remember that the browser evicted it). + Nor is it able to retrieve it from the server (since the server now only has `lazy-chunk..js` from the newer version). + +In the above scenario, the service worker is not able to serve an asset that would normally be cached. +That particular app version is broken and there is no way to fix the state of the client without reloading the page. +In such cases, the service worker notifies the client by sending an `UnrecoverableStateEvent` event. +You can subscribe to `SwUpdate#unrecoverable` to be notified and handle these errors. + + + + ## More on Angular service workers You may also be interested in the following: diff --git a/aio/content/guide/service-worker-config.md b/aio/content/guide/service-worker-config.md index 389033844ed20..6135f2f2184cf 100644 --- a/aio/content/guide/service-worker-config.md +++ b/aio/content/guide/service-worker-config.md @@ -267,6 +267,12 @@ By default, these criteria are: 1. The URL must not contain a file extension (i.e. a `.`) in the last path segment. 2. The URL must not contain `__`. +
      + +To configure whether navigation requests are sent through to the network or not, see the [navigationRequestStrategy](#navigation-request-strategy) section. + +
      + ### Matching navigation request URLs While these default criteria are fine in most cases, it is sometimes desirable to configure different rules. For example, you may want to ignore specific routes (that are not part of the Angular app) and pass them through to the server. @@ -285,3 +291,32 @@ If the field is omitted, it defaults to: '!/**/*__*/**', // Exclude URLs containing `__` in any other segment. ] ``` + +{@a navigation-request-strategy} + +## `navigationRequestStrategy` + +This optional property enables you to configure how the service worker handles navigation requests: + +```json +{ + "navigationRequestStrategy": "freshness" +} +``` + +Possible values: + +- `'performance'`: The default setting. Serves the specified [index file](#index-file), which is typically cached. +- `'freshness'`: Passes the requests through to the network and falls back to the `performance` behavior when offline. + This value is useful when the server redirects the navigation requests elsewhere using an HTTP redirect (3xx status code). + Reasons for using this value include: + - Redirecting to an authentication website when authentication is not handled by the application. + - Redirecting specific URLs to avoid breaking existing links/bookmarks after a website redesign. + - Redirecting to a different website, such as a server-status page, while a page is temporarily down. + +
      + +The `freshness` strategy usually results in more requests sent to the server, which can increase response latency. +It is recommended that you use the default performance strategy whenever possible. + +
      \ No newline at end of file diff --git a/aio/content/guide/service-worker-getting-started.md b/aio/content/guide/service-worker-getting-started.md index a005edd9e177e..d947479f6265f 100644 --- a/aio/content/guide/service-worker-getting-started.md +++ b/aio/content/guide/service-worker-getting-started.md @@ -107,7 +107,7 @@ Notice that all of the files the browser needs to render this application are ca
      Pay attention to two key points: -1. The generated `ngsw-config.json` includes a limited list of cacheable fonts and images extentions. In some cases, you might want to modify the glob pattern to suit your needs. +1. The generated `ngsw-config.json` includes a limited list of cacheable fonts and images extensions. In some cases, you might want to modify the glob pattern to suit your needs. 1. If `resourcesOutputPath` or `assets` paths are modified after the generation of configuration file, you need to change the paths manually in `ngsw-config.json`.
      diff --git a/aio/content/guide/strict-mode.md b/aio/content/guide/strict-mode.md index 3cfe153cb959f..4b0961cf61f53 100644 --- a/aio/content/guide/strict-mode.md +++ b/aio/content/guide/strict-mode.md @@ -1,17 +1,15 @@ # Strict mode -When you create a new workspace or a project you have an option to create them in a strict mode using the `--strict` flag. +When you create a new workspace or an application you have an option to create them in a strict mode using the `--strict` flag. -Enabling this flag initializes your new workspace or project with a few new settings that improve maintainability, help you catch bugs ahead of time, and allow the CLI to perform advanced optimizations on your application. +Enabling this flag initializes your new workspace or application with a few new settings that improve maintainability, help you catch bugs ahead of time. Additionally, applications that use these stricter settings are easier to statically analyze, which can help the `ng update` command refactor code more safely and precisely when you are updating to future versions of Angular. Specifically, the `strict` flag does the following: * Enables [`strict` mode in TypeScript](https://www.staging-typescript.org/tsconfig#strict), as well as other strictness flags recommended by the TypeScript team. Specifically, `forceConsistentCasingInFileNames`, `noImplicitReturns`, `noFallthroughCasesInSwitch`. -* Turns on strict Angular compiler flags [`strictTemplates`](guide/angular-compiler-options#stricttemplates) and [`strictInjectionParameters`](guide/angular-compiler-options#strictinjectionparameters) -* [Bundle size budgets](guide/build#configuring-size-budgets) have been reduced by ~75% -* Turns on [`no-any` tslint rule](https://palantir.github.io/tslint/rules/no-any/) to prevent declarations of type `any` -* [Marks your application as side-effect free](https://webpack.js.org/guides/tree-shaking/#mark-the-file-as-side-effect-free) to enable more advanced tree-shaking +* Turns on strict Angular compiler flags [`strictTemplates`](guide/angular-compiler-options#stricttemplates), [`strictInjectionParameters`](guide/angular-compiler-options#strictinjectionparameters) and [`strictInputAccessModifiers`](guide/template-typecheck#troubleshooting-template-errors). +* [Bundle size budgets](guide/build#configuring-size-budgets) have been reduced by ~75%. You can apply these settings at the workspace and project level. @@ -30,17 +28,3 @@ To create a new application in the strict mode within an existing non-strict wor ng generate application [project-name] --strict - -{@a side-effect} - -### Non-local side effects in applications - -When you create projects and workspaces using the `strict` mode, you'll notice an additional `package.json` file, located in `src/app/` directory. -This file informs tools and bundlers that the code under this directory is free of non-local side effects. Non-local side effects in the application code are not common and using them is not considered a good coding pattern. -More importantly, code with these types of side effects cannot be optimized, resulting in increased bundle sizes and applications that load more slowly. - -If you need more information, the following links may be helpful. - -* [Tree-shaking](https://webpack.js.org/guides/tree-shaking/) -* [Dealing with side effects and pure functions in JavaScript](https://dev.to/vonheikemen/dealing-with-side-effects-and-pure-functions-in-javascript-16mg) -* [How to deal with dirty side effects in your pure function JavaScript](https://jrsinclair.com/articles/2018/how-to-deal-with-dirty-side-effects-in-your-pure-functional-javascript/) \ No newline at end of file diff --git a/aio/content/guide/style-precedence.md b/aio/content/guide/style-precedence.md new file mode 100644 index 0000000000000..be5d92150a365 --- /dev/null +++ b/aio/content/guide/style-precedence.md @@ -0,0 +1,133 @@ +# Style Precedence + +When there are multiple bindings to the same class name or style attribute, Angular uses a set of precedence rules to determine which classes or styles to apply to the element. +These rules specify an order for which style- and class-related bindings have priority. +This styling precedence is as follows, from the most specific with the highest priority to least specific with the lowest priorty: + +1. Template bindings are the most specific because they apply to the element directly and exclusively, so they have the highest precedence. + + + + + + + + + + + + + + + + + + + + + + + +
      Binding typeExample
      Property binding<div [class.foo]="hasFoo">
      <div [style.color]="color">
      Map binding<div [class]="classExpression">
      <div [style]="styleExpression">
      Static value<div class="foo">
      <div style="color: blue">
      +1. Directive host bindings are less specific because you can use directives in multiple locations, so they have a lower precedence than template bindings. + + + + + + + + + + + + + + + + + + + + + + + +
      Binding typeExample
      Property bindinghost: {'[class.foo]': 'hasFoo'}
      host: {'[style.color]': 'color'}
      Map bindinghost: {'[class]': 'classExpr'}
      host: {'[style]': 'styleExpr'}
      Static valuehost: {'class': 'foo'}
      host: {'style': 'color: blue'}
      +1. Component host bindings have the lowest precedence. + + + + + + + + + + + + + + + + + + + + + + + +
      Binding typeExample
      Property bindinghost: {'[class.foo]': 'hasFoo'}
      host: {'[style.color]': 'color'}
      Map bindinghost: {'[class]': 'classExpression'}
      host: {'[style]': 'styleExpression'}
      Static valuehost: {'class': 'foo'}
      host: {'style': 'color: blue'}
      + +## Precedence and specificity + +In the following example, binding to a specific class, as in `[class.special]`, takes precedence over a generic `[class]` binding. +Similarly, binding to a specific style, as in `[style.color]`, takes precedence over a generic `[style]` binding. + + + +## Precedence and bindings from different sources + +Specificity rules also apply to bindings even when they originate from different sources. +An element can have bindings that originate from its own template, from host bindings on matched directives, and from host bindings on matched components. + + + +## Precedence of bindings and static attributes + +Bindings take precedence over static attributes because they are dynamic. +In the following case, `class` and `[class]` have similar specificity, but the `[class]` binding takes precedence. + + + +{@a styling-delegation} + +## Delegating to styles with lower precedence + +Higher precedence styles can defer to lower precedence styles using `undefined` values. +For example, consider the following template: + + + +Imagine that the `dirWithHostBinding` directive and the `comp-with-host-binding` component both have a `[style.width]` host binding. + + + +If `dirWithHostBinding` sets its binding to `undefined`, the `width` property falls back to the value of the `comp-with-host-binding` host binding. + + +@HostBinding('style.width') +width = ''; // undefined + + +
      + + If `dirWithHostBinding` sets its binding to `null`, Angular removes the `width` property entirely. + + + @HostBinding('style.width') + width = null; + + +
      diff --git a/aio/content/guide/template-reference-variables.md b/aio/content/guide/template-reference-variables.md index 1f3fd5db2844d..31f2cd140e223 100644 --- a/aio/content/guide/template-reference-variables.md +++ b/aio/content/guide/template-reference-variables.md @@ -37,9 +37,9 @@ by HTML. -The reference value of itemForm, without the ngForm attribute value, would be +The reference value of `itemForm`, without the `ngForm` attribute value, would be the [HTMLFormElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement). -There is, however, a difference between a Component and a Directive in that a `Component` +There is, however, a difference between a `Component` and a `Directive` in that a `Component` will be referenced without specifying the attribute value, and a `Directive` will not change the implicit reference (that is, the element). diff --git a/aio/content/guide/template-typecheck.md b/aio/content/guide/template-typecheck.md index 5ef322932982e..d5612bb76a043 100644 --- a/aio/content/guide/template-typecheck.md +++ b/aio/content/guide/template-typecheck.md @@ -114,6 +114,7 @@ In case of a false positive like these, there are a few options: |Strictness flag|Effect| |-|-| |`strictInputTypes`|Whether the assignability of a binding expression to the `@Input()` field is checked. Also affects the inference of directive generic types. | +|`strictInputAccessModifiers`|Whether access modifiers such as `private`/`protected`/`readonly` are honored when assigning a binding expression to an `@Input()`. If disabled, the access modifiers of the `@Input` are ignored; only the type is checked.| |`strictNullInputTypes`|Whether `strictNullChecks` is honored when checking `@Input()` bindings (per `strictInputTypes`). Turning this off can be useful when using a library that was not built with `strictNullChecks` in mind.| |`strictAttributeTypes`|Whether to check `@Input()` bindings that are made using text attributes (for example, `` vs ``). |`strictSafeNavigationTypes`|Whether the return type of safe navigation operations (for example, `user?.name`) will be correctly inferred based on the type of `user`). If disabled, `user?.name` will be of type `any`. diff --git a/aio/content/guide/testing-components-basics.md b/aio/content/guide/testing-components-basics.md index ca70d13559529..316aba4f6d5e7 100644 --- a/aio/content/guide/testing-components-basics.md +++ b/aio/content/guide/testing-components-basics.md @@ -375,6 +375,5 @@ Some noteworthy observations: When you're filtering by CSS selector and only testing properties of a browser's _native element_, the `By.css` approach may be overkill. It's often easier and more clear to filter with a standard `HTMLElement` method -such as `querySelector()` or `querySelectorAll()`, -as you'll see in the next set of tests. +such as `querySelector()` or `querySelectorAll()`. diff --git a/aio/content/guide/testing-components-scenarios.md b/aio/content/guide/testing-components-scenarios.md index fb0ec07f9ee00..28e40876a8f44 100644 --- a/aio/content/guide/testing-components-scenarios.md +++ b/aio/content/guide/testing-components-scenarios.md @@ -190,7 +190,7 @@ It knows who the user is based on a property of the injected `UserService`: The `WelcomeComponent` has decision logic that interacts with the service, logic that makes this component worth testing. -Here's the testing module configuration for the spec file, `app/welcome/welcome.component.spec.ts`: +Here's the testing module configuration for the spec file: @@ -415,7 +415,7 @@ You do have to call [tick()](api/core/testing/tick) to advance the (virtual) clo Calling [tick()](api/core/testing/tick) simulates the passage of time until all pending asynchronous activities finish. In this case, it waits for the error handler's `setTimeout()`. -The [tick()](api/core/testing/tick) function accepts milliseconds and tickOptions as parameters, the millisecond (defaults to 0 if not provided) parameter represents how much the virtual clock advances. For example, if you have a `setTimeout(fn, 100)` in a `fakeAsync()` test, you need to use tick(100) to trigger the fn callback. The tickOptions is an optional parameter with a property called `processNewMacroTasksSynchronously` (defaults to true) represents whether to invoke new generated macro tasks when ticking. +The [tick()](api/core/testing/tick) function accepts milliseconds and tickOptions as parameters, the millisecond (defaults to 0 if not provided) parameter represents how much the virtual clock advances. For example, if you have a `setTimeout(fn, 100)` in a `fakeAsync()` test, you need to use tick(100) to trigger the fn callback. The tickOptions is an optional parameter with a property called `processNewMacroTasksSynchronously` (defaults to true) that represents whether to invoke new generated macro tasks when ticking. The `TestBed.compileComponents()` method (see [below](#compile-components)) calls `XHR` @@ -1231,7 +1226,7 @@ and provide for _all_ services injected in _any_ component in the tree. That's too much effort just to answer a few simple questions about links. This section describes two techniques for minimizing the setup. -Use them, alone or in combination, to stay focused on the testing the primary component. +Use them, alone or in combination, to stay focused on testing the primary component. {@a stub-component} @@ -1340,7 +1335,7 @@ The `HostListener` wires the click event of the host element Clicking the anchor should trigger the `onClick()` method, which sets the stub's telltale `navigatedTo` property. Tests inspect `navigatedTo` to confirm that clicking the anchor -set the expected route definition. +sets the expected route definition.
      @@ -1573,7 +1568,7 @@ calls to other `TestBed` static methods such as `compileComponents()`. In this example, the `BannerComponent` is the only component to compile. Other examples configure the testing module with multiple components and may import application modules that hold yet more components. -Any of them could be require external files. +Any of them could require external files. The `TestBed.compileComponents` method asynchronously compiles all components configured in the testing module. diff --git a/aio/content/guide/testing-utility-apis.md b/aio/content/guide/testing-utility-apis.md index 0c1b6ddd12925..b79419a60fa37 100644 --- a/aio/content/guide/testing-utility-apis.md +++ b/aio/content/guide/testing-utility-apis.md @@ -19,7 +19,7 @@ Here's a summary of the stand-alone functions, in order of likely utility: - async + waitForAsync diff --git a/aio/content/guide/testing.md b/aio/content/guide/testing.md index a0ded806165f9..d601187525724 100644 --- a/aio/content/guide/testing.md +++ b/aio/content/guide/testing.md @@ -75,7 +75,7 @@ The tests run again, the browser refreshes, and the new test results appear. The CLI takes care of Jasmine and Karma configuration for you. -You can fine-tune many options by editing the `karma.conf.js` and +You can fine-tune many options by editing the `karma.conf.js` in the root folder of the project and the `test.ts` files in the `src/` folder. The `karma.conf.js` file is a partial Karma configuration file. @@ -217,7 +217,7 @@ script: - npm run e2e -- --protractor-config=e2e/protractor-ci.conf.js ``` -This does the same things as the Circle CI configuration, except that Travis doesn't come with Chrome, so we use Chromium instead. +This does the same things as the CircleCI configuration, except that Travis doesn't come with Chrome, so use Chromium instead. Step 2: Commit your changes and push them to your repository. diff --git a/aio/content/guide/typescript-configuration.md b/aio/content/guide/typescript-configuration.md index 3561008b200aa..1d058045c33f6 100644 --- a/aio/content/guide/typescript-configuration.md +++ b/aio/content/guide/typescript-configuration.md @@ -18,32 +18,7 @@ that are important to Angular developers, including details about the following ## Configuration files A given Angular workspace contains several TypeScript configuration files. -At the root level, there are two main TypeScript configuration files: a `tsconfig.json` file and a `tsconfig.base.json` file. - -The `tsconfig.json` file is a ["Solution Style"](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#support-for-solution-style-tsconfigjson-files) TypeScript configuration file. -Code editors and TypeScript’s language server use this file to improve development experience. -Compilers do not use this file. - -The `tsconfig.json` file contains a list of paths to the other TypeScript configuration files used in the workspace. - - -{ - "files": [], - "references": [ - { - "path": "./tsconfig.app.json" - }, - { - "path": "./tsconfig.spec.json" - }, - { - "path": "./projects/my-lib/tsconfig.lib.json" - } - ] -} - - -The `tsconfig.base.json` file specifies the base TypeScript and Angular compiler options that all projects in the workspace inherit. +At the root `tsconfig.json` file specifies the base TypeScript and Angular compiler options that all projects in the workspace inherit. The TypeScript and Angular have a wide range of options which can be used to configure type-checking features and generated output. For more information, see the [Configuration inheritance with extends](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#configuration-inheritance-with-extends) section of the TypeScript documentation. @@ -55,9 +30,9 @@ For details about configuration inheritance, see the [Configuration inheritance
      -The initial `tsconfig.base.json` for an Angular workspace typically looks like the following example. +The initial `tsconfig.json` for an Angular workspace typically looks like the following example. - + { "compileOnSave": false, "compilerOptions": { diff --git a/aio/content/guide/universal.md b/aio/content/guide/universal.md index d9f1bea9df9f7..a96a9788df50f 100644 --- a/aio/content/guide/universal.md +++ b/aio/content/guide/universal.md @@ -48,8 +48,7 @@ src/ app/ ... application code app.server.module.ts * server-side application module server.ts * express web server -tsconfig.json TypeScript solution style configuration -tsconfig.base.json TypeScript base configuration +tsconfig.json TypeScript base configuration tsconfig.app.json TypeScript browser application configuration tsconfig.server.json TypeScript server application configuration tsconfig.spec.json TypeScript tests configuration diff --git a/aio/content/guide/updating-to-version-10.md b/aio/content/guide/updating-to-version-10.md index 24abe1fa4001b..b8e62cd679898 100644 --- a/aio/content/guide/updating-to-version-10.md +++ b/aio/content/guide/updating-to-version-10.md @@ -37,10 +37,10 @@ If you're curious about the specific migrations being run by the CLI, see the [a {@a deprecations} ### New Deprecations -| Area | API or Feature | May be removed in | -| ----------------------------- | --------------------------------------------------------------------------- | ----------------- | -| `@angular/core` | [`WrappedValue`](guide/deprecations#wrapped-value) | v12 | -| browser support | [`IE 9, 10, and IE Mobile`](guide/deprecations#ie-9-10-and-ie-mobile-support) | v11 | +| Area | API or Feature | May be removed in | +| ----------------------------- | -------------------------------------------------- | ----------------- | +| `@angular/core` | [`WrappedValue`](guide/deprecations#wrapped-value) | v12 | +| browser support | IE 9, 10, and IE Mobile | v11 | {@a removals} @@ -77,6 +77,5 @@ Read about the migrations the CLI handles for you automatically: * [Migrating missing `@Directive()`/`@Component()` decorators](guide/migration-undecorated-classes) * [Migrating `ModuleWithProviders`](guide/migration-module-with-providers) -* [Solution-style `tsconfig.json` migration](guide/migration-solution-style-tsconfig) * [`tslib` direct dependency migration](guide/migration-update-libraries-tslib) * [Update `module` and `target` compiler options migration](guide/migration-update-module-and-target-compiler-options) diff --git a/aio/content/guide/upgrade.md b/aio/content/guide/upgrade.md index 93ec769c97de3..3293f4eb12595 100644 --- a/aio/content/guide/upgrade.md +++ b/aio/content/guide/upgrade.md @@ -479,6 +479,15 @@ using the `downgradeComponent()` method. The result is an AngularJS +
      + +By default, Angular change detection will also run on the component for every +AngularJS `$digest` cycle. If you wish to only have change detection run when +the inputs change, you can set `propagateDigest` to `false` when calling +`downgradeComponent()`. + +
      + Because `HeroDetailComponent` is an Angular component, you must also add it to the `declarations` in the `AppModule`. diff --git a/aio/content/guide/user-input.md b/aio/content/guide/user-input.md index e5aacd44436cd..19907e16a1a73 100644 --- a/aio/content/guide/user-input.md +++ b/aio/content/guide/user-input.md @@ -234,8 +234,8 @@ To fix this issue, listen to both the _Enter_ key and the _blur_ event. ## Put it all together -The previous page showed how to [display data](guide/displaying-data). -This page demonstrated event binding techniques. + +This page demonstrated several event binding techniques. Now, put it all together in a micro-app that can display a list of heroes and add new heroes to the list. @@ -324,5 +324,5 @@ These techniques are useful for small-scale demonstrations, but they quickly become verbose and clumsy when handling large amounts of user input. Two-way data binding is a more elegant and compact way to move values between data entry fields and model properties. -The next page, `Forms`, explains how to write +The [`Forms`](guide/forms-overview) page explains how to write two-way bindings with `NgModel`. diff --git a/aio/content/guide/using-libraries.md b/aio/content/guide/using-libraries.md index caf43ea7f94a2..07d3c9ebbe96e 100644 --- a/aio/content/guide/using-libraries.md +++ b/aio/content/guide/using-libraries.md @@ -32,7 +32,7 @@ To do this: 1. Create a `typings.d.ts` file in your `src/` folder. This file is automatically included as global type definition. -2. Add the following code in `src/typings.d.ts`. +2. Add the following code in `src/typings.d.ts`: ``` declare module 'host' { @@ -45,7 +45,7 @@ declare module 'host' { } ``` -3. In the component or file that uses the library, add the following code. +3. In the component or file that uses the library, add the following code: ``` import * as host from 'host'; @@ -129,7 +129,7 @@ interface JQuery { } ``` -If don't add the interface for the script-defined extension, your IDE shows an error: +If you don't add the interface for the script-defined extension, your IDE shows an error: ``` [TS][Error] Property 'myPlugin' does not exist on type 'JQuery' diff --git a/aio/content/guide/view-encapsulation.md b/aio/content/guide/view-encapsulation.md new file mode 100644 index 0000000000000..b0e95d4eca4f6 --- /dev/null +++ b/aio/content/guide/view-encapsulation.md @@ -0,0 +1,81 @@ +# View encapsulation + +In Angular, component CSS styles are encapsulated into the component's view and don't +affect the rest of the application. + +To control how this encapsulation happens on a *per +component* basis, you can set the *view encapsulation mode* in the component metadata. +Choose from the following modes: + +* `ShadowDom` view encapsulation uses the browser's native shadow DOM implementation (see + [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Shadow_DOM) + on the [MDN](https://developer.mozilla.org) site) + to attach a shadow DOM to the component's host element, and then puts the component + view inside that shadow DOM. The component's styles are included within the shadow DOM. + +* `Emulated` view encapsulation (the default) emulates the behavior of shadow DOM by preprocessing + (and renaming) the CSS code to effectively scope the CSS to the component's view. + For details, see [Inspecting generated CSS](guide/view-encapsulation#inspect-generated-css) below. + +* `None` means that Angular does no view encapsulation. + Angular adds the CSS to the global styles. + The scoping rules, isolations, and protections discussed earlier don't apply. + This is essentially the same as pasting the component's styles into the HTML. + +To set the components encapsulation mode, use the `encapsulation` property in the component metadata: + + + +`ShadowDom` view encapsulation only works on browsers that have native support +for shadow DOM (see [Shadow DOM v1](https://caniuse.com/#feat=shadowdomv1) on the +[Can I use](http://caniuse.com) site). The support is still limited, +which is why `Emulated` view encapsulation is the default mode and recommended +in most cases. + +{@a inspect-generated-css} + +## Inspecting generated CSS + +When using emulated view encapsulation, Angular preprocesses +all component styles so that they approximate the standard shadow CSS scoping rules. + +In the DOM of a running Angular application with emulated view +encapsulation enabled, each DOM element has some extra attributes +attached to it: + + + <hero-details _nghost-pmm-5> + <h2 _ngcontent-pmm-5>Mister Fantastic</h2> + <hero-team _ngcontent-pmm-5 _nghost-pmm-6> + <h3 _ngcontent-pmm-6>Team</h3> + </hero-team> + </hero-detail> + + + +There are two kinds of generated attributes: + +* An element that would be a shadow DOM host in native encapsulation has a + generated `_nghost` attribute. This is typically the case for component host elements. +* An element within a component's view has a `_ngcontent` attribute +that identifies to which host's emulated shadow DOM this element belongs. + +The exact values of these attributes aren't important. They are automatically +generated and you never refer to them in application code. But they are targeted +by the generated component styles, which are in the `` section of the DOM: + + + [_nghost-pmm-5] { + display: block; + border: 1px solid black; + } + + h3[_ngcontent-pmm-6] { + background-color: white; + border: 1px solid #777; + } + + +These styles are post-processed so that each selector is augmented +with `_nghost` or `_ngcontent` attribute selectors. +These extra selectors enable the scoping rules described in this page. diff --git a/aio/content/guide/web-worker.md b/aio/content/guide/web-worker.md index cdf2dd8a8e3a6..8151625e987a8 100644 --- a/aio/content/guide/web-worker.md +++ b/aio/content/guide/web-worker.md @@ -14,12 +14,16 @@ The CLI does not support running Angular itself in a web worker. To add a web worker to an existing project, use the Angular CLI `ng generate` command. -`ng generate web-worker` *location* +```bash +ng generate web-worker +``` You can add a web worker anywhere in your application. For example, to add a web worker to the root component, `src/app/app.component.ts`, run the following command. -`ng generate web-worker app` +```bash +ng generate web-worker app +``` The command performs the following actions. diff --git a/aio/content/guide/zone.md b/aio/content/guide/zone.md index 7b17ef9b8a28c..acafca0602b44 100644 --- a/aio/content/guide/zone.md +++ b/aio/content/guide/zone.md @@ -9,7 +9,7 @@ To understand the benefits of `NgZone`, it is important to have a clear grasp of ### Displaying and updating data in Angular -In Angular, you can [display data](guide/displaying-data) by binding controls in an HTML template to the properties of an Angular component. +In Angular, you can display data by binding controls in an HTML template to the properties of an Angular component. @@ -102,13 +102,13 @@ In Angular, this step is unnecessary. Whenever you update the data, your HTML is To understand how change detection works, first consider when the application needs to update the HTML. Typically, updates occur for one of the following reasons: -1. Component initialization. For example, when bootstrapping an Angular application, Angular loads the bootstrap component and triggers the [ApplicationRef.tick()](api/core/ApplicationRef#tick) to call change detection and View Rendering. Just as in the [displaying data](guide/displaying-data) sample, the `AppComponent` is the bootstrap component. This component has the properties `title` and `myHero`, which the application renders in the HTML. +1. Component initialization. For example, when bootstrapping an Angular application, Angular loads the bootstrap component and triggers the [ApplicationRef.tick()](api/core/ApplicationRef#tick) to call change detection and View Rendering. -2. Event listener. The DOM event listener can update the data in an Angular component and also trigger change detection, as in the following example. +1. Event listener. The DOM event listener can update the data in an Angular component and also trigger change detection, as in the following example. -3. HTTP Data Request. You can also get data from a server through an HTTP request. For example: +1. HTTP Data Request. You can also get data from a server through an HTTP request. For example: ```typescript @Component({ diff --git a/aio/content/images/bios/fmalcher.jpg b/aio/content/images/bios/fmalcher.jpg new file mode 100755 index 0000000000000..8c12213cdca8e Binary files /dev/null and b/aio/content/images/bios/fmalcher.jpg differ diff --git a/aio/content/images/bios/jessicajaniuk.jpg b/aio/content/images/bios/jessicajaniuk.jpg new file mode 100644 index 0000000000000..6026d84611a1d Binary files /dev/null and b/aio/content/images/bios/jessicajaniuk.jpg differ diff --git a/aio/content/images/bios/johanneshoppe.jpg b/aio/content/images/bios/johanneshoppe.jpg new file mode 100755 index 0000000000000..83ec2461c9699 Binary files /dev/null and b/aio/content/images/bios/johanneshoppe.jpg differ diff --git a/aio/content/images/bios/sajee.jpg b/aio/content/images/bios/sajee.jpg index bbdfa0926dc6c..820c92bacfcd8 100644 Binary files a/aio/content/images/bios/sajee.jpg and b/aio/content/images/bios/sajee.jpg differ diff --git a/aio/content/images/bios/samvloeberghs.jpg b/aio/content/images/bios/samvloeberghs.jpg new file mode 100644 index 0000000000000..b88025ebfb5c4 Binary files /dev/null and b/aio/content/images/bios/samvloeberghs.jpg differ diff --git a/aio/content/images/bios/thekiba.jpg b/aio/content/images/bios/thekiba.jpg new file mode 100644 index 0000000000000..0edab3bff9f72 Binary files /dev/null and b/aio/content/images/bios/thekiba.jpg differ diff --git a/aio/content/images/marketing/home/loved-by-millions.svg b/aio/content/images/marketing/home/loved-by-millions.svg index e3d5c67832d45..d2e8cfd240e51 100644 --- a/aio/content/images/marketing/home/loved-by-millions.svg +++ b/aio/content/images/marketing/home/loved-by-millions.svg @@ -1,571 +1,175 @@ - - - - Loved by Millions Copy - Created with Sketch. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + Loved by Millions + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/aio/content/marketing/contributors.json b/aio/content/marketing/contributors.json index 98d8b337febc5..f3ba0d7a40ca6 100644 --- a/aio/content/marketing/contributors.json +++ b/aio/content/marketing/contributors.json @@ -53,6 +53,9 @@ }, "kyliau": { "name": "Keen Yee Liau", + "twitter": "liauky", + "website": "https://github.com/kyliau", + "bio": "Keen works on language service and CLI. He also maintains Karma and Protractor.", "groups": ["Angular"], "lead": "igorminar", "picture": "kyliau.jpg" @@ -86,24 +89,6 @@ "groups": ["Angular"], "lead": "kara" }, - "matsko": { - "name": "Matias Niemela", - "picture": "matias.jpg", - "twitter": "yearofmoo", - "website": "http://yearofmoo.com", - "bio": "Matias Niemela is a fullstack web developer who has been programming & building websites for over 10 years, and a core team member of AngularJS for two years. In the spring of 2015 Matias joined Angular full time at Google. In his free time Matias loves to build complex things and is always up for public speaking, travelling and tweaking his current Vim setup.", - "groups": ["Angular"], - "lead": "kara" - }, - "kara": { - "name": "Kara Erickson", - "picture": "kara-erickson.jpg", - "twitter": "karaforthewin", - "website": "https://github.com/kara", - "bio": "Kara is a software engineer on the Angular team at Google and a co-organizer of the Angular-SF Meetup. Prior to Google, she helped build UI components in Angular for guest management systems at OpenTable. She enjoys snacking indiscriminately and probably other things too.", - "groups": ["Angular"], - "lead": "igorminar" - }, "pkozlowski-opensource": { "name": "Pawel Kozlowski", "picture": "pawel.jpg", @@ -476,8 +461,8 @@ "name": "Sajeetharan Sinnathurai", "picture": "sajee.jpg", "twitter": "kokkisajee", - "website": "https://sajeetharan.herokuapp.com/", - "bio": "Sajeetharan is a Developer, Top contributor on stackoverflow for #Angular, ng-SriLanka organizer. He makes use of his extensive knowledge over the past years to contribute to community to make the world a better place.", + "website": "https://sajeetharan.com/", + "bio": "Sajeetharan is a Cloud Architect, Top contributor on stackoverflow for #Angular, ng-SriLanka organizer. He makes use of his extensive knowledge over the past years to contribute to community to make the world a better place.", "groups": ["GDE"] }, "lacolaco": { @@ -618,26 +603,6 @@ "bio": "Justin (aka Schwarty) is a Google Developer Expert in Web Technologies and Angular, the host and maintainer of the weekly AngularAir live video broadcast, educator, writer and content creator. He has Angular courses available on LinkedIn Learning and Pluralsight and loves passing on years of full stack development knowledge to help empower others to find their inner awesomeness!", "groups": ["GDE"] }, - "dennispbrown": { - "name": "Denny Brown", - "picture": "denny.jpg", - "bio": "Denny is founder of Expert Support, a professional services firm specializing in technical communication, and leads the Angular technical writing team. His lifelong passion has been to reduce the time and effort required to understand complex technical information. Early on, he was Associate Chairman of the Computer Science Department at Stanford, where he taught introductory courses in programming. He also plays old-timers baseball in local leagues and national tournaments.", - "groups": ["Angular"], - "lead": "aikidave" - }, - "jbogarthyde": { - "name": "Judy Bogart", - "picture": "judy.png", - "groups": ["Angular"], - "lead": "dennispbrown" - }, - "rockument69": { - "name": "Tony Bove", - "picture": "rockument69.jpg", - "bio": "Tony is a technical writer with Expert Support. His lifelong passions are helping people use technology, writing fiction, and playing music. When he's not working or playing the harmonica with friends in a bluegrass band, he's swimming and snorkeling on a Kauai beach and playing ball with his Irish Wolfhound. He's worked at home for decades before it became a thing.", - "groups": ["Angular"], - "lead": "aikidave" - }, "kapunahelewong": { "name": "Kapunahele Wong", "picture": "kapunahele.jpg", @@ -751,9 +716,9 @@ "santosh": { "name": "Santosh Yadav", "picture": "santoshyadav.jpg", - "twitter": "Santosh19742211", + "twitter": "SantoshYadavDev", "website": "https://www.santoshyadav.dev", - "bio": "Santosh is a GDE for Angular and Web Technologies and loves to contribute to Open Source. He is the creator of ng deploy for netlify and core team member for NestJS Addons. He writes for AngularInDepth, mentors for DotNetTricks, organizes Pune Tech Meetup, and conducts free workshops on Angular.", + "bio": "Santosh is a GDE for Angular and loves to contribute to Open Source. He is the creator of ng deploy for netlify and core team member for NestJS Addons. He writes for AngularInDepth, mentors for DotNetTricks, organizes Pune Tech Meetup, and conducts free workshops on Angular.", "groups": ["GDE"] }, "josephperrott": { @@ -848,5 +813,46 @@ "website": "kreuzercode.com", "bio": "Kevin is a passionate freelance front-end engineer and Google Developer Expert based in Switzerland. He is a JavaScript enthusiast and fascinated by Angular. Kevin always tries to learn new things, expand his knowledge, and share it with others in the form of blog posts, workshops, podcasts, or presentations. He is a writer for various publications and the most active writer on Angular in-depth in 2019. Contributing to multiple projects and maintaining 7 npm packages, Kevin is also a big believer in open source. Furthermore, Kevin is a big football fan. Since his childhood, he has supported Real Madrid, which you might notice in a lot of his blog posts and tutorials.", "groups": ["GDE"] + }, + "samvloeberghs": { + "name": "Sam Vloeberghs", + "picture": "samvloeberghs.jpg", + "groups": ["GDE"], + "twitter": "samvloeberghs", + "website": "https://samvloeberghs.be", + "bio": "Sam is a freelance software architect and Internet entrepreneur, currently focusing on frontend technologies. Co-organiser of the Belgian Angular conference NG-BE and Angular Belgium Meetup group." + }, + "thekiba": { + "name": "Andrew Grekov", + "picture": "thekiba.jpg", + "twitter": "thekiba_io", + "website": "https://thekiba.io", + "bio": "Andrew is a software engineer using Angular and .NET. He spends most of his spare time staying up-to-date, helping other people, and experimenting with web tech.", + "groups": ["GDE"] + }, + "fmalcher": { + "name": "Ferdinand Malcher", + "picture": "fmalcher.jpg", + "twitter": "fmalcher01", + "website": "https://angular.schule", + "bio": "Ferdinand is a developer, trainer, and international speaker from Leipzig, Germany. He is co-author of the German Angular book and loves to share knowledge – that's why he writes books and blog posts, speaks at meetups and conferences, does Angular training and works as a consultant in his company \"Angular.Schule\".", + "groups": ["GDE"] + }, + "johanneshoppe": { + "name": "Johannes Hoppe", + "picture": "johanneshoppe.jpg", + "twitter": "johanneshoppe", + "website": "https://angular.schule", + "bio": "Johannes works as a software architect and consultant for Angular. He is co-author of the German Angular book and a passionate speaker. With his company \"Angular.Schule\" he offers public Angular training and consulting. Johannes is head of the Angular Meetup in Heidelberg, Germany, and is engaged in a couple of open source projects.", + "groups": ["GDE"] + }, + "jessicajaniuk": { + "name": "Jessica Janiuk", + "picture": "jessicajaniuk.jpg", + "twitter": "thepunderwoman", + "website": "https://github.com/jessicajaniuk", + "bio": "Jessica is a software engineer at Google. In her free time she is a historical fencer, astromech droid builder, photographer, pun purveyor, occasional cosplayer, and full time cat mom.", + "groups": ["Angular"], + "lead": "jelbourn" } } diff --git a/aio/content/marketing/events.json b/aio/content/marketing/events.json new file mode 100644 index 0000000000000..4526b786fad82 --- /dev/null +++ b/aio/content/marketing/events.json @@ -0,0 +1,245 @@ +[ + { + "name": "ng-china", + "location": "Online", + "linkUrl": "https://ng-china.org/", + "date": { + "start": "2020-11-21", + "end": "2020-11-22" + } + }, + { + "name": "EnterpriseNG", + "location": "Online", + "linkUrl": "https://www.ng-conf.org/", + "date": { + "start": "2020-11-19", + "end": "2020-11-20" + } + }, + { + "name": "ngrome", + "location": "Online", + "linkUrl": "https://ngrome.io/", + "date": { + "start": "2020-10-20", + "end": "2020-10-20" + } + }, + { + "name": "DevReach", + "location": "Online", + "linkUrl": "https://www.telerik.com/devreach/online/agenda-thursday#sessions", + "date": { + "start": "2020-10-19", + "end": "2020-10-23" + } + }, + { + "name": "ngVikings", + "location": "Oslo, Norway", + "linkUrl": "https://ngvikings.org/", + "date": { + "start": "2020-05-25", + "end": "2020-05-26" + }, + "workshopsDate": { + "start": "2020-05-27", + "end": "2020-05-27" + } + }, + { + "name": "ng-conf", + "location": "Salt Lake City, Utah", + "linkUrl": "https://ng-conf.org/", + "date": { + "start": "2020-04-01", + "end": "2020-04-03" + } + }, + { + "name": "ngIndia", + "location": "Delhi, India", + "linkUrl": "https://www.ng-ind.com/", + "date": { + "start": "2020-02-29", + "end": "2020-02-29" + } + }, + { + "name": "ReactiveConf", + "location": "Prague, Czech Republic", + "linkUrl": "https://reactiveconf.com/", + "date": { + "start": "2019-10-30", + "end": "2019-11-01" + } + }, + { + "name": "NG Rome MMXIX", + "location": "Rome, Italy", + "linkUrl": "https://ngrome.io", + "tooltip": "NG Rome MMXIX - The Italian Angular Conference", + "date": { + "start": "2019-10-07", + "end": "2019-10-07" + }, + "workshopsDate": { + "start": "2019-10-06", + "end": "2019-10-06" + } + }, + { + "name": "AngularConnect", + "location": "London, UK", + "linkUrl": "https://www.angularconnect.com/?utm_source=angular.io&utm_medium=referral", + "date": { + "start": "2019-09-19", + "end": "2019-09-20" + } + }, + { + "name": "NG-DE", + "location": "Berlin, Germany", + "linkUrl": "https://ng-de.org/", + "date": { + "start": "2019-08-30", + "end": "2019-08-31" + }, + "workshopsDate": { + "start": "2019-08-29", + "end": "2019-08-29" + } + }, + { + "name": "ng-japan", + "location": "Tokyo, Japan", + "linkUrl": "https://ngjapan.org/", + "date": { + "start": "2019-07-13", + "end": "2019-07-13" + } + }, + { + "name": "ngVikings", + "location": "Copenhagen, Denmark", + "linkUrl": "https://ngvikings.org/", + "date": { + "start": "2019-05-27", + "end": "2019-05-28" + }, + "workshopsDate": { + "start": "2019-05-26", + "end": "2019-05-26" + } + }, + { + "name": "ng-conf", + "location": "Salt Lake City, Utah", + "linkUrl": "https://ng-conf.org/", + "date": { + "start": "2019-05-01", + "end": "2019-05-03" + } + }, + { + "name": "ng-India", + "location": "Gurgaon, India", + "linkUrl": "https://www.ng-ind.com/", + "date": { + "start": "2019-02-23", + "end": "2019-02-23" + } + }, + { + "name": "ngAtlanta", + "location": "Atlanta, Georgia", + "linkUrl": "https://ng-atl.org/", + "date": { + "start": "2019-01-09", + "end": "2019-01-12" + } + }, + { + "name": "AngularConnect", + "location": "London, United Kingdom", + "linkUrl": "https://past.angularconnect.com/2018", + "date": { + "start": "2018-11-05", + "end": "2018-11-07" + } + }, + { + "name": "ReactiveConf", + "location": "Prague, Czech Republic", + "linkUrl": "https://reactiveconf.com/", + "date": { + "start": "2018-10-29", + "end": "2018-10-31" + } + }, + { + "name": "AngularMix", + "location": "Orlando, Florida", + "linkUrl": "https://angularmix.com/", + "date": { + "start": "2018-10-10", + "end": "2018-10-12" + } + }, + { + "name": "Angular Conf Australia", + "location": "Melbourne, Australia", + "linkUrl": "https://www.angularconf.com.au/", + "date": { + "start": "2018-06-22", + "end": "2018-06-22" + } + }, + { + "name": "ng-japan", + "location": "Tokyo, Japan", + "linkUrl": "https://ngjapan.org/en.html", + "date": { + "start": "2018-06-16", + "end": "2018-06-16" + } + }, + { + "name": "WeAreDevelopers", + "location": "Vienna, Austria", + "linkUrl": "https://www.wearedevelopers.com/", + "tooltip": "WeAreDevs", + "date": { + "start": "2018-05-16", + "end": "2018-05-18" + } + }, + { + "name": "ng-conf", + "location": "Salt Lake City, Utah", + "linkUrl": "https://ng-conf.org/", + "date": { + "start": "2018-04-18", + "end": "2018-04-20" + } + }, + { + "name": "ngVikings", + "location": "Helsinki, Finland", + "linkUrl": "https://ngvikings.org/", + "date": { + "start": "2018-03-01", + "end": "2018-03-02" + } + }, + { + "name": "ngAtlanta", + "location": "Atlanta, Georgia", + "linkUrl": "https://ng-atl.org/", + "date": { + "start": "2018-01-30", + "end": "2018-01-30" + } + } +] diff --git a/aio/content/marketing/resources.json b/aio/content/marketing/resources.json index d2ec90a6ff960..649776030c3d1 100644 --- a/aio/content/marketing/resources.json +++ b/aio/content/marketing/resources.json @@ -30,10 +30,10 @@ "url": "https://dev.to/t/angular", "title": "DEV Community" }, - "angular-in-depth": { - "desc": "The place where advanced Angular concepts are explained", - "url": "https://blog.angularindepth.com", - "title": "Angular In Depth" + "indepth-dev": { + "desc": "Peer-reviewed Angular articles and tutorials.", + "url": "https://indepth.dev/angular/", + "title": "Angular inDepth" } } }, @@ -63,6 +63,12 @@ "logo": "", "title": "NgRuAir", "url": "https://github.com/ngRuAir/ngruair" + }, + "the-deep-dive": { + "desc": "The advanced web development podcast about Angular, RxJS, TypeScript and other technologies. English, audio only.", + "logo": "https://i.imgur.com/mmE5Feq.jpg", + "title": "The Deep Dive", + "url": "https://thedeepdive.simplecast.com" } } } @@ -429,6 +435,12 @@ "desc": "Jigsaw provides a set of web components based on Angular. It is supporting the development of all applications of Big Data Product of ZTE (https://www.zte.com.cn).", "title": "Awade Jigsaw (Chinese)", "url": "https://jigsaw-zte.gitee.io" + }, + "material-dayjs-adapter": { + "desc": "A DayJS implementation of @angular/material's DateAdapter that results in smaller bundle sizes than its MomentJS counterpart.", + "rev": true, + "title": "material-dayjs-adapter", + "url": "https://www.npmjs.com/package/@tabuckner/material-dayjs-adapter" } } } diff --git a/aio/content/start/index.md b/aio/content/start/index.md index 26992786de5a3..3b3dd4220fcef 100644 --- a/aio/content/start/index.md +++ b/aio/content/start/index.md @@ -1,4 +1,4 @@ -# Part 1: Getting started with a basic Angular app +# Getting started with a basic Angular app Welcome to Angular! diff --git a/aio/content/start/start-data.md b/aio/content/start/start-data.md index 3a5a3cf196436..781fc1961fa2c 100644 --- a/aio/content/start/start-data.md +++ b/aio/content/start/start-data.md @@ -1,4 +1,4 @@ -# Try it: Manage data +# Managing data At the end of [In-app Navigation](start/start-routing "Try it: In-app Navigation"), the online store application has a product catalog with two views: a product list and product details. Users can click on a product name from the list to see details in a new view, with a distinct URL, or route. @@ -40,7 +40,7 @@ A later part of this tutorial, [Use forms for user input](start/start-forms "Try -
      The StackBlitz generator might provide the cart service in `app.module.ts` by default. That differs from the example, which uses a bundle-optimization technique, an `@Injectable()` decorator with the `{ providedIn: 'root' }` statement. For more information about services, see [Introduction to Services and Dependency Injection](guide/architecture-services "Concepts > Intro to Services and DI"). @@ -236,7 +236,7 @@ For more information about services, see [Introduction to Services and Dependenc Servers often return data in the form of a stream. -Streams are useful because they make it easy to transform the returned data and make modifications to the way you request that data. +Streams are useful because they make it easy to transform the returned data and make modifications to the way you request that data. The Angular HTTP client, `HttpClient`, is a built-in way to fetch data from external APIs and provide them to your app as a stream. This section shows you how to use the HTTP client to retrieve shipping prices from an external file. diff --git a/aio/content/start/start-deployment.md b/aio/content/start/start-deployment.md index 94b99c39e4659..b1c41c8e032f7 100644 --- a/aio/content/start/start-deployment.md +++ b/aio/content/start/start-deployment.md @@ -1,4 +1,4 @@ -# Try it: Deployment +# Deploying an application To deploy your application, you have to compile it, and then host the JavaScript, CSS, and HTML on a web server. Built Angular applications are very portable and can live in any environment or served by any technology, such as Node, Java, .NET, PHP, and many others. diff --git a/aio/content/start/start-forms.md b/aio/content/start/start-forms.md index 00f2c98191270..b1981df4fc38f 100644 --- a/aio/content/start/start-forms.md +++ b/aio/content/start/start-forms.md @@ -1,4 +1,4 @@ -# Try it: Use forms for user input +# Using forms for user input At the end of [Managing Data](start/start-data "Try it: Managing Data"), the online store application has a product catalog and a shopping cart. diff --git a/aio/content/start/start-routing.md b/aio/content/start/start-routing.md index 42a4ce2ae0509..7a9afd80bc510 100644 --- a/aio/content/start/start-routing.md +++ b/aio/content/start/start-routing.md @@ -1,4 +1,4 @@ -# In-app navigation +# Adding navigation At the end of [part 1](start "Get started with a basic Angular app"), the online store application has a basic product catalog. The app doesn't have any variable states or navigation. diff --git a/aio/firebase.json b/aio/firebase.json index ae07bfe70fc07..033674d538358 100644 --- a/aio/firebase.json +++ b/aio/firebase.json @@ -31,6 +31,7 @@ {"type": 301, "source": "/guide/quickstart", "destination": "/start"}, {"type": 301, "source": "/getting-started", "destination": "/start"}, {"type": 301, "source": "/getting-started/:rest*", "destination": "/start/:rest*"}, + {"type": 301, "source": "/guide/displaying-data", "destination": "/start#template-syntax"}, // Renaming of Getting Started topics {"type": 301, "source": "/start/data", "destination": "/start/start-data"}, @@ -128,7 +129,8 @@ // The below paths are referenced in users projects generated by the CLI {"type": 301, "source": "/config/tsconfig", "destination": "/guide/typescript-configuration"}, {"type": 301, "source": "/config/solution-tsconfig", "destination": "https://devblogs.microsoft.com/typescript/announcing-typescript-3-9/#solution-style-tsconfig"}, - {"type": 301, "source": "/config/app-package-json", "destination": "/guide/strict-mode#non-local-side-effects-in-applications"} + {"type": 301, "source": "/config/app-package-json", "destination": "/guide/strict-mode#non-local-side-effects-in-applications"}, + {"type": 301, "source": "/strict", "destination": "/guide/strict-mode"} ], "rewrites": [ { diff --git a/aio/ngsw-config.json b/aio/ngsw-config.json index c3977373aafb2..28fd8f79c9f95 100644 --- a/aio/ngsw-config.json +++ b/aio/ngsw-config.json @@ -102,6 +102,9 @@ "!/guide/cli-quickstart", "!/guide/cli-quickstart.html", "!/guide/cli-quickstart/", + "!/guide/displaying-data", + "!/guide/displaying-data.html", + "!/guide/displaying-data/", "!/guide/learning-angular", "!/guide/learning-angular.html", "!/guide/learning-angular/", @@ -148,6 +151,7 @@ "!/styleguide/**", "!/testing", "!/testing/**", - "!/config/**" + "!/config/**", + "!/strict" ] } diff --git a/aio/package.json b/aio/package.json index ec8a353b67e59..078cc2e7554bf 100644 --- a/aio/package.json +++ b/aio/package.json @@ -23,7 +23,7 @@ "build-local-with-viewengine": "yarn ~~build", "prebuild-local-with-viewengine-ci": "node scripts/switch-to-viewengine && yarn setup-local-ci", "build-local-with-viewengine-ci": "yarn ~~build --progress=false", - "extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js b0b27361d", + "extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js 9d53eac1b", "lint": "yarn check-env && yarn docs-lint && ng lint && yarn example-lint && yarn tools-lint", "test": "yarn check-env && ng test", "pree2e": "yarn check-env && yarn update-webdriver", @@ -63,13 +63,14 @@ "tools-lint": "tslint --config \"tools/tslint.json\" --project \"tools/firebase-test-utils\"", "tools-test": "./scripts/deploy-to-firebase.test.sh && yarn docs-test && yarn boilerplate:test && jasmine tools/ng-packages-installer/index.spec.js && yarn firebase-utils-test", "preserve-and-sync": "yarn docs", - "serve-and-sync": "run-p \"start\" \"docs-watch --watch-only\"", + "serve-and-sync": "run-p \"docs-watch --watch-only\" \"start {@}\" --", "boilerplate:add": "node ./tools/examples/example-boilerplate add", "boilerplate:add:viewengine": "yarn boilerplate:add --viewengine", "boilerplate:remove": "node ./tools/examples/example-boilerplate remove", "boilerplate:test": "node tools/examples/test.js", "generate-stackblitz": "node ./tools/stackblitz-builder/generateStackblitz", "generate-zips": "node ./tools/example-zipper/generateZips", + "create-example": "node ./tools/examples/create-example.js", "build-404-page": "node scripts/build-404-page", "update-webdriver": "node ../scripts/webdriver-manager-update.js", "~~audit-web-app": "node scripts/audit-web-app", @@ -86,32 +87,31 @@ }, "private": true, "dependencies": { - "@angular/animations": "10.0.2", - "@angular/cdk": "10.0.1", - "@angular/common": "10.0.2", - "@angular/compiler": "10.0.2", - "@angular/core": "10.0.2", - "@angular/elements": "10.0.2", + "@angular/animations": "10.1.3", + "@angular/cdk": "10.2.2", + "@angular/common": "10.1.3", + "@angular/compiler": "10.1.3", + "@angular/core": "10.1.3", + "@angular/elements": "10.1.3", "@angular/fire": "~6.0.3", - "@angular/forms": "10.0.2", - "@angular/material": "10.0.1", - "@angular/platform-browser": "10.0.2", - "@angular/platform-browser-dynamic": "10.0.2", - "@angular/router": "10.0.2", - "@angular/service-worker": "10.0.2", + "@angular/forms": "10.1.3", + "@angular/material": "10.2.2", + "@angular/platform-browser": "10.1.3", + "@angular/platform-browser-dynamic": "10.1.3", + "@angular/router": "10.1.3", + "@angular/service-worker": "10.1.3", "@webcomponents/custom-elements": "1.2.1", "firebase": "~7.18.0", "first-input-delay": "^0.1.3", "proxy-polyfill": "^0.3.2", "rxjs": "^6.5.3", - "tslib": "^1.10.0", + "tslib": "^2.0.0", "zone.js": "~0.10.3" }, "devDependencies": { - "@angular-devkit/build-angular": "0.1000.1", - "@angular/cli": "10.0.1", - "@angular/compiler-cli": "10.0.2", - "@angular/language-service": "10.0.2", + "@angular-devkit/build-angular": "0.1001.3", + "@angular/cli": "10.1.3", + "@angular/compiler-cli": "10.1.3", "@types/jasmine": "^3.4.2", "@types/jasminewd2": "^2.0.8", "@types/lunr": "^2.3.2", @@ -122,7 +122,7 @@ "canonical-path": "1.0.0", "chalk": "^2.1.0", "cjson": "^0.5.0", - "codelyzer": "^6.0.0-next.1", + "codelyzer": "^6.0.0", "cross-spawn": "^5.1.0", "css-selector-parser": "^1.3.0", "dgeni": "^0.4.11", @@ -139,8 +139,8 @@ "html": "^1.0.0", "ignore": "^3.3.3", "image-size": "^0.5.1", - "jasmine": "^3.4.0", - "jasmine-core": "^3.4.0", + "jasmine": "~3.6.0", + "jasmine-core": "~3.6.0", "jasmine-spec-reporter": "~5.0.0", "jsdom": "^9.12.0", "json-schema-traverse": "^0.4.1", @@ -148,7 +148,7 @@ "karma": "~5.0.0", "karma-chrome-launcher": "^3.1.0", "karma-coverage-istanbul-reporter": "^2.1.0", - "karma-jasmine": "^3.1.1", + "karma-jasmine": "~4.0.0", "karma-jasmine-html-reporter": "^1.4.2", "light-server": "^2.6.2", "lighthouse": "6.1.0", @@ -157,7 +157,7 @@ "lunr": "^2.1.0", "npm-run-all": "^4.1.5", "protractor": "~5.4.4", - "puppeteer": "3.3.0", + "puppeteer": "5.1.0", "rehype": "^6.0.0", "rehype-slug": "^2.0.0", "remark": "^9.0.0", @@ -168,7 +168,7 @@ "tree-kill": "^1.1.0", "ts-node": "^8.4.1", "tslint": "~6.1.0", - "typescript": "~3.9.5", + "typescript": "~4.0.2", "uglify-js": "^3.0.15", "unist-util-filter": "^0.2.1", "unist-util-source": "^1.0.1", @@ -176,6 +176,6 @@ "unist-util-visit-parents": "^1.1.1", "watchr": "^3.0.1", "xregexp": "^4.0.0", - "yargs": "^7.0.2" + "yargs": "^16.1.0" } } diff --git a/aio/src/app/app.component.spec.ts b/aio/src/app/app.component.spec.ts index cffcd9d80dd27..108fb8e552939 100644 --- a/aio/src/app/app.component.spec.ts +++ b/aio/src/app/app.component.spec.ts @@ -781,7 +781,7 @@ describe('AppComponent', () => { it('should grab focus when the / key is pressed', () => { const searchBox: SearchBoxComponent = fixture.debugElement.query(By.directive(SearchBoxComponent)).componentInstance; spyOn(searchBox, 'focus'); - window.document.dispatchEvent(new KeyboardEvent('keyup', { 'key': '/' })); + window.document.dispatchEvent(new KeyboardEvent('keyup', { key: '/' })); fixture.detectChanges(); expect(searchBox.focus).toHaveBeenCalled(); }); @@ -790,7 +790,7 @@ describe('AppComponent', () => { const searchBox: SearchBoxComponent = fixture.debugElement.query(By.directive(SearchBoxComponent)).componentInstance; spyOn(searchBox, 'focus'); component.showSearchResults = true; - window.document.dispatchEvent(new KeyboardEvent('keyup', { 'key': 'Escape' })); + window.document.dispatchEvent(new KeyboardEvent('keyup', { key: 'Escape' })); fixture.detectChanges(); expect(searchBox.focus).toHaveBeenCalled(); }); @@ -967,23 +967,23 @@ describe('AppComponent', () => { // Initially, `isTransitoning` is true. expect(component.isTransitioning).toBe(true); - expect(toolbar.classes['transitioning']).toBe(true); + expect(toolbar.classes.transitioning).toBe(true); triggerDocViewerEvent('docRendered'); fixture.detectChanges(); expect(component.isTransitioning).toBe(false); - expect(toolbar.classes['transitioning']).toBeFalsy(); + expect(toolbar.classes.transitioning).toBeFalsy(); // While a document is being rendered, `isTransitoning` is set to true. triggerDocViewerEvent('docReady'); fixture.detectChanges(); expect(component.isTransitioning).toBe(true); - expect(toolbar.classes['transitioning']).toBe(true); + expect(toolbar.classes.transitioning).toBe(true); triggerDocViewerEvent('docRendered'); fixture.detectChanges(); expect(component.isTransitioning).toBe(false); - expect(toolbar.classes['transitioning']).toBeFalsy(); + expect(toolbar.classes.transitioning).toBeFalsy(); }); it('should update the sidenav state as soon as a new document is inserted (but not before)', () => { @@ -1030,15 +1030,15 @@ describe('AppComponent', () => { navigateTo('guide/pipes'); expect(component.pageId).toEqual('guide-pipes'); - expect(container.properties['id']).toEqual('guide-pipes'); + expect(container.properties.id).toEqual('guide-pipes'); navigateTo('news'); expect(component.pageId).toEqual('news'); - expect(container.properties['id']).toEqual('news'); + expect(container.properties.id).toEqual('news'); navigateTo(''); expect(component.pageId).toEqual('home'); - expect(container.properties['id']).toEqual('home'); + expect(container.properties.id).toEqual('home'); }); it('should not be affected by changes to the query', () => { @@ -1049,7 +1049,7 @@ describe('AppComponent', () => { navigateTo('guide/other?search=http'); expect(component.pageId).toEqual('guide-other'); - expect(container.properties['id']).toEqual('guide-other'); + expect(container.properties.id).toEqual('guide-other'); }); }); @@ -1124,7 +1124,7 @@ describe('AppComponent', () => { function checkHostClass(type: string, value: string) { const host = fixture.debugElement; - const classes: string = host.properties['className']; + const classes: string = host.properties.className; const classArray = classes.split(' ').filter(c => c.indexOf(`${type}-`) === 0); expect(classArray.length).toBeLessThanOrEqual(1, `"${classes}" should have only one class matching ${type}-*`); expect(classArray).toEqual([`${type}-${value}`], `"${classes}" should contain ${type}-${value}`); @@ -1305,42 +1305,42 @@ class TestHttpClient { // tslint:disable:quotemark navJson = { - "TopBar": [ + TopBar: [ { - "url": "features", - "title": "Features" + url: 'features', + title: 'Features', }, { - "url": "no-title", - "title": "No Title" + url: 'no-title', + title: 'No Title', }, ], - "SideNav": [ + SideNav: [ { - "title": "Core", - "tooltip": "Learn the core capabilities of Angular", - "children": [ + title: 'Core', + tooltip: 'Learn the core capabilities of Angular', + children: [ { - "url": "guide/pipes", - "title": "Pipes", - "tooltip": "Pipes transform displayed values within a template." + url: 'guide/pipes', + title: 'Pipes', + tooltip: 'Pipes transform displayed values within a template.', }, { - "url": "guide/bags", - "title": "Bags", - "tooltip": "Pack your bags for a code adventure." - } - ] + url: 'guide/bags', + title: 'Bags', + tooltip: 'Pack your bags for a code adventure.', + }, + ], }, { - "url": "api", - "title": "API", - "tooltip": "Details of the Angular classes and values." - } + url: 'api', + title: 'API', + tooltip: 'Details of the Angular classes and values.', + }, ], - "docVersions": TestHttpClient.docVersions, + docVersions: TestHttpClient.docVersions, - "__versionInfo": TestHttpClient.versionInfo, + __versionInfo: TestHttpClient.versionInfo, }; get(url: string) { diff --git a/aio/src/app/app.component.ts b/aio/src/app/app.component.ts index 42826349bf7e6..bc07be293075c 100644 --- a/aio/src/app/app.component.ts +++ b/aio/src/app/app.component.ts @@ -147,7 +147,7 @@ export class AppComponent implements OnInit { // Compute the version picker list from the current version and the versions in the navigation map combineLatest([ this.navigationService.versionInfo, - this.navigationService.navigationViews.pipe(map(views => views['docVersions'])), + this.navigationService.navigationViews.pipe(map(views => views.docVersions)), ]).subscribe(([versionInfo, versions]) => { // TODO(pbd): consider whether we can lookup the stable and next versions from the internet const computedVersions: NavigationNode[] = [ @@ -167,10 +167,10 @@ export class AppComponent implements OnInit { }); this.navigationService.navigationViews.subscribe(views => { - this.footerNodes = views['Footer'] || []; - this.sideNavNodes = views['SideNav'] || []; - this.topMenuNodes = views['TopBar'] || []; - this.topMenuNarrowNodes = views['TopBarNarrow'] || this.topMenuNodes; + this.footerNodes = views.Footer || []; + this.sideNavNodes = views.SideNav || []; + this.topMenuNodes = views.TopBar || []; + this.topMenuNarrowNodes = views.TopBarNarrow || this.topMenuNodes; }); this.navigationService.versionInfo.subscribe(vi => this.versionInfo = vi); diff --git a/aio/src/app/custom-elements/api/api-list.component.spec.ts b/aio/src/app/custom-elements/api/api-list.component.spec.ts index 0c7a18a667075..fb97db2c38767 100644 --- a/aio/src/app/custom-elements/api/api-list.component.spec.ts +++ b/aio/src/app/custom-elements/api/api-list.component.spec.ts @@ -223,77 +223,77 @@ class TestApiService { // tslint:disable:quotemark const apiSections: ApiSection[] = [ { - "name": "common", - "title": "common", - "path": "api/common", - "deprecated": false, - "items": [ + name: 'common', + title: 'common', + path: 'api/common', + deprecated: false, + items: [ { - "name": "class_1", - "title": "Class 1", - "path": "api/common/class_1", - "docType": "class", - "stability": "experimental", - "securityRisk": false, + name: 'class_1', + title: 'Class 1', + path: 'api/common/class_1', + docType: 'class', + stability: 'experimental', + securityRisk: false, }, { - "name": "class_2", - "title": "Class 2", - "path": "api/common/class_2", - "docType": "class", - "stability": "stable", - "securityRisk": false, + name: 'class_2', + title: 'Class 2', + path: 'api/common/class_2', + docType: 'class', + stability: 'stable', + securityRisk: false, }, { - "name": "directive_1", - "title": "Directive 1", - "path": "api/common/directive_1", - "docType": "directive", - "stability": "stable", - "securityRisk": true, + name: 'directive_1', + title: 'Directive 1', + path: 'api/common/directive_1', + docType: 'directive', + stability: 'stable', + securityRisk: true, }, { - "name": "pipe_1", - "title": "Pipe 1", - "path": "api/common/pipe_1", - "docType": "pipe", - "stability": "stable", - "securityRisk": true, + name: 'pipe_1', + title: 'Pipe 1', + path: 'api/common/pipe_1', + docType: 'pipe', + stability: 'stable', + securityRisk: true, }, - ] + ], }, { - "name": "core", - "title": "core", - "path": "api/core", - "deprecated": false, - "items": [ + name: 'core', + title: 'core', + path: 'api/core', + deprecated: false, + items: [ { - "name": "class_3", - "title": "Class 3", - "path": "api/core/class_3", - "docType": "class", - "stability": "experimental", - "securityRisk": false, + name: 'class_3', + title: 'Class 3', + path: 'api/core/class_3', + docType: 'class', + stability: 'experimental', + securityRisk: false, }, { - "name": "function_1", - "title": "Function 1", - "path": "api/core/function 1", - "docType": "function", - "stability": "deprecated", - "securityRisk": true, + name: 'function_1', + title: 'Function 1', + path: 'api/core/function 1', + docType: 'function', + stability: 'deprecated', + securityRisk: true, }, { - "name": "const_1", - "title": "Const 1", - "path": "api/core/const_1", - "docType": "const", - "stability": "stable", - "securityRisk": false, - } - ] - } + name: 'const_1', + title: 'Const 1', + path: 'api/core/const_1', + docType: 'const', + stability: 'stable', + securityRisk: false, + }, + ], + }, ]; function getApiSections() { return apiSections; } diff --git a/aio/src/app/custom-elements/api/api.service.ts b/aio/src/app/custom-elements/api/api.service.ts index ae94866a4b1f7..b6ca5ea26d5a9 100644 --- a/aio/src/app/custom-elements/api/api.service.ts +++ b/aio/src/app/custom-elements/api/api.service.ts @@ -67,7 +67,7 @@ export class ApiService implements OnDestroy { * API sections is an array of Angular top modules and metadata about their API documents (items). * Updates `sections` observable * - * @param {string} [src] - Name of the api list JSON file + * @param [src] - Name of the api list JSON file */ fetchSections(src?: string) { // TODO: get URL by configuration? diff --git a/aio/src/app/custom-elements/code/pretty-printer.service.ts b/aio/src/app/custom-elements/code/pretty-printer.service.ts index 24538d8702b03..0f234dd7871d4 100644 --- a/aio/src/app/custom-elements/code/pretty-printer.service.ts +++ b/aio/src/app/custom-elements/code/pretty-printer.service.ts @@ -20,13 +20,13 @@ export class PrettyPrinter { } private getPrettyPrintOne(): Promise { - const ppo = (window as any)['prettyPrintOne']; + const ppo = (window as any).prettyPrintOne; return ppo ? Promise.resolve(ppo) : // `prettyPrintOne` is not on `window`, which means `prettify.js` has not been loaded yet. // Import it; ad a side-effect it will add `prettyPrintOne` on `window`. import('assets/js/prettify.js' as any) .then( - () => (window as any)['prettyPrintOne'], + () => (window as any).prettyPrintOne, err => { const msg = `Cannot get prettify.js from server: ${err.message}`; this.logger.error(new Error(msg)); @@ -37,9 +37,9 @@ export class PrettyPrinter { /** * Format code snippet as HTML - * @param {string} code - the code snippet to format; should already be HTML encoded - * @param {string} [language] - The language of the code to render (could be javascript, html, typescript, etc) - * @param {string|number} [linenums] - Whether to display line numbers: + * @param code - the code snippet to format; should already be HTML encoded + * @param [language] - The language of the code to render (could be javascript, html, typescript, etc) + * @param [linenums] - Whether to display line numbers: * - false: don't display * - true: do display * - number: do display but start at the given number diff --git a/aio/src/app/custom-elements/contributor/contributor-list.component.spec.ts b/aio/src/app/custom-elements/contributor/contributor-list.component.spec.ts index 48d9bd20805f0..ccf426558a634 100644 --- a/aio/src/app/custom-elements/contributor/contributor-list.component.spec.ts +++ b/aio/src/app/custom-elements/contributor/contributor-list.component.spec.ts @@ -1,4 +1,4 @@ -import { ReflectiveInjector } from '@angular/core'; +import { Injector } from '@angular/core'; import { of } from 'rxjs'; @@ -12,20 +12,22 @@ import { LocationService } from 'app/shared/location.service'; describe('ContributorListComponent', () => { let component: ContributorListComponent; - let injector: ReflectiveInjector; + let injector: Injector; let contributorService: TestContributorService; let locationService: TestLocationService; let contributorGroups: ContributorGroup[]; beforeEach(() => { - injector = ReflectiveInjector.resolveAndCreate([ - ContributorListComponent, - {provide: ContributorService, useClass: TestContributorService }, - {provide: LocationService, useClass: TestLocationService } - ]); - - locationService = injector.get(LocationService); - contributorService = injector.get(ContributorService); + injector = Injector.create({ + providers: [ + {provide: ContributorListComponent, deps: [ContributorService, LocationService] }, + {provide: ContributorService, useClass: TestContributorService, deps: [] }, + {provide: LocationService, useClass: TestLocationService, deps: [] } + ] + }); + + locationService = injector.get(LocationService) as unknown as TestLocationService; + contributorService = injector.get(ContributorService) as unknown as TestContributorService; contributorGroups = contributorService.testContributors; }); @@ -61,7 +63,7 @@ describe('ContributorListComponent', () => { it('should set the query to the "GDE" group when user selects "GDE"', () => { component = getComponent(); component.selectGroup('GDE'); - expect(locationService.searchResult['group']).toBe('GDE'); + expect(locationService.searchResult.group).toBe('GDE'); }); it('should set the query to the first group when user selects unknown name', () => { @@ -69,7 +71,7 @@ describe('ContributorListComponent', () => { component.selectGroup('GDE'); // a legit group that isn't the first component.selectGroup('foo'); // not a legit group name - expect(locationService.searchResult['group']).toBe('Angular'); + expect(locationService.searchResult.group).toBe('Angular'); }); //// Test Helpers //// diff --git a/aio/src/app/custom-elements/contributor/contributor-list.component.ts b/aio/src/app/custom-elements/contributor/contributor-list.component.ts index e6887d5ac9630..fd0116fe971fb 100644 --- a/aio/src/app/custom-elements/contributor/contributor-list.component.ts +++ b/aio/src/app/custom-elements/contributor/contributor-list.component.ts @@ -29,7 +29,7 @@ export class ContributorListComponent implements OnInit { private locationService: LocationService) { } ngOnInit() { - const groupName = this.locationService.search()['group'] || ''; + const groupName = this.locationService.search().group || ''; // no need to unsubscribe because `contributors` completes this.contributorService.contributors .subscribe(grps => { diff --git a/aio/src/app/custom-elements/element-registry.ts b/aio/src/app/custom-elements/element-registry.ts index 57b12bf5eab30..be4036687f516 100644 --- a/aio/src/app/custom-elements/element-registry.ts +++ b/aio/src/app/custom-elements/element-registry.ts @@ -40,6 +40,10 @@ export const ELEMENT_MODULE_LOAD_CALLBACKS_AS_ROUTES = [ { selector: 'live-example', loadChildren: () => import('./live-example/live-example.module').then(m => m.LiveExampleModule) + }, + { + selector: 'aio-events', + loadChildren: () => import('./events/events.module').then(m => m.EventsModule) } ]; diff --git a/aio/src/app/custom-elements/events/events.component.html b/aio/src/app/custom-elements/events/events.component.html new file mode 100644 index 0000000000000..17e5f10b22fd4 --- /dev/null +++ b/aio/src/app/custom-elements/events/events.component.html @@ -0,0 +1,43 @@ +

      Where we'll be presenting:

      + + + + + + + + + + + + + + + +
      EventLocationDate
      {{event.name}}{{event.location}} +
      + {{getEventDates(event)}} +
      +
      + +

      Where we already presented:

      + + + + + + + + + + + + + + + +
      EventLocationDate
      {{event.name}}{{event.location}} +
      + {{getEventDates(event)}} +
      +
      diff --git a/aio/src/app/custom-elements/events/events.component.spec.ts b/aio/src/app/custom-elements/events/events.component.spec.ts new file mode 100644 index 0000000000000..e84f25053bbea --- /dev/null +++ b/aio/src/app/custom-elements/events/events.component.spec.ts @@ -0,0 +1,231 @@ +import { Injector } from '@angular/core'; +import { Subject } from 'rxjs'; +import { Duration, Event, EventsComponent } from './events.component'; +import { EventsService } from './events.service'; + +describe('EventsComponent', () => { + let component: EventsComponent; + let injector: Injector; + let eventsService: TestEventsService; + + beforeEach(() => { + injector = Injector.create({ + providers: [ + { provide: EventsComponent, deps: [EventsService] } , + { provide: EventsService, useClass: TestEventsService, deps: [] }, + ] + }); + eventsService = injector.get(EventsService) as unknown as TestEventsService; + component = injector.get(EventsComponent) as unknown as EventsComponent; + }); + + it('should have no pastEvents when first created', () => { + expect(component.pastEvents).toBeUndefined(); + }); + + it('should have no upcoming when first created', () => { + expect(component.upcomingEvents).toBeUndefined(); + }); + + describe('ngOnInit()', () => { + beforeEach(() => { + jasmine.clock().install(); + jasmine.clock().mockDate(new Date(2020, 5, 15, 23, 59, 59)); + component.ngOnInit(); + }); + + afterEach(() => jasmine.clock().uninstall()); + + it('should separate past and upcoming events', () => { + eventsService.events.next([ + createMockEvent( + 'Upcoming event 1', + {start: '2020-06-16', end: '2020-06-17'}, + {start: '2020-06-18', end: '2020-06-18'}), + createMockEvent( + 'Upcoming event 3', + {start: '2222-01-01', end: '2222-01-02'}), + createMockEvent( + 'Past event 2', + {start: '2020-06-13', end: '2020-06-14'}), + createMockEvent( + 'Upcoming event 2', + {start: '2020-06-17', end: '2020-06-18'}, + {start: '2020-06-16', end: '2020-06-16'}), + createMockEvent( + 'Past event 1', + {start: '2020-05-30', end: '2020-05-31'}), + createMockEvent( + 'Past event 3', + {start: '2020-06-14', end: '2020-06-14'}, + {start: '2020-06-16', end: '2020-06-17'}), + ]); + + expect(component.pastEvents.map(evt => evt.name)).toEqual(jasmine.arrayWithExactContents( + ['Past event 1', 'Past event 2', 'Past event 3'])); + + expect(component.upcomingEvents.map(evt => evt.name)).toEqual(jasmine.arrayWithExactContents( + ['Upcoming event 1', 'Upcoming event 2', 'Upcoming event 3'])); + }); + + it('should order past events in reverse chronological order (ignoring workshops dates)', () => { + eventsService.events.next([ + createMockEvent( + 'Past event 2', + {start: '1999-12-13', end: '1999-12-14'}, + {start: '1999-12-11', end: '1999-12-11'}), + createMockEvent( + 'Past event 4', + {start: '2020-01-16', end: '2020-01-17'}, + {start: '2020-01-14', end: '2020-01-15'}), + createMockEvent( + 'Past event 3', + {start: '2020-01-15', end: '2020-01-16'}, + {start: '2020-01-17', end: '2020-01-18'}), + createMockEvent( + 'Past event 1', + {start: '1999-12-12', end: '1999-12-15'}), + ]); + + expect(component.pastEvents.map(evt => evt.name)).toEqual( + ['Past event 4', 'Past event 3', 'Past event 2', 'Past event 1']); + }); + + it('should order upcoming events in chronological order (ignoring workshops dates)', () => { + eventsService.events.next([ + createMockEvent( + 'Upcoming event 2', + {start: '2020-12-13', end: '2020-12-14'}, + {start: '2020-12-11', end: '2020-12-11'}), + createMockEvent( + 'Upcoming event 4', + {start: '2021-01-16', end: '2021-01-17'}, + {start: '2021-01-14', end: '2021-01-15'}), + createMockEvent( + 'Upcoming event 3', + {start: '2021-01-15', end: '2021-01-16'}, + {start: '2021-01-17', end: '2021-01-18'}), + createMockEvent( + 'Upcoming event 1', + {start: '2020-12-12', end: '2020-12-15'}), + ]); + + expect(component.upcomingEvents.map(evt => evt.name)).toEqual( + ['Upcoming event 1', 'Upcoming event 2', 'Upcoming event 3', 'Upcoming event 4']); + }); + + it('should treat ongoing events as upcoming', () => { + eventsService.events.next([ + createMockEvent( + 'Ongoing event 1', + {start: '2020-06-14', end: '2020-06-16'}), + createMockEvent( + 'Ongoing event 2', + {start: '2020-06-14', end: '2020-06-15'}, + {start: '2020-06-13', end: '2020-06-13'}), + ]); + + expect(component.pastEvents).toEqual([]); + expect(component.upcomingEvents.map(evt => evt.name)).toEqual(jasmine.arrayWithExactContents( + ['Ongoing event 1', 'Ongoing event 2'])); + }); + }); + + describe('getEventDates()', () => { + describe('(without workshops)', () => { + it('should correctly format the main event date', () => { + const testEvent = createMockEvent('Test', {start: '2020-06-20', end: '2020-06-20'}); + expect(component.getEventDates(testEvent)).toBe('June 20, 2020'); + }); + + it('should correctly format the main event date spanning mupliple days', () => { + const testEvent = createMockEvent('Test', {start: '2019-09-19', end: '2019-09-21'}); + expect(component.getEventDates(testEvent)).toBe('September 19-21, 2019'); + }); + + it('should correctly format the main event date spanning mupliple months', () => { + const testEvent = createMockEvent('Test', {start: '2019-10-30', end: '2019-11-01'}); + expect(component.getEventDates(testEvent)).toBe('October 30 - November 1, 2019'); + }); + }); + + describe('(with workshops)', () => { + it('should correctly format event dates with workshops after main event', () => { + const testEvent = createMockEvent( + 'Test', + {start: '2020-07-25', end: '2020-07-26'}, + {start: '2020-07-27', end: '2020-07-27'}); + + expect(component.getEventDates(testEvent)) + .toBe('July 25-26 (conference), July 27 (workshops), 2020'); + }); + + it('should correctly format event dates with workshops before main event', () => { + const testEvent = createMockEvent( + 'Test', + {start: '2019-10-07', end: '2019-10-07'}, + {start: '2019-10-06', end: '2019-10-06'}); + + expect(component.getEventDates(testEvent)) + .toBe('October 6 (workshops), October 7 (conference), 2019'); + }); + + it('should correctly format event dates spanning multiple days', () => { + const testEvent = createMockEvent( + 'Test', + {start: '2019-08-30', end: '2019-08-31'}, + {start: '2019-08-28', end: '2019-08-29'}); + + expect(component.getEventDates(testEvent)) + .toBe('August 28-29 (workshops), August 30-31 (conference), 2019'); + }); + + it('should correctly format event dates with workshops on different month before the main event', + () => { + const testEvent = createMockEvent( + 'Test', + {start: '2020-08-01', end: '2020-08-02'}, + {start: '2020-07-30', end: '2020-07-31'}); + + expect(component.getEventDates(testEvent)) + .toBe('July 30-31 (workshops), August 1-2 (conference), 2020'); + }); + + it('should correctly format event dates with workshops on different month after the main event', + () => { + const testEvent = createMockEvent( + 'Test', + {start: '2020-07-30', end: '2020-07-31'}, + {start: '2020-08-01', end: '2020-08-02'}); + + expect(component.getEventDates(testEvent)) + .toBe('July 30-31 (conference), August 1-2 (workshops), 2020'); + }); + + it('should correctly format event dates spanning multiple months', () => { + const testEvent = createMockEvent( + 'Test', + {start: '2020-07-31', end: '2020-08-01'}, + {start: '2020-07-30', end: '2020-08-01'}); + + expect(component.getEventDates(testEvent)) + .toBe('July 30 - August 1 (workshops), July 31 - August 1 (conference), 2020'); + }); + }); + }); + + // Helpers + class TestEventsService { + events = new Subject(); + } + + function createMockEvent(name: string, date: Duration, workshopsDate?: Duration): Event { + return { + name, + location: '', + linkUrl: '', + date, + workshopsDate, + }; + } +}); diff --git a/aio/src/app/custom-elements/events/events.component.ts b/aio/src/app/custom-elements/events/events.component.ts new file mode 100644 index 0000000000000..9c9555054e931 --- /dev/null +++ b/aio/src/app/custom-elements/events/events.component.ts @@ -0,0 +1,102 @@ +import { Component, OnInit } from '@angular/core'; + +import { EventsService } from './events.service'; + +const DAY = 24 * 60 * 60 * 1000; +const MONTHS = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', +]; + +export type date = string; // of the format `YYYY-MM-DD`. +export interface Duration { + start: date; + end: date; +} + +export interface Event { + name: string; + location: string; + linkUrl: string; + tooltip?: string; + date: Duration; + workshopsDate?: Duration; +} + +@Component({ + selector: 'aio-events', + templateUrl: 'events.component.html' +}) +export class EventsComponent implements OnInit { + + pastEvents: Event[]; + upcomingEvents: Event[]; + + constructor(private eventsService: EventsService) { } + + ngOnInit() { + this.eventsService.events.subscribe(events => { + this.pastEvents = events + .filter(event => new Date(event.date.end).getTime() < Date.now() - DAY) + .sort((l: Event, r: Event) => isBefore(l.date, r.date) ? 1 : -1); + + this.upcomingEvents = events + .filter(event => new Date(event.date.end).getTime() >= Date.now() - DAY) + .sort((l: Event, r: Event) => isBefore(l.date, r.date) ? -1 : 1); + }); + } + + getEventDates(event: Event) { + let dateString; + + // Check if there is a workshop + if (event.workshopsDate) { + const mainEventDateString = `${processDate(event.date)} (conference)`; + const workshopsDateString = `${processDate(event.workshopsDate)} (workshops)`; + const areWorkshopsBeforeEvent = isBefore(event.workshopsDate, event.date); + + dateString = areWorkshopsBeforeEvent ? + `${workshopsDateString}, ${mainEventDateString}` : + `${mainEventDateString}, ${workshopsDateString}`; + } else { + // If no work shop date create conference date string + dateString = processDate(event.date); + } + dateString = `${dateString}, ${new Date(event.date.end).getFullYear()}`; + return dateString; + } +} + +function processDate(dates: Duration) { + // Covert Date sting to date object for comparisons + const startDate = new Date(dates.start); + const endDate = new Date(dates.end); + + // Create a date string in the start like January 31 + let processedDate = `${MONTHS[startDate.getMonth()]} ${startDate.getDate()}`; + + // If they are in different months add the string '- February 2' Making the final string January 31 - February 2 + if (startDate.getMonth() !== endDate.getMonth()) { + processedDate = `${processedDate} - ${MONTHS[endDate.getMonth()]} ${endDate.getDate()}`; + } else if (startDate.getDate() !== endDate.getDate()) { + // If not add - date eg it will make // January 30-31 + processedDate = `${processedDate}-${endDate.getDate()}`; + } + + return processedDate; +} + +function isBefore(duration1: Duration, duration2: Duration): boolean { + return (duration1.start < duration2.start) || + (duration1.start === duration2.start && duration1.end < duration2.end); +} diff --git a/aio/src/app/custom-elements/events/events.module.ts b/aio/src/app/custom-elements/events/events.module.ts new file mode 100644 index 0000000000000..04803e7e6a668 --- /dev/null +++ b/aio/src/app/custom-elements/events/events.module.ts @@ -0,0 +1,15 @@ +import { NgModule, Type } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { EventsComponent } from './events.component'; +import { EventsService } from './events.service'; +import { WithCustomElementComponent } from '../element-registry'; + +@NgModule({ + imports: [ CommonModule ], + declarations: [ EventsComponent ], + entryComponents: [ EventsComponent ], + providers: [ EventsService] +}) +export class EventsModule implements WithCustomElementComponent { + customElementComponent: Type = EventsComponent; +} diff --git a/aio/src/app/custom-elements/events/events.service.spec.ts b/aio/src/app/custom-elements/events/events.service.spec.ts new file mode 100644 index 0000000000000..5102e017035fd --- /dev/null +++ b/aio/src/app/custom-elements/events/events.service.spec.ts @@ -0,0 +1,56 @@ +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { Injector } from '@angular/core'; +import { TestBed } from '@angular/core/testing'; + +import { EventsService } from './events.service'; +import { Logger } from 'app/shared/logger.service'; +import { MockLogger } from 'testing/logger.service'; + +describe('EventsService', () => { + + let injector: Injector; + let eventsService: EventsService; + let httpMock: HttpTestingController; + let mockLogger: MockLogger; + + beforeEach(() => { + injector = TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [ + EventsService, + { provide: Logger, useClass: MockLogger } + ] + }); + + eventsService = injector.get(EventsService); + mockLogger = injector.get(Logger) as any; + httpMock = injector.get(HttpTestingController); + }); + + afterEach(() => httpMock.verify()); + + it('should make a single connection to the server', () => { + eventsService.events.subscribe(); + eventsService.events.subscribe(); + httpMock.expectOne('generated/events.json'); + expect().nothing(); // Prevent jasmine from complaining about no expectations. + }); + + it('should handle a failed request for `events.json`', () => { + const request = httpMock.expectOne('generated/events.json'); + request.error(new ErrorEvent('404')); + expect(mockLogger.output.error).toEqual([ + [jasmine.any(Error)] + ]); + expect(mockLogger.output.error[0][0].message).toMatch(/^generated\/events\.json request failed:/); + }); + + it('should return an empty array on a failed request for `events.json`', done => { + const request = httpMock.expectOne('generated/events.json'); + request.error(new ErrorEvent('404')); + eventsService.events.subscribe(results => { + expect(results).toEqual([]); + done(); + }); + }); +}); diff --git a/aio/src/app/custom-elements/events/events.service.ts b/aio/src/app/custom-elements/events/events.service.ts new file mode 100644 index 0000000000000..c4d8ecd0e257d --- /dev/null +++ b/aio/src/app/custom-elements/events/events.service.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; + +import { ConnectableObservable, Observable, of } from 'rxjs'; +import { catchError, publishLast } from 'rxjs/operators'; + +import { Event } from './events.component'; +import { CONTENT_URL_PREFIX } from 'app/documents/document.service'; +import { Logger } from 'app/shared/logger.service'; + +const eventsPath = CONTENT_URL_PREFIX + 'events.json'; + +@Injectable() +export class EventsService { + events: Observable; + + constructor(private http: HttpClient, private logger: Logger) { + this.events = this.getEvents(); + } + + private getEvents() { + const events = this.http.get(eventsPath).pipe( + catchError(error => { + this.logger.error(new Error(`${eventsPath} request failed: ${error.message}`)); + return of([]); + }), + publishLast() + ); + (events as ConnectableObservable).connect(); + return events; + } +} diff --git a/aio/src/app/custom-elements/resource/resource-list.component.spec.ts b/aio/src/app/custom-elements/resource/resource-list.component.spec.ts index 60a9374252423..11c31ff2413dc 100644 --- a/aio/src/app/custom-elements/resource/resource-list.component.spec.ts +++ b/aio/src/app/custom-elements/resource/resource-list.component.spec.ts @@ -1,4 +1,4 @@ -import { ReflectiveInjector } from '@angular/core'; +import { Injector } from '@angular/core'; import { of } from 'rxjs'; @@ -12,20 +12,22 @@ import { Category } from './resource.model'; describe('ResourceListComponent', () => { let component: ResourceListComponent; - let injector: ReflectiveInjector; + let injector: Injector; let resourceService: TestResourceService; let locationService: TestLocationService; let categories: Category[]; beforeEach(() => { - injector = ReflectiveInjector.resolveAndCreate([ - ResourceListComponent, - {provide: ResourceService, useClass: TestResourceService }, - {provide: LocationService, useClass: TestLocationService } - ]); - - locationService = injector.get(LocationService); - resourceService = injector.get(ResourceService); + injector = Injector.create({ + providers: [ + {provide: ResourceListComponent, deps: [ResourceService, LocationService] }, + {provide: ResourceService, useClass: TestResourceService, deps: [] }, + {provide: LocationService, useClass: TestLocationService, deps: [] } + ] + }); + + locationService = injector.get(LocationService) as unknown as TestLocationService; + resourceService = injector.get(ResourceService) as unknown as TestResourceService; categories = resourceService.testCategories; }); @@ -61,7 +63,7 @@ describe('ResourceListComponent', () => { it('should set the query to the "education" category when user selects "education"', () => { component = getComponent(); component.selectCategory('education'); - expect(locationService.searchResult['category']).toBe('education'); + expect(locationService.searchResult.category).toBe('education'); }); it('should set the query to the first category when user selects unknown name', () => { @@ -69,7 +71,7 @@ describe('ResourceListComponent', () => { component.selectCategory('education'); // a legit group that isn't the first component.selectCategory('foo'); // not a legit group name - expect(locationService.searchResult['category']).toBe('development'); + expect(locationService.searchResult.category).toBe('development'); }); //// Test Helpers //// diff --git a/aio/src/app/custom-elements/resource/resource-list.component.ts b/aio/src/app/custom-elements/resource/resource-list.component.ts index 6b48195fa8c11..63be0ec155003 100644 --- a/aio/src/app/custom-elements/resource/resource-list.component.ts +++ b/aio/src/app/custom-elements/resource/resource-list.component.ts @@ -20,7 +20,7 @@ export class ResourceListComponent implements OnInit { } ngOnInit() { - const category = this.locationService.search()['category'] || ''; + const category = this.locationService.search().category || ''; // Not using async pipe because cats appear twice in template // No need to unsubscribe because categories observable completes. this.resourceService.categories.subscribe(cats => { diff --git a/aio/src/app/custom-elements/resource/resource.service.spec.ts b/aio/src/app/custom-elements/resource/resource.service.spec.ts index 2d9f3a4d5ba7a..032c11d32509d 100644 --- a/aio/src/app/custom-elements/resource/resource.service.spec.ts +++ b/aio/src/app/custom-elements/resource/resource.service.spec.ts @@ -86,62 +86,61 @@ describe('ResourceService', () => { }); function getTestResources() { - // tslint:disable:quotemark return { - "Cat 3": { - "order": 3, - "subCategories": { - "Cat3 SubCat1": { - "order": 2, - "resources": { - "Cat3 SubCat1 Res1": { - "desc": "Meetup in Barcelona, Spain. ", - "title": "Angular Beers", - "url": "http://www.meetup.com/AngularJS-Beers/" + 'Cat 3': { + order: 3, + subCategories: { + 'Cat3 SubCat1': { + order: 2, + resources: { + 'Cat3 SubCat1 Res1': { + desc: 'Meetup in Barcelona, Spain. ', + title: 'Angular Beers', + url: 'http://www.meetup.com/AngularJS-Beers/', }, - "Cat3 SubCat1 Res2": { - "desc": "Angular Camps in Barcelona, Spain.", - "title": "Angular Camp", - "url": "http://angularcamp.org/" - } - } + 'Cat3 SubCat1 Res2': { + desc: 'Angular Camps in Barcelona, Spain.', + title: 'Angular Camp', + url: 'http://angularcamp.org/', + }, + }, }, - "Cat3 SubCat2": { - "order": 1, - "resources": { - "Cat3 SubCat2 Res1": { - "desc": "A community index of components and libraries", - "title": "Catalog of Angular Components & Libraries", - "url": "https://a/b/c" - } - } + 'Cat3 SubCat2': { + order: 1, + resources: { + 'Cat3 SubCat2 Res1': { + desc: 'A community index of components and libraries', + title: 'Catalog of Angular Components & Libraries', + url: 'https://a/b/c', + }, + }, }, - } + }, }, - "Cat 1": { - "order": 1, - "subCategories": { - "Cat1 SubCat1": { - "order": 1, - "resources": { - "S S S": { - "desc": "SSS", - "title": "Sssss", - "url": "http://s/s/s" + 'Cat 1': { + order: 1, + subCategories: { + 'Cat1 SubCat1': { + order: 1, + resources: { + 'S S S': { + desc: 'SSS', + title: 'Sssss', + url: 'http://s/s/s', }, - "A A A": { - "desc": "AAA", - "title": "Aaaa", - "url": "http://a/a/a" + 'A A A': { + desc: 'AAA', + title: 'Aaaa', + url: 'http://a/a/a', }, - "Z Z Z": { - "desc": "ZZZ", - "title": "Zzzzz", - "url": "http://z/z/z" - } - } + 'Z Z Z': { + desc: 'ZZZ', + title: 'Zzzzz', + url: 'http://z/z/z', + }, + }, }, }, - } + }, }; } diff --git a/aio/src/app/layout/doc-viewer/doc-viewer.component.ts b/aio/src/app/layout/doc-viewer/doc-viewer.component.ts index 2661dfc5338e7..0fce7f88cd431 100644 --- a/aio/src/app/layout/doc-viewer/doc-viewer.component.ts +++ b/aio/src/app/layout/doc-viewer/doc-viewer.component.ts @@ -21,7 +21,7 @@ const initialDocViewerContent = initialDocViewerElement ? initialDocViewerElemen selector: 'aio-doc-viewer', template: '' // TODO(robwormald): shadow DOM and emulated don't work here (?!) - // encapsulation: ViewEncapsulation.Native + // encapsulation: ViewEncapsulation.ShadowDom }) export class DocViewerComponent implements OnDestroy { // Enable/Disable view transition animations. diff --git a/aio/src/app/navigation/navigation.service.spec.ts b/aio/src/app/navigation/navigation.service.spec.ts index 028b357979adb..96fc80b95bbf9 100644 --- a/aio/src/app/navigation/navigation.service.spec.ts +++ b/aio/src/app/navigation/navigation.service.spec.ts @@ -86,7 +86,7 @@ describe('NavigationService', () => { ]; beforeEach(() => { - navService.navigationViews.subscribe(views => view = views['sideNav']); + navService.navigationViews.subscribe(views => view = views.sideNav); httpMock.expectOne({}).flush({sideNav}); }); @@ -254,7 +254,7 @@ describe('NavigationService', () => { {...v, ...{ tooltip: v.title + '.'}}) ); - navService.navigationViews.subscribe(views => actualDocVersions = views['docVersions']); + navService.navigationViews.subscribe(views => actualDocVersions = views.docVersions); }); it('should extract the docVersions', () => { diff --git a/aio/src/app/search/search-box/search-box.component.ts b/aio/src/app/search/search-box/search-box.component.ts index 737b3ac1fba33..bced17ccf8d6c 100644 --- a/aio/src/app/search/search-box/search-box.component.ts +++ b/aio/src/app/search/search-box/search-box.component.ts @@ -41,7 +41,7 @@ export class SearchBoxComponent implements AfterViewInit { * When we first show this search box we trigger a search if there is a search query in the URL */ ngAfterViewInit() { - const query = this.locationService.search()['search']; + const query = this.locationService.search().search; if (query) { this.query = this.decodeQuery(query); this.doSearch(); diff --git a/aio/src/app/search/search.service.spec.ts b/aio/src/app/search/search.service.spec.ts index 4fad506ac05de..906236f16178c 100644 --- a/aio/src/app/search/search.service.spec.ts +++ b/aio/src/app/search/search.service.spec.ts @@ -1,4 +1,4 @@ -import { ReflectiveInjector, NgZone } from '@angular/core'; +import { Injector, NgZone } from '@angular/core'; import { fakeAsync, tick } from '@angular/core/testing'; import { of } from 'rxjs'; import { SearchService } from './search.service'; @@ -6,7 +6,7 @@ import { WebWorkerClient } from 'app/shared/web-worker'; describe('SearchService', () => { - let injector: ReflectiveInjector; + let injector: Injector; let service: SearchService; let sendMessageSpy: jasmine.Spy; let mockWorker: WebWorkerClient; @@ -16,10 +16,13 @@ describe('SearchService', () => { mockWorker = { sendMessage: sendMessageSpy } as any; spyOn(WebWorkerClient, 'create').and.returnValue(mockWorker); - injector = ReflectiveInjector.resolveAndCreate([ - SearchService, - { provide: NgZone, useFactory: () => new NgZone({ enableLongStackTrace: false }) } - ]); + injector = Injector.create({ + providers: [ + { provide: SearchService, deps: [NgZone]}, + { provide: NgZone, useFactory: () => new NgZone({ enableLongStackTrace: false }), deps: [] } + ] + }); + service = injector.get(SearchService); }); diff --git a/aio/src/app/search/search.worker.ts b/aio/src/app/search/search.worker.ts index 2482bb9085627..153416a680d40 100644 --- a/aio/src/app/search/search.worker.ts +++ b/aio/src/app/search/search.worker.ts @@ -26,7 +26,7 @@ function createIndex(loadIndexFn: IndexLoader): lunr.Index { // The lunr typings are missing QueryLexer so we have to add them here manually. const queryLexer = (lunr as any as { QueryLexer: { termSeparator: RegExp } }).QueryLexer; queryLexer.termSeparator = lunr.tokenizer.separator = /\s+/; - return lunr(/** @this */function() { + return lunr(function() { this.ref('path'); this.field('topics', { boost: 15 }); this.field('titleWords', { boost: 10 }); @@ -44,7 +44,7 @@ function handleMessage(message: { data: WebWorkerMessage }): void { const payload = message.data.payload; switch (type) { case 'load-index': - makeRequest(SEARCH_TERMS_URL, function(searchInfo: PageInfo[]) { + makeRequest(SEARCH_TERMS_URL, (searchInfo: PageInfo[]) => { index = createIndex(loadIndex(searchInfo)); postMessage({ type, id, payload: true }); }); @@ -94,7 +94,7 @@ function queryIndex(query: string): PageInfo[] { results = index.search(query + ' ' + titleQuery); } // Map the hits into info about each page to be returned as results - return results.map(function(hit) { return pages[hit.ref]; }); + return results.map(hit => pages[hit.ref]); } } catch (e) { // If the search query cannot be parsed the index throws an error diff --git a/aio/src/app/shared/deployment.service.spec.ts b/aio/src/app/shared/deployment.service.spec.ts index 34df4ec92e952..5c19ee20164a3 100644 --- a/aio/src/app/shared/deployment.service.spec.ts +++ b/aio/src/app/shared/deployment.service.spec.ts @@ -1,4 +1,4 @@ -import { ReflectiveInjector } from '@angular/core'; +import { Injector } from '@angular/core'; import { environment } from 'environments/environment'; import { LocationService } from 'app/shared/location.service'; import { MockLocationService } from 'testing/location.service'; @@ -15,7 +15,7 @@ describe('Deployment service', () => { it('should get the mode from the `mode` query parameter if available', () => { const injector = getInjector(); - const locationService: MockLocationService = injector.get(LocationService); + const locationService = injector.get(LocationService) as unknown as MockLocationService; locationService.search.and.returnValue({ mode: 'bar' }); const deployment = injector.get(Deployment); @@ -25,8 +25,8 @@ describe('Deployment service', () => { }); function getInjector() { - return ReflectiveInjector.resolveAndCreate([ - Deployment, - { provide: LocationService, useFactory: () => new MockLocationService('') } - ]); + return Injector.create({providers: [ + { provide: Deployment, deps: [LocationService] }, + { provide: LocationService, useFactory: () => new MockLocationService(''), deps: [] } + ]}); } diff --git a/aio/src/app/shared/deployment.service.ts b/aio/src/app/shared/deployment.service.ts index 3a77b91c93b2e..651f27cf4699d 100644 --- a/aio/src/app/shared/deployment.service.ts +++ b/aio/src/app/shared/deployment.service.ts @@ -11,7 +11,7 @@ export class Deployment { * The deployment mode set from the environment provided at build time; * or overridden by the `mode` query parameter: e.g. `...?mode=archive` */ - mode: string = this.location.search()['mode'] || environment.mode; + mode: string = this.location.search().mode || environment.mode; constructor(private location: LocationService) {} } diff --git a/aio/src/app/shared/location.service.ts b/aio/src/app/shared/location.service.ts index df59d4d48d1a1..a3c193a818c2b 100644 --- a/aio/src/app/shared/location.service.ts +++ b/aio/src/app/shared/location.service.ts @@ -97,7 +97,7 @@ export class LocationService { /** * Handle user's anchor click * - * @param anchor {HTMLAnchorElement} - the anchor element clicked + * @param anchor The anchor element clicked * @param button Number of the mouse button held down. 0 means left or none * @param ctrlKey True if control key held down * @param metaKey True if command or window key held down diff --git a/aio/src/app/shared/logger.service.spec.ts b/aio/src/app/shared/logger.service.spec.ts index d676cc4e3769b..2dedb6e228db6 100644 --- a/aio/src/app/shared/logger.service.spec.ts +++ b/aio/src/app/shared/logger.service.spec.ts @@ -1,4 +1,4 @@ -import { ErrorHandler, ReflectiveInjector } from '@angular/core'; +import { ErrorHandler, Injector } from '@angular/core'; import { Logger } from './logger.service'; describe('logger service', () => { @@ -10,10 +10,10 @@ describe('logger service', () => { beforeEach(() => { logSpy = spyOn(console, 'log'); warnSpy = spyOn(console, 'warn'); - const injector = ReflectiveInjector.resolveAndCreate([ - Logger, - { provide: ErrorHandler, useClass: MockErrorHandler } - ]); + const injector = Injector.create({providers: [ + { provide: Logger, deps: [ErrorHandler] }, + { provide: ErrorHandler, useClass: MockErrorHandler, deps: [] } + ]}); logger = injector.get(Logger); errorHandler = injector.get(ErrorHandler); }); diff --git a/aio/src/app/shared/reporting-error-handler.spec.ts b/aio/src/app/shared/reporting-error-handler.spec.ts index a7389824d4083..39fb790e30645 100644 --- a/aio/src/app/shared/reporting-error-handler.spec.ts +++ b/aio/src/app/shared/reporting-error-handler.spec.ts @@ -1,4 +1,4 @@ -import { ErrorHandler, ReflectiveInjector } from '@angular/core'; +import { ErrorHandler, Injector } from '@angular/core'; import { TestBed } from '@angular/core/testing'; import { WindowToken } from 'app/shared/window'; import { AppModule } from 'app/app.module'; @@ -14,11 +14,12 @@ describe('ReportingErrorHandler service', () => { onerrorSpy = jasmine.createSpy('onerror'); superHandler = spyOn(ErrorHandler.prototype, 'handleError'); - const injector = ReflectiveInjector.resolveAndCreate([ - { provide: ErrorHandler, useClass: ReportingErrorHandler }, - { provide: WindowToken, useFactory: () => ({ onerror: onerrorSpy }) } - ]); - handler = injector.get(ErrorHandler); + const injector = Injector.create({providers: [ + { provide: ErrorHandler, useClass: ReportingErrorHandler, deps: [WindowToken] }, + { provide: WindowToken, useFactory: () => ({ onerror: onerrorSpy }), deps: [] } + ]}); + + handler = injector.get(ErrorHandler) as unknown as ReportingErrorHandler; }); it('should be registered on the AppModule', () => { diff --git a/aio/src/app/shared/scroll-spy.service.spec.ts b/aio/src/app/shared/scroll-spy.service.spec.ts index 4563683c72163..9184839fa564e 100644 --- a/aio/src/app/shared/scroll-spy.service.spec.ts +++ b/aio/src/app/shared/scroll-spy.service.spec.ts @@ -1,4 +1,4 @@ -import { Injector, ReflectiveInjector } from '@angular/core'; +import { Injector } from '@angular/core'; import { fakeAsync, tick } from '@angular/core/testing'; import { DOCUMENT } from '@angular/common'; @@ -151,11 +151,11 @@ describe('ScrollSpyService', () => { let scrollSpyService: ScrollSpyService; beforeEach(() => { - injector = ReflectiveInjector.resolveAndCreate([ + injector = Injector.create({providers: [ { provide: DOCUMENT, useValue: { body: {} } }, { provide: ScrollService, useValue: { topOffset: 50 } }, - ScrollSpyService - ]); + { provide: ScrollSpyService, deps: [DOCUMENT, ScrollService] } + ]}); scrollSpyService = injector.get(ScrollSpyService); }); diff --git a/aio/src/app/shared/scroll.service.spec.ts b/aio/src/app/shared/scroll.service.spec.ts index bd3ffd71f1151..1a8c19db7369f 100644 --- a/aio/src/app/shared/scroll.service.spec.ts +++ b/aio/src/app/shared/scroll.service.spec.ts @@ -1,7 +1,7 @@ import {Location, LocationStrategy, PlatformLocation, ViewportScroller} from '@angular/common'; import {DOCUMENT} from '@angular/common'; import {MockLocationStrategy, SpyLocation} from '@angular/common/testing'; -import {ReflectiveInjector} from '@angular/core'; +import {Injector} from '@angular/core'; import {fakeAsync, tick} from '@angular/core/testing'; import {ScrollService, topMargin} from './scroll.service'; @@ -15,7 +15,7 @@ describe('ScrollService', () => { }; const topOfPageElem = {} as Element; - let injector: ReflectiveInjector; + let injector: Injector; let document: MockDocument; let platformLocation: MockPlatformLocation; let scrollService: ScrollService; @@ -41,21 +41,25 @@ describe('ScrollService', () => { jasmine.createSpyObj('viewportScroller', ['getScrollPosition', 'scrollToPosition']); beforeEach(() => { - injector = ReflectiveInjector.resolveAndCreate([ - { - provide: ScrollService, - useFactory: createScrollService, - deps: [DOCUMENT, PlatformLocation, ViewportScroller, Location], - }, - {provide: Location, useClass: SpyLocation}, {provide: DOCUMENT, useClass: MockDocument}, - {provide: PlatformLocation, useClass: MockPlatformLocation}, - {provide: ViewportScroller, useValue: viewportScrollerStub}, - {provide: LocationStrategy, useClass: MockLocationStrategy} - ]); + injector = Injector.create( { + providers: [ + { + provide: ScrollService, + useFactory: createScrollService, + deps: [DOCUMENT, PlatformLocation, ViewportScroller, Location], + }, + {provide: Location, useClass: SpyLocation, deps: [] }, + {provide: DOCUMENT, useClass: MockDocument, deps: []}, + {provide: PlatformLocation, useClass: MockPlatformLocation, deps: []}, + {provide: ViewportScroller, useValue: viewportScrollerStub}, + {provide: LocationStrategy, useClass: MockLocationStrategy, deps: []} + ] + }); + platformLocation = injector.get(PlatformLocation); - document = injector.get(DOCUMENT); + document = injector.get(DOCUMENT) as unknown as MockDocument; scrollService = injector.get(ScrollService); - location = injector.get(Location); + location = injector.get(Location) as unknown as SpyLocation; spyOn(window, 'scrollBy'); }); @@ -95,7 +99,7 @@ describe('ScrollService', () => { if (original !== undefined) { Object.defineProperty(window.history, 'scrollRestoration', original); } else { - delete window.history.scrollRestoration; + delete (window.history as any).scrollRestoration; } } }); diff --git a/aio/src/app/shared/toc.service.spec.ts b/aio/src/app/shared/toc.service.spec.ts index ffe765e8200e8..be5cd36fe5977 100644 --- a/aio/src/app/shared/toc.service.spec.ts +++ b/aio/src/app/shared/toc.service.spec.ts @@ -1,5 +1,5 @@ import { DOCUMENT } from '@angular/common'; -import { ReflectiveInjector } from '@angular/core'; +import { Injector } from '@angular/core'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; import { Subject } from 'rxjs'; @@ -7,7 +7,7 @@ import { ScrollItem, ScrollSpyInfo, ScrollSpyService } from 'app/shared/scroll-s import { TocItem, TocService } from './toc.service'; describe('TocService', () => { - let injector: ReflectiveInjector; + let injector: Injector; let scrollSpyService: MockScrollSpyService; let tocService: TocService; let lastTocList: TocItem[]; @@ -21,13 +21,14 @@ describe('TocService', () => { } beforeEach(() => { - injector = ReflectiveInjector.resolveAndCreate([ - { provide: DomSanitizer, useClass: TestDomSanitizer }, + injector = Injector.create({providers: [ + { provide: DomSanitizer, useClass: TestDomSanitizer, deps: [] }, { provide: DOCUMENT, useValue: document }, - { provide: ScrollSpyService, useClass: MockScrollSpyService }, - TocService, - ]); - scrollSpyService = injector.get(ScrollSpyService); + { provide: ScrollSpyService, useClass: MockScrollSpyService, deps: [] }, + { provide: TocService, deps: [DOCUMENT, DomSanitizer, ScrollSpyService] }, + ]}); + + scrollSpyService = injector.get(ScrollSpyService) as unknown as MockScrollSpyService; tocService = injector.get(TocService); tocService.tocList.subscribe(tocList => lastTocList = tocList); }); @@ -330,7 +331,7 @@ describe('TocService', () => { }); it('should have bypassed HTML sanitizing of heading\'s innerHTML ', () => { - const domSanitizer: TestDomSanitizer = injector.get(DomSanitizer); + const domSanitizer: TestDomSanitizer = injector.get(DomSanitizer) as unknown as TestDomSanitizer; expect(domSanitizer.bypassSecurityTrustHtml) .toHaveBeenCalledWith('Setup to develop locally.'); }); diff --git a/aio/src/app/sw-updates/sw-updates.service.spec.ts b/aio/src/app/sw-updates/sw-updates.service.spec.ts index e99330d663f08..fa35b19931e60 100644 --- a/aio/src/app/sw-updates/sw-updates.service.spec.ts +++ b/aio/src/app/sw-updates/sw-updates.service.spec.ts @@ -1,4 +1,4 @@ -import { ApplicationRef, ReflectiveInjector } from '@angular/core'; +import { ApplicationRef, Injector } from '@angular/core'; import { discardPeriodicTasks, fakeAsync, tick } from '@angular/core/testing'; import { SwUpdate } from '@angular/service-worker'; import { Subject } from 'rxjs'; @@ -8,7 +8,7 @@ import { SwUpdatesService } from './sw-updates.service'; describe('SwUpdatesService', () => { - let injector: ReflectiveInjector; + let injector: Injector; let appRef: MockApplicationRef; let service: SwUpdatesService; let swu: MockSwUpdate; @@ -21,16 +21,16 @@ describe('SwUpdatesService', () => { // run `setup()`/`tearDown()` in `beforeEach()`/`afterEach()` blocks. We use the `run()` helper // to call them inside each test's zone. const setup = (isSwUpdateEnabled: boolean) => { - injector = ReflectiveInjector.resolveAndCreate([ - { provide: ApplicationRef, useClass: MockApplicationRef }, - { provide: Logger, useClass: MockLogger }, - { provide: SwUpdate, useFactory: () => new MockSwUpdate(isSwUpdateEnabled) }, - SwUpdatesService - ]); - - appRef = injector.get(ApplicationRef); + injector = Injector.create({providers: [ + { provide: ApplicationRef, useClass: MockApplicationRef, deps: [] }, + { provide: Logger, useClass: MockLogger, deps: [] }, + { provide: SwUpdate, useFactory: () => new MockSwUpdate(isSwUpdateEnabled), deps: [] }, + { provide: SwUpdatesService, deps: [ApplicationRef, Logger, SwUpdate] } + ]}); + + appRef = injector.get(ApplicationRef) as unknown as MockApplicationRef; service = injector.get(SwUpdatesService); - swu = injector.get(SwUpdate); + swu = injector.get(SwUpdate) as unknown as MockSwUpdate; checkInterval = (service as any).checkInterval; }; const tearDown = () => service.ngOnDestroy(); diff --git a/aio/src/app/sw-updates/sw-updates.service.ts b/aio/src/app/sw-updates/sw-updates.service.ts index f44df3286bda5..38ea8c4658da7 100644 --- a/aio/src/app/sw-updates/sw-updates.service.ts +++ b/aio/src/app/sw-updates/sw-updates.service.ts @@ -13,14 +13,13 @@ import { Logger } from 'app/shared/logger.service'; * 1. Checks for available ServiceWorker updates once instantiated. * 2. Re-checks every 6 hours. * 3. Whenever an update is available, it activates the update. - * - * @property - * `updateActivated` {Observable} - Emit the version hash whenever an update is activated. */ @Injectable() export class SwUpdatesService implements OnDestroy { private checkInterval = 1000 * 60 * 60 * 6; // 6 hours private onDestroy = new Subject(); + + /** Emit the version hash whenever an update is activated. */ updateActivated: Observable; constructor(appRef: ApplicationRef, private logger: Logger, private swu: SwUpdate) { diff --git a/aio/src/polyfills.ts b/aio/src/polyfills.ts index 7d239456a5f3a..d8d53e062fae8 100644 --- a/aio/src/polyfills.ts +++ b/aio/src/polyfills.ts @@ -18,7 +18,7 @@ * BROWSER POLYFILLS */ -/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +/** IE11 requires the following for NgClass support on SVG elements */ // import 'classlist.js'; // Run `npm install --save classlist.js`. /** diff --git a/aio/src/styles/0-base/_typography.scss b/aio/src/styles/0-base/_typography.scss index 5a1b50e61d83b..20619f775e8a3 100755 --- a/aio/src/styles/0-base/_typography.scss +++ b/aio/src/styles/0-base/_typography.scss @@ -214,7 +214,7 @@ code { margin-left: 2px; position: relative; @include line-height(24); - vertical-align: bottom; + vertical-align: middle; } } diff --git a/aio/src/styles/2-modules/_api-pages.scss b/aio/src/styles/2-modules/_api-pages.scss index 33ca56a9e47d3..34aeb94fc7d9a 100644 --- a/aio/src/styles/2-modules/_api-pages.scss +++ b/aio/src/styles/2-modules/_api-pages.scss @@ -38,7 +38,11 @@ margin: 0; clear: left; } - + .actions { + display: flex; + color: $blue; + @include font-size(14); + } .show-all { display: initial; } diff --git a/aio/src/styles/2-modules/_modules-dir.scss b/aio/src/styles/2-modules/_modules-dir.scss index 157e80121e6bb..76302968a5cdb 100644 --- a/aio/src/styles/2-modules/_modules-dir.scss +++ b/aio/src/styles/2-modules/_modules-dir.scss @@ -25,7 +25,6 @@ @import 'progress-bar'; @import 'presskit'; @import 'resources'; - @import 'scrollbar'; @import 'search-results'; @import 'select-menu'; @import 'table'; diff --git a/aio/src/styles/2-modules/_scrollbar.scss b/aio/src/styles/2-modules/_scrollbar.scss deleted file mode 100644 index dd9b27e9bd0ac..0000000000000 --- a/aio/src/styles/2-modules/_scrollbar.scss +++ /dev/null @@ -1,27 +0,0 @@ -body::-webkit-scrollbar, mat-sidenav.sidenav::-webkit-scrollbar, .mat-sidenav-content::-webkit-scrollbar { - height: 6px; - width: 6px; -} - -body::-webkit-scrollbar-track, mat-sidenav.sidenav::-webkit-scrollbar-track, .mat-sidenav-content::-webkit-scrollbar-track { - -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); -} - -body::-webkit-scrollbar-thumb, mat-sidenav.sidenav::-webkit-scrollbar-thumb, .mat-sidenav-content::-webkit-scrollbar-thumb { - background-color: $mediumgray; - outline: 1px solid $darkgray; -} - -.search-results::-webkit-scrollbar, .toc-container::-webkit-scrollbar { - height: 4px; - width: 4px; -} - -.search-results::-webkit-scrollbar-track, .toc-container::-webkit-scrollbar-track { - -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); -} - -.search-results::-webkit-scrollbar-thumb, .toc-container::-webkit-scrollbar-thumb { - background-color: $mediumgray; - outline: 1px solid slategrey; -} diff --git a/aio/src/styles/2-modules/_toc.scss b/aio/src/styles/2-modules/_toc.scss index 20fed744e9bc0..6a71ed21bc6d6 100644 --- a/aio/src/styles/2-modules/_toc.scss +++ b/aio/src/styles/2-modules/_toc.scss @@ -105,9 +105,7 @@ li { box-sizing: border-box; - @include font-size(12); - @include line-height(16); - padding: 3px 0 3px 12px; + padding: 7px 0 7px 12px; position: relative; transition: all 0.3s ease-in-out; @@ -129,6 +127,7 @@ color: lighten($darkgray, 10); overflow: visible; @include font-size(12); + @include line-height(16); display: table-cell; } @@ -168,11 +167,11 @@ } &:first-child:before { - top: 13px; + top: 15px; } &:last-child:before { - bottom: calc(100% - 14px); + bottom: calc(100% - 15px); } &:not(.active):hover a:before { diff --git a/aio/src/testing/dom-utils.ts b/aio/src/testing/dom-utils.ts index 54510abeced1c..8e296fe352f68 100644 --- a/aio/src/testing/dom-utils.ts +++ b/aio/src/testing/dom-utils.ts @@ -5,7 +5,7 @@ export function createCustomEvent(doc: Document, name: string, detail: any): Cus const bubbles = false; const cancelable = false; - // On IE9-11, `CustomEvent` is not a constructor. + // On IE11, `CustomEvent` is not a constructor. if (typeof CustomEvent !== 'function') { const event = doc.createEvent('CustomEvent'); event.initCustomEvent(name, bubbles, cancelable, detail); diff --git a/aio/tests/deployment/shared/URLS_TO_REDIRECT.txt b/aio/tests/deployment/shared/URLS_TO_REDIRECT.txt index 23a6370555a3d..887ad52883b74 100644 --- a/aio/tests/deployment/shared/URLS_TO_REDIRECT.txt +++ b/aio/tests/deployment/shared/URLS_TO_REDIRECT.txt @@ -177,6 +177,7 @@ /getting-started/forms /start/start-forms /getting-started/deployment /start/start-deployment /guide/cli-quickstart /start +/guide/displaying-data /start#template-syntax /guide/learning-angular /start /guide/learning-angular.html /start /guide/metadata /guide/aot-compiler diff --git a/aio/tests/e2e/src/api-pages.e2e-spec.ts b/aio/tests/e2e/src/api-pages.e2e-spec.ts index b97e89e4f30ee..636b7b0b62168 100644 --- a/aio/tests/e2e/src/api-pages.e2e-spec.ts +++ b/aio/tests/e2e/src/api-pages.e2e-spec.ts @@ -1,6 +1,6 @@ import { ApiPage } from './api.po'; -describe('Api pages', function() { +describe('Api pages', () => { it('should show direct subclasses of a class', () => { const page = new ApiPage('api/forms/AbstractControlDirective'); expect(page.getDescendants('class', true)).toEqual(['ControlContainer', 'NgControl']); diff --git a/aio/tests/e2e/src/app.e2e-spec.ts b/aio/tests/e2e/src/app.e2e-spec.ts index 73f6c0532c5d1..3f14cbc7bcc2c 100644 --- a/aio/tests/e2e/src/app.e2e-spec.ts +++ b/aio/tests/e2e/src/app.e2e-spec.ts @@ -1,7 +1,7 @@ import { browser, by, element, ElementFinder } from 'protractor'; import { SitePage } from './app.po'; -describe('site App', function() { +describe('site App', () => { let page: SitePage; beforeEach(() => { @@ -99,10 +99,11 @@ describe('site App', function() { describe('scrolling to the top', () => { it('should scroll to the top when navigating to another page', () => { page.navigateTo('guide/security'); - page.scrollTo('bottom'); expect(page.getScrollTop()).toBeGreaterThan(0); - + // Navigate to Reference section, then check + // Find the navigation item that has the text "api" + page.click(page.getNavItem(/reference/i)); page.click(page.getNavItem(/api/i)); expect(page.locationPath()).toBe('/api'); expect(page.getScrollTop()).toBe(0); diff --git a/aio/tools/README.md b/aio/tools/README.md index e44c358091e2b..1a949daea41c3 100644 --- a/aio/tools/README.md +++ b/aio/tools/README.md @@ -29,41 +29,38 @@ sub-folder. Also there are a number of common boilerplate files that are needed example's project. We maintain these common boilerplate files centrally to reduce the amount of effort if one of them needs to change. -This `examples` tool folder contains two utilities: +This `examples` tool folder contains three utilities: * example-boilerplate.js - install/remove the npm dependencies and boilerplate files into/from each of the examples' subfolders. * run-example-e2e.js - run the e2e tests for one or more examples +* create-example.js - create a new example from the `example-scaffold/` directory or by importing files from a CLI project. See the [README.md](examples/README.md) for more details. ## example-zipper -In the AIO application, we offer the reader the option to download each example as a full self-contained -runnable project packaged as a zip file. These zip files are generated by the utility in this folder. +In the AIO application, we offer the reader the option to download each example as a full self-contained runnable project packaged as a zip file. +These zip files are generated by the utility in this folder. See the [README.md](example-zipper/README.md) for more details. ## stackblitz-builder In the AIO application, we can embed a running version of the example as a [Stackblitz](https://stackblitz.com/) session. -We can also provide a link to create a runnable version of the example in the [Stackblitz](https://stackblitz.com/) -editor. +We can also provide a link to create a runnable version of the example in the [Stackblitz](https://stackblitz.com/) editor. See the [README.md](stackblitz-builder/README.md) for more details. ## transforms -All the content that is rendered by the AIO application, and some of its configuration files, are -generated from source files by [Dgeni](https://github.com/angular/dgeni). Dgeni is a general purpose -documentation generation tool. +All the content that is rendered by the AIO application, and some of its configuration files, are generated from source files by [Dgeni](https://github.com/angular/dgeni). +Dgeni is a general purpose documentation generation tool. -Markdown files in `/aio/content`, code comments in the core Angular source files and example files are -processed and transformed into files that are consumed by the AIO application. +Markdown files in `/aio/content`, code comments in the core Angular source files and example files are processed and transformed into files that are consumed by the AIO application. -Dgeni is configured by "packages", which contain services and processors. Some of these packages are -installed as `node_modules` from the [dgeni-packages](https://github.com/angular/dgeni-packages) and -some are specific to the AIO project. +Dgeni is configured by "packages", which contain services and processors. +Some of these packages are installed as `node_modules` from the [dgeni-packages](https://github.com/angular/dgeni-packages) and some are specific to the AIO project. -The project specific packages are stored in the `aio/tools/transforms` folder. See the -[README.md](transforms/README.md) for more details. +The project specific packages are stored in the `aio/tools/transforms` folder. +See the [README.md](transforms/README.md) for more details. diff --git a/aio/tools/RELEASE.md b/aio/tools/RELEASE.md deleted file mode 100644 index 419d2597db10e..0000000000000 --- a/aio/tools/RELEASE.md +++ /dev/null @@ -1,16 +0,0 @@ -# Docs releases - -This document explains how to update the documentation examples after an Angular release. This is only needed for major and minor versions. - -All the packages for the docs' examples are specified in `/aio/tools/examples/shared/package.json` - -**1)** So within the `shared` folder, you need to issue the following command: - -``` -$ yarn upgrade-interactive --tilde -``` - -There, select all the packages that are updated on the new Angular release. - -**2)** Changes to the tsconfig.json? There are several files in `/aio/tools/examples/shared/boilerplate/*/tsconfig.json` (based on the example type). - diff --git a/aio/tools/cli-patches/README.md b/aio/tools/cli-patches/README.md index e92303bf249df..9767ce32de77d 100644 --- a/aio/tools/cli-patches/README.md +++ b/aio/tools/cli-patches/README.md @@ -1,7 +1,5 @@ # Overview -The AIO application is built using the Angular CLI tool. We are often trialling new features for the CLI, which -we apply to the library after it is installed. This folder contains git patch files that contain these new features -and a utility to apply those patches to the CLI library. +The AIO application is built using the Angular CLI tool. We are often trialling new features for the CLI, which we apply to the library after it is installed. This folder contains git patch files that contain these new features and a utility to apply those patches to the CLI library. -**Currently, we have no patches to run.** \ No newline at end of file +**Currently, we have no patches to run.** diff --git a/aio/tools/example-zipper/README.md b/aio/tools/example-zipper/README.md index 344f68fe2b3bb..1a1f5f01ecaf1 100644 --- a/aio/tools/example-zipper/README.md +++ b/aio/tools/example-zipper/README.md @@ -1,13 +1,14 @@ # Overview -In the AIO application, we offer the reader the option to download each example as a full self-contained -runnable project packaged as a zip file. These zip files are generated by the utility in this folder. +In the AIO application, we offer the reader the option to download each example as a full self-contained runnable project packaged as a zip file. +These zip files are generated by the utility in this folder. ## Example zipper -The `exampleZipper.js` tool is very similar to the Stackblitz's `builder.js`. The latter creates an HTML file -with all the examples' files and the former creates a zip file instead. They both use the `stackblitz.json` file -to flag an example as something to stackblitz or zip. For example: +The `exampleZipper.js` tool is very similar to the Stackblitz's `builder.js`. +The latter creates an HTML file with all the examples' files and the former creates a zip file instead. +They both use the `stackblitz.json` file to flag an example as something to stackblitz or zip. +For example: ```json { @@ -41,8 +42,7 @@ The `exampleZipper.js` won't include any `System.js` related files for CLI-based As mentioned, the tool uses the `stackblitz.json` as a flag and also a configuration file for the zipper. The problem is that not all examples have a stackblitz but they could offer a zip instead. -In those cases, you can create a `zipper.json` file with the same syntax. It will be ignored by the -stackblitz tool. +In those cases, you can create a `zipper.json` file with the same syntax. It will be ignored by the stackblitz tool. ## Executing the zip generation @@ -50,5 +50,4 @@ stackblitz tool. Where? At `src/generated/zips/`. -Then the `` embedded component will look at this folder to get the zip it needs for -the example. +Then the `` embedded component will look at this folder to get the zip it needs for the example. diff --git a/aio/tools/examples/README.md b/aio/tools/examples/README.md index 85a83bdc8ab66..12bf0830ab0a1 100644 --- a/aio/tools/examples/README.md +++ b/aio/tools/examples/README.md @@ -1,110 +1,165 @@ # Overview -Many of the documentation pages contain snippets of code examples. Extract these snippets from -real working example applications, which are stored in subfolders of the `/aio/content/examples` -folder. Each example can be built and run independently. Each example also provides e2e specs, which -are run as part of our CircleCI legacy build tasks, to verify that the examples continue to work as -expected, as changes are made to the core Angular libraries. +Many of the documentation pages contain snippets of code examples. +These snippets are extracted from real working example applications, which are stored in sub-folders of the [aio/content/examples/](.) folder. +Each example can be built and run independently. +Each example also provides tests (mostly e2e and occasionally unit tests), which are run as part of our CircleCI `test_docs_examples*` jobs, to verify that the examples continue to work as expected, as changes are made to the core Angular libraries. -In order to build, run and test these examples independently you need to install dependencies into -their sub-folder. Also there are a number of common boilerplate files that are needed to configure -each example's project. Maintain these common boilerplate files centrally to reduce the amount -of effort if one of them needs to change. +In order to build, run and test these examples independently, you need to install dependencies into their sub-folder. +Also there are a number of common boilerplate files that are needed to configure each example's project. +These common boilerplate files are maintained centrally to reduce the amount of effort if one of them needs to change. > **Note for Windows users** > -> Setting up the examples involves creating some [symbolic links](https://en.wikipedia.org/wiki/Symbolic_link) (see [here](#symlinked-node_modules) for details). On Windows, this requires to either have [Developer Mode enabled](https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10) (supported on Windows 10 or newer) or run the setup commands as administrator. +> Setting up the examples involves creating some [symbolic links](https://en.wikipedia.org/wiki/Symbolic_link) (see [here](#symlinked-node_modules) for details). +> On Windows, this requires to either have [Developer Mode enabled](https://blogs.windows.com/windowsdeveloper/2016/12/02/symlinks-windows-10) (supported on Windows 10 or newer) or run the setup commands as administrator. + ## Boilerplate overview -As mentioned, many of the documentation pages contain snippets extracted from real example applications. -To achieve that, all those applications needs to contain a basic boilerplate. E.g. a `node_modules` -folder, `package.json` with scripts, etc. +As mentioned above, many of the documentation pages contain snippets extracted from real example applications. +To achieve that, all those applications need to contain some basic boilerplate, such as a `node_modules/` folder, a `package.json` file with scripts and dependencies, etc. + +There are also different project types, each with its own boilerplate. +For example, there are projects based on the Angular CLI, projects that use AngularJS, Custom Elements, i18n, server-side rendering, etc. +(See the [example configuration section](#example-config) below for more info on how to specify the project type.) + +To avoid having to maintain the boilerplate in each example, we use the [example-boilerplate-js](./example-boilerplate.js) script to provide a set of files that works across all the examples of a specific type. -No one wants to maintain the boilerplate on each example, so the goal of this tool is to provide a set of files that works across all the examples. ### Boilerplate files -Inside `/aio/tools/examples/shared/boilerplate` you will find a set of folders representing each project type. +Inside [shared/boilerplate/](./shared/boilerplate) there is a sub-folder with boilerplate files for each of the different project types. + +Currently, the following project types are supported: -Currently you will find the next project types: +- `cli`: For example apps based on the Angular CLI. This is the default type and is used in the majority of the examples. +- `cli-ajs`: For CLI-based examples that also use AngularJS (but not via `@angular/upgrade`). +- `elements`: For CLI-based examples that also use `@angular/elements`. +- `getting-started`: For the "Getting started" tutorial. Essentially the same as `cli` but with custom CSS styles. +- `i18n`: For CLI-based examples that also use internationalization. +- `schematics`: For CLI-based examples that include a library with schematics. +- `service-worker`: For CLI-based examples that also use `@angular/service-worker`. +- `systemjs`: For non-CLI legacy examples using SystemJS. This is deprecated and only used in few examples. +- `testing`: For CLI-based examples that are related to unit testing. +- `universal`: For CLI-based examples that also use `@nguniversal/express-engine` for SSR. -* cli - For CLI based examples. This is the default one, to be used in the majority of the examples. -* getting-started - CLI-based with its own set of styles. -* i18n - CLI-based with additional scripts for internationalization. -* schematics - CLI-based with additional scripts for building schematics. -* service-worker - CLI-based with additional packages and configuration for service workers. -* systemjs - Currently in deprecation, only used in a few examples. -* testing - CLI-based with additional styles for jasmine testing. -* universal - CLI-based with an extra server target. -* viewengine - Additional configuration for running CLI-/SystemJS-based examples with `ViewEngine` (the pre-Ivy compiler/renderer). +There are also the following special folders: +- `common`: Contains files used in many examples. + (See the [next section](#example-config) for info on how to exclude common files in certain examples.) +- `viewengine/cli`: Additional configuration for running CLI-based examples with `ViewEngine` (the pre-Ivy compiler/renderer). + This applies to all CLI-based examples, such as `cli-ajs`, `elements`, `getting-started`, etc. +- `viewengine/systemjs`: Additional configuration for running SystemJS-based examples with `ViewEngine` (the pre-Ivy compiler/renderer). -There is also a `common` folder that contains files used in all different examples. -### The example-config.json + +### The `example-config.json` -Each example is identified by an **example-config.json** configuration file in its root folder. -This configuration file indicates what type of boilerplate this example needs. E.g. +Each example is identified by an `example-config.json` configuration file in its root folder. +This configuration file indicates what type of boilerplate this example needs and how to test it. +For example: ```json { - "projectType": "cli", - "useCommonBoilerplate": true + "projectType": "cli" } ``` -If the file is empty then the default type of cli is assumed. -When the boilerplate tooling runs, it will copy into the example folder all of the appropriate files based on the project type. +The file is expected to contain a JSON object with zero or more of the following properties: + +- `projectType: string`: One of the supported project types (see above). + Default: `"cli"` +- `useCommonBoilerplate: boolean`: Whether to include common boilerplate from the [common/](./shared/boilerplate/common) folder. + Default: `true` + +**SystemJS-only properties:** +- `build: string`: The npm script to run in order to build the example app. + Default: `"build"` +- `run: string`: The npm script to run in order to serve the example app (so that e2e test can be run against it). + Default `"serve:e2e"` + +**CLI-only properties:** +- `tests: object[]`: An array of objects, each specifying a test command. This can be used to run multiple test commands in series (for example, to run unit and e2e tests). + The commands are specified as `{cmd: string, args: string[]}` and must be in a format that could be passed to Node.js' `child_process.spawn(cmd, args)`. You can use a special `{PORT}` placeholder, that will be replaced with the port on which the app is served during the actual test. + Default: + + ```json + [ + { + "cmd": "yarn", + "args": [ + "e2e", + "--prod", + "--protractor-config=e2e/protractor-puppeteer.conf.js", + "--no-webdriver-update", + "--port={PORT}" + ] + } + ] + ``` + +An empty `example-config.json` file is equivalent with `{"projectType": "cli"}`. + -### A node_modules to share +### A `node_modules/` to share -With all the boilerplate files in place, the only missing piece are the installed packages. For -that you have a `/aio/tools/examples/shared/package.json` which contains **all** the packages -needed to run all the examples through all different boilerplates. +With all the boilerplate files in place, the only missing piece is the installed packages. +For that we have [shared/package.json](./shared/package.json), which contains **all** the packages needed to run any example type. -After installing these dependencies, a `node_modules/` folder will be created at -`/aio/tools/examples/shared/node_modules/`. This folder will be **symlinked** into each example. +Upon installing these dependencies, a [shared/node_modules/](./shared/node_modules) folder is created. +This folder will be **symlinked** into each example. So it is not a copy like the other boilerplate files. -### End to end tests -End to end changes between boilerplates. +### End-to-end tests -For CLI applications, create a `app.e2e-spec.ts` inside the `e2e` folder. The tooling will run -`ng e2e` for each CLI based examples. +End-to-end infrastructure is slightly different between CLI- and SystemJS-based examples. -For SystemJS, each example contains an `e2e-spec.ts` file. You can find all the related configuration files -in the `/aio/tools/examples/shared` folder. +For CLI-based examples, create an `app.e2e-spec.ts` file inside the `e2e/` folder. +This will be picked up by the default testing command (see the [example configuration section](#example-config) above). +If you are using a custom test command, make sure e2e specs are picked up (if applicable). -### example-boilerplate.js +For SystemJS-based examples, create an `e2e-spec.ts` file inside the example root folder. +These apps will be tested with the following command: -This script installs all the dependencies that are shared among all the examples, creates the -`node_modules` symlinks and copy all the boilerplate files where needed. It won't do anything -about stackblitz nor e2e tests. +```sh +yarn protractor aio/tools/examples/shared/protractor.config.js \ + --specs=/e2e-spec.ts \ + --params.appDir= +``` -It also contains a function to remove all the boilerplate. It uses a `git clean -xdf` to do -the job. It will remove all files that don't exist in the git repository, **including any -new file that you are working on that hasn't been stage yet.** So be sure to save your work -before removing the boilerplate. -### run-example-e2e.js +### `example-boilerplate.js` -This script will find all the `e2e-spec.ts` files and run them. +The [example-boilerplate.js](./example-boilerplate.js) script installs the dependencies for all examples, creates the `node_modules/` symlinks and copies the necessary boilerplate files into example folders. -To not run all tests, you can use the `--filter=name` flag to run the example's e2e that contains -that name. +It also contains a function to remove all the boilerplate. +It uses `git clean -xdf` to do the job. +It will remove all files that are not tracked by git, **including any new files that you are working on that haven't been stageg yet.** +So, be sure to commit your work before removing the boilerplate. -It also has an optional `--setup` flag to run the `example-boilerplate.js` script and install -the latest `webdriver`. -It will create a `/aio/protractor-results.txt` file when it finishes running tests. +### `run-example-e2e.js` -### Updating example dependencies +The [run-example-e2e.js](./run-example-e2e.js) script will find and run the e2e tests for all examples. +Although it only runs e2e tests by default, it can be configured to run any test command (for CLI-based examples) by using the `tests` property of the [example-config.json](#example-config) file. +It is named `*-e2e` for historical reasons, but it is not limited to running e2e tests. -With every major release, we update the examples to be on the latest version. The following steps to update are: +See [aio/README.md](../../README.md#developer-tasks) for the available command-line options. + +Running the script will create an `aio/protractor-results.txt` file with the results of the tests. + +### `create-example.js` + +The [create-example.js](./create-example.js) script creates a new example under the `aio/content/examples` directory. + +You must provide a new name for the example. +By default the script will place basic scaffold files into the new example (from [shared/example-scaffold](./shared/example-scaffold)). +But you can also specify the path to a separate CLI project, from which the script will copy files that would not be considered "boilerplate". +See the [Boilerplate overview](#boilerplate-overview) for more information. + +### Updating example dependencies -* In the `shared/package.json` file, bump all the `@angular/*`, `@angular-devkit/*`, `rxjs`, `typescript`, and `zone.js` package versions to the version that corresponds with the [framework version](../../../package.json). -* In the `shared` folder, run `yarn` to update the dependencies for the shared `node_modules` and the `yarn.lock` file. -* In the `boilerplate` folder, go through each sub-folder and update the `package.json` dependencies if one is present. -* Follow the [update guide](./shared/boilerplate/UPDATING_CLI.md) to update the common files used in the examples based on project type. +With every major Angular release, we update the examples to be on the latest version. +See [UPDATING.md](./UPDATING.md) for instructions. diff --git a/aio/tools/examples/UPDATING.md b/aio/tools/examples/UPDATING.md new file mode 100644 index 0000000000000..2c823e7422ad6 --- /dev/null +++ b/aio/tools/examples/UPDATING.md @@ -0,0 +1,55 @@ +# Update example dependencies + +Follow these steps to update the examples to the latest versions of Angular (and related dependencies): + +- In [shared/package.json](./shared/package.json), bump all the `@angular/*` and `@nguniversal/*` package versions to the version you want to update to and update their peer dependencies (such as `@angular-devkit/*`, `rxjs`, `typescript`, `zone.js`) and other dependencies (e.g. `@types/*`) to the latest compatible versions. + + > NOTE: + > The [angular-cli-diff](https://github.com/cexbrayat/angular-cli-diff) repo can be a useful resource for discovering what dependency versions are used for a basic CLI app at a specific CLI version. + +- In the [shared/](./shared) directory, run `yarn` to update the dependencies in the [shared/node_modules/](./shared/node_modules) directory and the [shared/yarn.lock](./shared/yarn.lock) file. + +- In the [shared/](./shared) directory, run `yarn sync-deps` to update the dependency versions of the `package.json` files in each sub-folder of [shared/boilerplate/](./shared/boilerplate) to match the ones in [shared/package.json](./shared/package.json). + +- Follow the steps in the following section to update the rest of the boilerplate files. + + +## Update other boilerplate files + +The Angular CLI default setup is updated using `ng update`. +Any necessary changes to boilerplate files will be done automatically through migration schematics. + +> NOTE: +> Migrations affecting source code files will not happen automatically, because `ng update` does not know about all the examples in `aio/content/examples/`. +> You have to make these changes (if any) manually. +> Again, the [angular-cli-diff](https://github.com/cexbrayat/angular-cli-diff) repo can be a useful resource for discovering changes between versions. + +- In the [shared/boilerplate/cli/](./shared/boilerplate/cli) directory, run the following commands to migrate the the project to the current versions of Angular CLI and the Angular framework (updated in previous steps): + ```sh + # Ensure dependencies are installed. + yarn install + + # Migrate project to new versions. + yarn ng update @angular/cli --migrate-only --from= + yarn ng update @angular/core --migrate-only --from= + ``` + + > NOTE: + > In order for `ng update` to work, there must be a `node_modules/` directory with installed dependencies inside the [shared/boilerplate/cli/](./shared/boilerplate/cli) directory. + > This `node_modules/` directory is only needed during the update operation and is otherwise ignored (both by git and by the [example-boilerplate.js](./example-boilerplate.js) script) by means of the [shared/boilerplate/.gitignore](./shared/boilerplate/.gitignore) file. + +- The previous command made any necessary changes to boilerplate files inside the `cli/` directory, but the same changes need to be applied to the other CLI-based boilerplate directories. + Inspect the changes in `cli/` and manually apply the necessary ones to other CLI-based boilerplate directories. + +- Also ensure that any relevant changes in the [shared/boilerplate/cli/](./shared/boilerplate/cli) directory are copied to the [shared/example-scaffold/](./shared/example-scaffold) directory, which is used when creating new examples (via `yarn create-example ...`). + Only files that would not be considered boilerplate should be added to the `example-scaffold/` directory. + +- Ensure any changes to [cli/tslint.json](./shared/boilerplate/cli/tslint.json) are ported over to [systemjs/tslint.json](./shared/boilerplate/systemjs/tslint.json) and also [aio/content/examples/tslint.json](../../content/examples/tslint.json). + This last part is important, since this file is used to lint example code on CI. + +- Inspect the changes and determine whether some of them need to be applied to the `systemjs` boilerplate files. + +- Inspect the changes and determine whether any updates to guides are necessary. + For example, if a file is renamed or moved, any guides mentioning that file may need updating to refer to the new name/location. + +- Commit all changes to the repository. diff --git a/aio/tools/examples/constants.js b/aio/tools/examples/constants.js new file mode 100644 index 0000000000000..c7d590d9d93f7 --- /dev/null +++ b/aio/tools/examples/constants.js @@ -0,0 +1,6 @@ +const path = require('canonical-path'); + +exports.EXAMPLES_BASE_PATH = path.resolve(__dirname, '../../content/examples'); +exports.EXAMPLE_CONFIG_FILENAME = 'example-config.json'; +exports.SHARED_PATH = path.resolve(__dirname, 'shared'); +exports.STACKBLITZ_CONFIG_FILENAME = 'stackblitz.json'; diff --git a/aio/tools/examples/create-example.js b/aio/tools/examples/create-example.js new file mode 100644 index 0000000000000..7db729e1f5243 --- /dev/null +++ b/aio/tools/examples/create-example.js @@ -0,0 +1,140 @@ +const fs = require('fs-extra'); +const glob = require('glob'); +const ignore = require('ignore'); +const path = require('canonical-path'); +const shelljs = require('shelljs'); +const yargs = require('yargs'); + +const {EXAMPLES_BASE_PATH, EXAMPLE_CONFIG_FILENAME, SHARED_PATH, STACKBLITZ_CONFIG_FILENAME} = + require('./constants'); +const BASIC_SOURCE_PATH = path.resolve(SHARED_PATH, 'example-scaffold'); + +shelljs.set('-e'); + +if (require.main === module) { + const options = + yargs(process.argv.slice(2)) + .command( + '$0 [source]', + [ + 'Create a new example.', + '', + 'If [source] is provided then the relevant files from the CLI project at that path are copied into the example.', + ].join('\n')) + .strict() + .version(false) + .argv; + + const exampleName = options.name; + const examplePath = path.resolve(EXAMPLES_BASE_PATH, exampleName); + + console.log('Creating new example at', examplePath); + createEmptyExample(exampleName, examplePath); + + const sourcePath = + options.source !== undefined ? path.resolve(options.source) : BASIC_SOURCE_PATH; + console.log('Copying files from', sourcePath); + copyExampleFiles(sourcePath, examplePath, exampleName); + + console.log(`The new "${exampleName}" example has been created.`); + console.log('Now run "yarn boilerplate:add" to set it up for development.'); + console.log( + 'You can find more info on working with docs examples in aio/tools/examples/README.md.') +} + +/** + * Create the directory and marker files for the new example. + */ +function createEmptyExample(exampleName, examplePath) { + ensureExamplePath(examplePath); + writeExampleConfigFile(examplePath); + writeStackBlitzFile(exampleName, examplePath); +} + +/** + * Ensure that the new example directory exists. + */ +function ensureExamplePath(examplePath) { + if (fs.existsSync(examplePath)) { + throw new Error( + `Unable to create example. The path to the new example already exists: ${examplePath}`); + } + fs.ensureDirSync(examplePath); +} + +/** + * Write the `example-config.json` file to the new example. + */ +function writeExampleConfigFile(examplePath) { + fs.writeFileSync(path.resolve(examplePath, EXAMPLE_CONFIG_FILENAME), ''); +} + +/** + * Write the `stackblitz.json` file into the new example. + */ +function writeStackBlitzFile(exampleName, examplePath) { + const config = { + description: titleize(exampleName), + files: ['!**/*.d.ts', '!**/*.js', '!**/*.[1,2].*'], + tags: [exampleName.split('-')] + }; + fs.writeFileSync( + path.resolve(examplePath, STACKBLITZ_CONFIG_FILENAME), + JSON.stringify(config, null, 2) + '\n'); +} + +/** + * Copy all the files from the `sourcePath`, which are not ignored by the `.gitignore` file in the + * `EXAMPLES_BASE_PATH`, to the `examplePath`. + */ +function copyExampleFiles(sourcePath, examplePath, exampleName) { + const gitIgnoreSource = getGitIgnore(sourcePath); + const gitIgnoreExamples = getGitIgnore(EXAMPLES_BASE_PATH); + + // Grab the files in the source folder and filter them based on the gitignore rules. + const sourceFiles = + glob.sync('**/*', { + cwd: sourcePath, + dot: true, + ignore: ['**/node_modules/**', '.git/**', '.gitignore'], + mark: true + }) + // Filter out the directories, leaving only files + .filter(filePath => !/\/$/.test(filePath)) + // Filter out files that match the source directory .gitignore rules + .filter(filePath => !gitIgnoreSource.ignores(filePath)) + // Filter out files that match the examples directory .gitignore rules + .filter(filePath => !gitIgnoreExamples.ignores(path.join(exampleName, filePath))); + + for (const sourceFile of sourceFiles) { + console.log(' - ', sourceFile); + const destPath = path.resolve(examplePath, sourceFile) + fs.ensureDirSync(path.dirname(destPath)); + fs.copySync(path.resolve(sourcePath, sourceFile), destPath); + } +} + +function getGitIgnore(directory) { + const gitIgnoreMatcher = ignore(); + const gitignoreFilePath = path.resolve(directory, '.gitignore'); + if (fs.existsSync(gitignoreFilePath)) { + const gitignoreFile = fs.readFileSync(gitignoreFilePath, 'utf8'); + gitIgnoreMatcher.add(gitignoreFile); + } + return gitIgnoreMatcher; +} + +/** + * Convert a kebab-case string to space separated Title Case string. + */ +function titleize(input) { + return input.replace( + /(-|^)(.)/g, (_, pre, char) => `${pre === '-' ? ' ' : ''}${char.toUpperCase()}`); +} + +exports.createEmptyExample = createEmptyExample; +exports.ensureExamplePath = ensureExamplePath; +exports.writeExampleConfigFile = writeExampleConfigFile; +exports.writeStackBlitzFile = writeStackBlitzFile; +exports.copyExampleFiles = copyExampleFiles; +exports.titleize = titleize; \ No newline at end of file diff --git a/aio/tools/examples/create-example.spec.js b/aio/tools/examples/create-example.spec.js new file mode 100644 index 0000000000000..79b1992449ec8 --- /dev/null +++ b/aio/tools/examples/create-example.spec.js @@ -0,0 +1,130 @@ +const path = require('canonical-path'); +const fs = require('fs-extra'); +const {glob} = require('glob'); + +const {EXAMPLES_BASE_PATH, EXAMPLE_CONFIG_FILENAME, SHARED_PATH, STACKBLITZ_CONFIG_FILENAME} = + require('./constants'); + +const { + copyExampleFiles, + createEmptyExample, + ensureExamplePath, + titleize, + writeExampleConfigFile, + writeStackBlitzFile +} = require('./create-example'); + +describe('create-example tool', () => { + describe('createEmptyExample', () => { + it('should create an empty example with marker files', () => { + spyOn(fs, 'existsSync').and.returnValue(false); + spyOn(fs, 'ensureDirSync'); + const writeFileSpy = spyOn(fs, 'writeFileSync'); + + createEmptyExample('foo-bar', '/path/to/foo-bar'); + expect(writeFileSpy).toHaveBeenCalledTimes(2); + expect(writeFileSpy) + .toHaveBeenCalledWith(`/path/to/foo-bar/${EXAMPLE_CONFIG_FILENAME}`, jasmine.any(String)); + expect(writeFileSpy) + .toHaveBeenCalledWith( + `/path/to/foo-bar/${STACKBLITZ_CONFIG_FILENAME}`, jasmine.any(String)); + }); + }); + + describe('ensureExamplePath', () => { + it('should error if the path already exists', () => { + spyOn(fs, 'existsSync').and.returnValue(true); + expect(() => ensureExamplePath('foo/bar')) + .toThrowError( + `Unable to create example. The path to the new example already exists: foo/bar`); + }); + + it('should create the directory on disk', () => { + spyOn(fs, 'existsSync').and.returnValue(false); + const spy = spyOn(fs, 'ensureDirSync'); + ensureExamplePath('foo/bar'); + expect(spy).toHaveBeenCalledWith('foo/bar'); + }); + }); + + describe('writeExampleConfigFile', () => { + it('should write a JSON file to disk', () => { + const spy = spyOn(fs, 'writeFileSync'); + writeExampleConfigFile('/foo/bar'); + expect(spy).toHaveBeenCalledWith(`/foo/bar/${EXAMPLE_CONFIG_FILENAME}`, ''); + }); + }); + + describe('writeStackBlitzFile', () => { + it('should write a JSON file to disk', () => { + const spy = spyOn(fs, 'writeFileSync'); + writeStackBlitzFile('bar-bar', '/foo/bar-bar'); + expect(spy).toHaveBeenCalledWith(`/foo/bar-bar/${STACKBLITZ_CONFIG_FILENAME}`, [ + '{', + ' "description": "Bar Bar",', + ' "files": [', + ' "!**/*.d.ts",', + ' "!**/*.js",', + ' "!**/*.[1,2].*"', + ' ],', + ' "tags": [', + ' [', + ' "bar",', + ' "bar"', + ' ]', + ' ]', + '}', + '', + ].join('\n')); + }); + }); + + describe('copyExampleFiles', () => { + it('should copy over files that are not ignored by git', () => { + const examplesGitIgnorePath = path.resolve(EXAMPLES_BASE_PATH, '.gitignore'); + const sourceGitIgnorePath = path.resolve('/source/path', '.gitignore'); + + spyOn(console, 'log'); + spyOn(fs, 'existsSync').and.returnValue(true); + const readFileSyncSpy = spyOn(fs, 'readFileSync').and.callFake(p => { + switch (p) { + case examplesGitIgnorePath: + return '**/a/b/**'; + case sourceGitIgnorePath: + return '**/*.bad'; + default: + throw new Error('Unexpected path'); + } + }); + spyOn(glob, 'sync').and.returnValue([ + 'a/', 'a/b/', 'a/c', 'x.ts', 'x.bad', 'a/b/y.ts', 'a/b/y.bad' + ]); + const ensureDirSyncSpy = spyOn(fs, 'ensureDirSync'); + const copySyncSpy = spyOn(fs, 'copySync'); + + copyExampleFiles('/source/path', '/path/to/test-example', 'test-example'); + + expect(readFileSyncSpy).toHaveBeenCalledWith(examplesGitIgnorePath, 'utf8'); + expect(readFileSyncSpy).toHaveBeenCalledWith(sourceGitIgnorePath, 'utf8'); + + expect(ensureDirSyncSpy.calls.allArgs()).toEqual([ + ['/path/to/test-example/a'], + ['/path/to/test-example'], + ]); + + expect(copySyncSpy.calls.allArgs()).toEqual([ + ['/source/path/a/c', '/path/to/test-example/a/c'], + ['/source/path/x.ts', '/path/to/test-example/x.ts'], + ]); + }); + }); + + describe('titleize', () => { + it('should convert a kebab-case string to title-case', () => { + expect(titleize('abc')).toEqual('Abc'); + expect(titleize('abc-def')).toEqual('Abc Def'); + expect(titleize('123')).toEqual('123'); + expect(titleize('abc---def')).toEqual('Abc - Def'); + }); + }); +}); diff --git a/aio/tools/examples/example-boilerplate.js b/aio/tools/examples/example-boilerplate.js index bc1c939656426..5a2909f0ec511 100644 --- a/aio/tools/examples/example-boilerplate.js +++ b/aio/tools/examples/example-boilerplate.js @@ -1,10 +1,11 @@ const fs = require('fs-extra'); const glob = require('glob'); +const ignore = require('ignore'); const path = require('canonical-path'); const shelljs = require('shelljs'); const yargs = require('yargs'); +const {EXAMPLES_BASE_PATH, EXAMPLE_CONFIG_FILENAME, SHARED_PATH} = require('./constants'); -const SHARED_PATH = path.resolve(__dirname, 'shared'); const SHARED_NODE_MODULES_PATH = path.resolve(SHARED_PATH, 'node_modules'); const BOILERPLATE_BASE_PATH = path.resolve(SHARED_PATH, 'boilerplate'); @@ -12,9 +13,6 @@ const BOILERPLATE_CLI_PATH = path.resolve(BOILERPLATE_BASE_PATH, 'cli'); const BOILERPLATE_COMMON_PATH = path.resolve(BOILERPLATE_BASE_PATH, 'common'); const BOILERPLATE_VIEWENGINE_PATH = path.resolve(BOILERPLATE_BASE_PATH, 'viewengine'); -const EXAMPLES_BASE_PATH = path.resolve(__dirname, '../../content/examples'); -const EXAMPLE_CONFIG_FILENAME = 'example-config.json'; - class ExampleBoilerPlate { /** * Add boilerplate files to all the examples @@ -23,6 +21,8 @@ class ExampleBoilerPlate { // Get all the examples folders, indicated by those that contain a `example-config.json` file const exampleFolders = this.getFoldersContaining(EXAMPLES_BASE_PATH, EXAMPLE_CONFIG_FILENAME, 'node_modules'); + const gitignore = ignore().add(fs.readFileSync(path.resolve(BOILERPLATE_BASE_PATH, '.gitignore'), 'utf8')); + const isPathIgnored = absolutePath => gitignore.ignores(path.relative(BOILERPLATE_BASE_PATH, absolutePath)); if (!fs.existsSync(SHARED_NODE_MODULES_PATH)) { throw new Error( @@ -48,22 +48,22 @@ class ExampleBoilerPlate { // boilerplate files first. // (Some of these files might be later overwritten by type-specific files.) if (boilerPlateType !== 'cli' && boilerPlateType !== 'systemjs') { - this.copyDirectoryContents(BOILERPLATE_CLI_PATH, exampleFolder); + this.copyDirectoryContents(BOILERPLATE_CLI_PATH, exampleFolder, isPathIgnored); } // Copy the type-specific boilerplate files. - this.copyDirectoryContents(boilerPlateBasePath, exampleFolder); + this.copyDirectoryContents(boilerPlateBasePath, exampleFolder, isPathIgnored); // Copy the common boilerplate files (unless explicitly not used). if (exampleConfig.useCommonBoilerplate !== false) { - this.copyDirectoryContents(BOILERPLATE_COMMON_PATH, exampleFolder); + this.copyDirectoryContents(BOILERPLATE_COMMON_PATH, exampleFolder, isPathIgnored); } // Copy ViewEngine (pre-Ivy) specific files if (viewengine) { const veBoilerPlateType = boilerPlateType === 'systemjs' ? 'systemjs' : 'cli'; const veBoilerPlateBasePath = path.resolve(BOILERPLATE_VIEWENGINE_PATH, veBoilerPlateType); - this.copyDirectoryContents(veBoilerPlateBasePath, exampleFolder); + this.copyDirectoryContents(veBoilerPlateBasePath, exampleFolder, isPathIgnored); } }); } @@ -89,25 +89,30 @@ class ExampleBoilerPlate { loadJsonFile(filePath) { return fs.readJsonSync(filePath, {throws: false}) || {}; } - copyDirectoryContents(srcDir, dstDir) { + copyDirectoryContents(srcDir, dstDir, isPathIgnored) { shelljs.ls('-Al', srcDir).forEach(stat => { const srcPath = path.resolve(srcDir, stat.name); const dstPath = path.resolve(dstDir, stat.name); + if (isPathIgnored(srcPath)) { + // `srcPath` is ignored (e.g. by a `.gitignore` file): Ignore it. + return; + } + if (stat.isDirectory()) { // `srcPath` is a directory: Recursively copy it to `dstDir`. shelljs.mkdir('-p', dstPath); - return this.copyDirectoryContents(srcPath, dstPath); - } else { - // `srcPath` is a file: Copy it to `dstDir`. - // (Also make the file non-writable to avoid accidental editing of boilerplate files). - if (shelljs.test('-f', dstPath)) { - // If the file already exists, ensure it is writable (so it can be overwritten). - shelljs.chmod(666, dstPath); - } - shelljs.cp(srcPath, dstDir); - shelljs.chmod(444, dstPath); + return this.copyDirectoryContents(srcPath, dstPath, isPathIgnored); + } + + // `srcPath` is a file: Copy it to `dstDir`. + // (Also make the file non-writable to avoid accidental editing of boilerplate files). + if (shelljs.test('-f', dstPath)) { + // If the file already exists, ensure it is writable (so it can be overwritten). + shelljs.chmod(666, dstPath); } + shelljs.cp(srcPath, dstDir); + shelljs.chmod(444, dstPath); }); } } diff --git a/aio/tools/examples/example-boilerplate.spec.js b/aio/tools/examples/example-boilerplate.spec.js index cff911a1c38d3..f716f5c434492 100644 --- a/aio/tools/examples/example-boilerplate.spec.js +++ b/aio/tools/examples/example-boilerplate.spec.js @@ -56,10 +56,10 @@ describe('example-boilerplate tool', () => { expect(exampleBoilerPlate.copyDirectoryContents).toHaveBeenCalledTimes(4); expect(exampleBoilerPlate.copyDirectoryContents.calls.allArgs()).toEqual([ - [`${boilerplateDir}/systemjs`, 'a/b'], - [`${boilerplateDir}/common`, 'a/b'], - [`${boilerplateDir}/systemjs`, 'c/d'], - [`${boilerplateDir}/common`, 'c/d'], + [`${boilerplateDir}/systemjs`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/common`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/systemjs`, 'c/d', jasmine.any(Function)], + [`${boilerplateDir}/common`, 'c/d', jasmine.any(Function)], ]); }); @@ -71,10 +71,10 @@ describe('example-boilerplate tool', () => { expect(exampleBoilerPlate.copyDirectoryContents).toHaveBeenCalledTimes(4); expect(exampleBoilerPlate.copyDirectoryContents.calls.allArgs()).toEqual([ - [`${boilerplateDir}/cli`, 'a/b'], - [`${boilerplateDir}/common`, 'a/b'], - [`${boilerplateDir}/cli`, 'c/d'], - [`${boilerplateDir}/common`, 'c/d'], + [`${boilerplateDir}/cli`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/common`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/cli`, 'c/d', jasmine.any(Function)], + [`${boilerplateDir}/common`, 'c/d', jasmine.any(Function)], ]); }); @@ -86,10 +86,10 @@ describe('example-boilerplate tool', () => { expect(exampleBoilerPlate.copyDirectoryContents).toHaveBeenCalledTimes(4); expect(exampleBoilerPlate.copyDirectoryContents.calls.allArgs()).toEqual([ - [`${boilerplateDir}/cli`, 'a/b'], - [`${boilerplateDir}/common`, 'a/b'], - [`${boilerplateDir}/cli`, 'c/d'], - [`${boilerplateDir}/common`, 'c/d'], + [`${boilerplateDir}/cli`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/common`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/cli`, 'c/d', jasmine.any(Function)], + [`${boilerplateDir}/common`, 'c/d', jasmine.any(Function)], ]); }); @@ -101,12 +101,12 @@ describe('example-boilerplate tool', () => { expect(exampleBoilerPlate.copyDirectoryContents).toHaveBeenCalledTimes(6); expect(exampleBoilerPlate.copyDirectoryContents.calls.allArgs()).toEqual([ - [`${boilerplateDir}/cli`, 'a/b'], - [`${boilerplateDir}/i18n`, 'a/b'], - [`${boilerplateDir}/common`, 'a/b'], - [`${boilerplateDir}/cli`, 'c/d'], - [`${boilerplateDir}/i18n`, 'c/d'], - [`${boilerplateDir}/common`, 'c/d'], + [`${boilerplateDir}/cli`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/i18n`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/common`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/cli`, 'c/d', jasmine.any(Function)], + [`${boilerplateDir}/i18n`, 'c/d', jasmine.any(Function)], + [`${boilerplateDir}/common`, 'c/d', jasmine.any(Function)], ]); }); @@ -118,12 +118,12 @@ describe('example-boilerplate tool', () => { expect(exampleBoilerPlate.copyDirectoryContents).toHaveBeenCalledTimes(6); expect(exampleBoilerPlate.copyDirectoryContents.calls.allArgs()).toEqual([ - [`${boilerplateDir}/cli`, 'a/b'], - [`${boilerplateDir}/universal`, 'a/b'], - [`${boilerplateDir}/common`, 'a/b'], - [`${boilerplateDir}/cli`, 'c/d'], - [`${boilerplateDir}/universal`, 'c/d'], - [`${boilerplateDir}/common`, 'c/d'], + [`${boilerplateDir}/cli`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/universal`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/common`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/cli`, 'c/d', jasmine.any(Function)], + [`${boilerplateDir}/universal`, 'c/d', jasmine.any(Function)], + [`${boilerplateDir}/common`, 'c/d', jasmine.any(Function)], ]); }); @@ -148,12 +148,12 @@ describe('example-boilerplate tool', () => { expect(exampleBoilerPlate.copyDirectoryContents).toHaveBeenCalledTimes(6); expect(exampleBoilerPlate.copyDirectoryContents.calls.allArgs()).toEqual([ - [`${boilerplateDir}/systemjs`, 'a/b'], - [`${boilerplateDir}/common`, 'a/b'], - [`${boilerplateDir}/viewengine/systemjs`, 'a/b'], - [`${boilerplateDir}/systemjs`, 'c/d'], - [`${boilerplateDir}/common`, 'c/d'], - [`${boilerplateDir}/viewengine/systemjs`, 'c/d'], + [`${boilerplateDir}/systemjs`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/common`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/viewengine/systemjs`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/systemjs`, 'c/d', jasmine.any(Function)], + [`${boilerplateDir}/common`, 'c/d', jasmine.any(Function)], + [`${boilerplateDir}/viewengine/systemjs`, 'c/d', jasmine.any(Function)], ]); }); @@ -165,12 +165,12 @@ describe('example-boilerplate tool', () => { expect(exampleBoilerPlate.copyDirectoryContents).toHaveBeenCalledTimes(6); expect(exampleBoilerPlate.copyDirectoryContents.calls.allArgs()).toEqual([ - [`${boilerplateDir}/cli`, 'a/b'], - [`${boilerplateDir}/common`, 'a/b'], - [`${boilerplateDir}/viewengine/cli`, 'a/b'], - [`${boilerplateDir}/cli`, 'c/d'], - [`${boilerplateDir}/common`, 'c/d'], - [`${boilerplateDir}/viewengine/cli`, 'c/d'], + [`${boilerplateDir}/cli`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/common`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/viewengine/cli`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/cli`, 'c/d', jasmine.any(Function)], + [`${boilerplateDir}/common`, 'c/d', jasmine.any(Function)], + [`${boilerplateDir}/viewengine/cli`, 'c/d', jasmine.any(Function)], ]); }); @@ -182,14 +182,14 @@ describe('example-boilerplate tool', () => { expect(exampleBoilerPlate.copyDirectoryContents).toHaveBeenCalledTimes(8); expect(exampleBoilerPlate.copyDirectoryContents.calls.allArgs()).toEqual([ - [`${boilerplateDir}/cli`, 'a/b'], - [`${boilerplateDir}/elements`, 'a/b'], - [`${boilerplateDir}/common`, 'a/b'], - [`${boilerplateDir}/viewengine/cli`, 'a/b'], - [`${boilerplateDir}/cli`, 'c/d'], - [`${boilerplateDir}/elements`, 'c/d'], - [`${boilerplateDir}/common`, 'c/d'], - [`${boilerplateDir}/viewengine/cli`, 'c/d'], + [`${boilerplateDir}/cli`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/elements`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/common`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/viewengine/cli`, 'a/b', jasmine.any(Function)], + [`${boilerplateDir}/cli`, 'c/d', jasmine.any(Function)], + [`${boilerplateDir}/elements`, 'c/d', jasmine.any(Function)], + [`${boilerplateDir}/common`, 'c/d', jasmine.any(Function)], + [`${boilerplateDir}/viewengine/cli`, 'c/d', jasmine.any(Function)], ]); }); }); @@ -214,10 +214,12 @@ describe('example-boilerplate tool', () => { describe('copyDirectoryContents', () => { const spyFnFor = fnName => (...args) => { callLog.push(`${fnName}(${args.join(', ')})`); }; + let isPathIgnoredSpy; let callLog; beforeEach(() => { callLog = []; + isPathIgnoredSpy = jasmine.createSpy('isPathIgnored').and.returnValue(false); spyOn(shelljs, 'chmod').and.callFake(spyFnFor('chmod')); spyOn(shelljs, 'cp').and.callFake(spyFnFor('cp')); spyOn(shelljs, 'mkdir').and.callFake(spyFnFor('mkdir')); @@ -226,17 +228,17 @@ describe('example-boilerplate tool', () => { it('should list all contents of a directory', () => { const lsSpy = spyOn(shelljs, 'ls').and.returnValue([]); - exampleBoilerPlate.copyDirectoryContents('source/dir', 'destination/dir'); + exampleBoilerPlate.copyDirectoryContents('source/dir', 'destination/dir', isPathIgnoredSpy); expect(lsSpy).toHaveBeenCalledWith('-Al', 'source/dir'); }); - it('should use copy files and make them read-only', () => { + it('should copy files and make them read-only', () => { spyOn(shelljs, 'ls').and.returnValue([ {name: 'file-1.txt', isDirectory: () => false}, {name: 'file-2.txt', isDirectory: () => false}, ]); - exampleBoilerPlate.copyDirectoryContents('source/dir', 'destination/dir'); + exampleBoilerPlate.copyDirectoryContents('source/dir', 'destination/dir', isPathIgnoredSpy); expect(callLog).toEqual([ `test(-f, ${path.resolve('destination/dir/file-1.txt')})`, @@ -249,6 +251,22 @@ describe('example-boilerplate tool', () => { ]); }); + it('should skip files that are ignored', () => { + spyOn(shelljs, 'ls').and.returnValue([ + {name: 'file-1.txt', isDirectory: () => false}, + {name: 'file-2.txt', isDirectory: () => false}, + ]); + isPathIgnoredSpy.and.callFake(path => path.endsWith('file-1.txt')); + + exampleBoilerPlate.copyDirectoryContents('source/dir', 'destination/dir', isPathIgnoredSpy); + + expect(callLog).toEqual([ + `test(-f, ${path.resolve('destination/dir/file-2.txt')})`, + `cp(${path.resolve('source/dir/file-2.txt')}, destination/dir)`, + `chmod(444, ${path.resolve('destination/dir/file-2.txt')})`, + ]); + }); + it('should make existing files in destination writable before overwriting', () => { spyOn(shelljs, 'ls').and.returnValue([ {name: 'new-file.txt', isDirectory: () => false}, @@ -256,7 +274,7 @@ describe('example-boilerplate tool', () => { ]); shelljs.test.and.callFake((_, filePath) => filePath.endsWith('existing-file.txt')); - exampleBoilerPlate.copyDirectoryContents('source/dir', 'destination/dir'); + exampleBoilerPlate.copyDirectoryContents('source/dir', 'destination/dir', isPathIgnoredSpy); expect(callLog).toEqual([ `cp(${path.resolve('source/dir/new-file.txt')}, destination/dir)`, @@ -283,7 +301,7 @@ describe('example-boilerplate tool', () => { {name: 'file-4.txt', isDirectory: () => false}, ]); - exampleBoilerPlate.copyDirectoryContents('source/dir', 'destination/dir'); + exampleBoilerPlate.copyDirectoryContents('source/dir', 'destination/dir', isPathIgnoredSpy); expect(callLog).toEqual([ // Copy `file-1.txt`. @@ -317,6 +335,33 @@ describe('example-boilerplate tool', () => { `chmod(444, ${path.resolve('destination/dir/file-2.txt')})`, ]); }); + + it('should skip ignored directories', () => { + spyOn(shelljs, 'ls') + .withArgs('-Al', 'source/dir').and.returnValue([ + {name: 'file-1.txt', isDirectory: () => false}, + {name: 'sub-dir-1', isDirectory: () => true}, + ]) + .withArgs('-Al', path.resolve('source/dir/sub-dir-1')).and.returnValue([ + {name: 'file-2.txt', isDirectory: () => false}, + {name: 'sub-dir-2', isDirectory: () => true}, + ]) + .withArgs('-Al', path.resolve('source/dir/sub-dir-1/sub-dir-2')).and.returnValue([ + {name: 'file-3.txt', isDirectory: () => false}, + ]); + isPathIgnoredSpy.and.callFake(path => path.endsWith('sub-dir-1')); + + exampleBoilerPlate.copyDirectoryContents('source/dir', 'destination/dir', isPathIgnoredSpy); + + expect(callLog).toEqual([ + // Copy `file-1.txt`. + `test(-f, ${path.resolve('destination/dir/file-1.txt')})`, + `cp(${path.resolve('source/dir/file-1.txt')}, destination/dir)`, + `chmod(444, ${path.resolve('destination/dir/file-1.txt')})`, + + // Skip `sub-dir-1` and all its contents. + ]); + }); }); describe('loadJsonFile', () => { diff --git a/aio/tools/examples/shared/boilerplate/.gitignore b/aio/tools/examples/shared/boilerplate/.gitignore index ceed8f2aed2ab..908cc874638c1 100644 --- a/aio/tools/examples/shared/boilerplate/.gitignore +++ b/aio/tools/examples/shared/boilerplate/.gitignore @@ -1,2 +1,3 @@ +**/node_modules/ +**/package-lock.json **/yarn.lock -**/package-lock.json \ No newline at end of file diff --git a/aio/tools/examples/shared/boilerplate/UPDATING_CLI.md b/aio/tools/examples/shared/boilerplate/UPDATING_CLI.md deleted file mode 100644 index e905b4a3167c3..0000000000000 --- a/aio/tools/examples/shared/boilerplate/UPDATING_CLI.md +++ /dev/null @@ -1,50 +0,0 @@ -# How to update the CLI project - -The Angular CLI default setup is updated using `ng update`. Any necessary file changes will be done automatically through migration schematics. - -In the `cli` folder, update the Angular CLI depedencies to the latest version: - -``` -ng update @angular/cli --next -``` - -Then update the Angular Framework dependencies to the latest version: - -``` -ng update @angular/core --next -``` - -Commit any changes to the `cli` folder to the repository. - -## Updating other CLI-based projects - -Along with the boilerplate files for the `cli` folder, the other cli-based projects need to be updated also. Each cli-based project has slightly modified files specific to the project type. Make sure any necessary changes to these projects are made also to be in alignment with the `cli` project files. - -The specific changes to each project type are listed below: - -* i18n - - angular.json - - Includes additional configurations for `build`, `serve`, and `e2e` for different locales - - package.json - - Includes custom scripts for building and serving different locales -* ivy - - cli/tsconfig.app.json - - Includes an `angularCompilerOptions` object with `enableIvy` set to `true` -* schematics - - angular.json - - Includes a `my-lib` project that contains a library with example schematics -* service-worker - - angular.json - - Has `serviceWorker` set to `true` in the `production` build target - - package.json - - Includes `@angular/service-worker` in `dependencies` -* testing - - angular.json - - Includes `src/test.css` in the `styles` for the `test` target -* universal - - angular.json - - Includes a `server` target in the `build` architect runners - - package.json - - Includes custom scripts for building the `server` - - Includes additional `dependencies` on `@angular/platform-server`, `@nguniversal/express-engine`, and `express` - - Includes additional `devDependencies` on `@nguniversal/builders` and `@types/express` diff --git a/aio/tools/examples/shared/boilerplate/cli-ajs/package.json b/aio/tools/examples/shared/boilerplate/cli-ajs/package.json index d025bc756a285..5b4bb2eca221a 100644 --- a/aio/tools/examples/shared/boilerplate/cli-ajs/package.json +++ b/aio/tools/examples/shared/boilerplate/cli-ajs/package.json @@ -13,43 +13,42 @@ }, "private": true, "dependencies": { - "@angular/animations": "~9.1.4", - "@angular/common": "~9.1.4", - "@angular/compiler": "~9.1.4", - "@angular/core": "~9.1.4", - "@angular/forms": "~9.1.4", - "@angular/platform-browser": "~9.1.4", - "@angular/platform-browser-dynamic": "~9.1.4", - "@angular/router": "~9.1.4", - "angular": "1.7.9", + "@angular/animations": "~10.1.3", + "@angular/common": "~10.1.3", + "@angular/compiler": "~10.1.3", + "@angular/core": "~10.1.3", + "@angular/forms": "~10.1.3", + "@angular/platform-browser": "~10.1.3", + "@angular/platform-browser-dynamic": "~10.1.3", + "@angular/router": "~10.1.3", + "angular": "1.8.0", "angular-in-memory-web-api": "~0.11.0", - "angular-route": "1.7.9", - "rxjs": "~6.5.4", - "tslib": "^1.10.0", + "angular-route": "1.8.0", + "rxjs": "~6.6.0", + "tslib": "^2.0.0", "zone.js": "~0.10.3" }, "devDependencies": { - "@angular-devkit/build-angular": "~0.901.4", - "@angular/cli": "~9.1.4", - "@angular/compiler-cli": "~9.1.4", - "@angular/language-service": "~9.1.4", - "@types/angular": "^1.6.57", - "@types/angular-route": "^1.7.0", + "@angular-devkit/build-angular": "~0.1001.3", + "@angular/cli": "~10.1.3", + "@angular/compiler-cli": "~10.1.3", + "@types/angular": "1.7.3", + "@types/angular-route": "1.7.1", "@types/jasmine": "~3.5.0", "@types/jasminewd2": "~2.0.3", "@types/node": "^12.11.1", - "codelyzer": "^5.1.2", - "jasmine-core": "~3.5.0", + "codelyzer": "^6.0.0", + "jasmine-core": "~3.6.0", "jasmine-marbles": "~0.6.0", - "jasmine-spec-reporter": "~4.2.1", + "jasmine-spec-reporter": "~5.0.0", "karma": "~5.0.0", "karma-chrome-launcher": "~3.1.0", - "karma-coverage-istanbul-reporter": "~2.1.0", - "karma-jasmine": "~3.0.1", - "karma-jasmine-html-reporter": "^1.4.2", - "protractor": "~5.4.3", + "karma-coverage-istanbul-reporter": "~3.0.2", + "karma-jasmine": "~4.0.0", + "karma-jasmine-html-reporter": "^1.5.0", + "protractor": "~7.0.0", "ts-node": "~8.3.0", "tslint": "~6.1.0", - "typescript": "~3.8.3" + "typescript": "~4.0.3" } } diff --git a/aio/tools/examples/shared/boilerplate/cli/browserslist b/aio/tools/examples/shared/boilerplate/cli/.browserslistrc similarity index 52% rename from aio/tools/examples/shared/boilerplate/cli/browserslist rename to aio/tools/examples/shared/boilerplate/cli/.browserslistrc index b23d6dc5bd905..427441dc93085 100644 --- a/aio/tools/examples/shared/boilerplate/cli/browserslist +++ b/aio/tools/examples/shared/boilerplate/cli/.browserslistrc @@ -2,14 +2,16 @@ # For additional information regarding the format and rule options, please see: # https://github.com/browserslist/browserslist#queries +# For the full list of supported browsers by the Angular framework, please see: +# https://angular.io/guide/browser-support + # You can see what browsers were selected by your queries by running: # npx browserslist -# Googlebot uses an older version of Chrome -# For additional information see: https://developers.google.com/search/docs/guides/rendering - -> 0.5% -last 2 versions +last 1 Chrome version +last 1 Firefox version +last 2 Edge major versions +last 2 Safari major versions +last 2 iOS major versions Firefox ESR -not dead -not IE 9-11 # For IE 9-11 support, remove 'not'. \ No newline at end of file +not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. diff --git a/aio/tools/examples/shared/boilerplate/cli/angular.json b/aio/tools/examples/shared/boilerplate/cli/angular.json index 243a463309980..0aebc63a978b0 100644 --- a/aio/tools/examples/shared/boilerplate/cli/angular.json +++ b/aio/tools/examples/shared/boilerplate/cli/angular.json @@ -5,7 +5,11 @@ "projects": { "angular.io-example": { "projectType": "application", - "schematics": {}, + "schematics": { + "@schematics/angular:application": { + "strict": true + } + }, "root": "", "sourceRoot": "src", "prefix": "app", @@ -18,6 +22,7 @@ "main": "src/main.ts", "polyfills": "src/polyfills.ts", "tsConfig": "tsconfig.app.json", + "aot": true, "assets": [ "src/favicon.ico", "src/assets" @@ -40,20 +45,19 @@ "sourceMap": false, "extractCss": true, "namedChunks": false, - "aot": true, "extractLicenses": true, "vendorChunk": false, "buildOptimizer": true, "budgets": [ { "type": "initial", - "maximumWarning": "2mb", - "maximumError": "5mb" + "maximumWarning": "500kb", + "maximumError": "1mb" }, { "type": "anyComponentStyle", - "maximumWarning": "6kb", - "maximumError": "10kb" + "maximumWarning": "2kb", + "maximumError": "4kb" } ] } diff --git a/aio/tools/examples/shared/boilerplate/cli/e2e/protractor.conf.js b/aio/tools/examples/shared/boilerplate/cli/e2e/protractor.conf.js index ec47c8ae2e510..09a96840f2319 100644 --- a/aio/tools/examples/shared/boilerplate/cli/e2e/protractor.conf.js +++ b/aio/tools/examples/shared/boilerplate/cli/e2e/protractor.conf.js @@ -2,7 +2,7 @@ // Protractor configuration file, see link for more information // https://github.com/angular/protractor/blob/master/lib/config.ts -const { SpecReporter } = require('jasmine-spec-reporter'); +const { SpecReporter, StacktraceOption } = require('jasmine-spec-reporter'); /** * @type { import("protractor").Config } @@ -27,6 +27,10 @@ exports.config = { require('ts-node').register({ project: require('path').join(__dirname, './tsconfig.json') }); - jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); + jasmine.getEnv().addReporter(new SpecReporter({ + spec: { + displayStacktrace: StacktraceOption.PRETTY + } + })); } }; diff --git a/aio/tools/examples/shared/boilerplate/cli/e2e/tsconfig.json b/aio/tools/examples/shared/boilerplate/cli/e2e/tsconfig.json index 39b800f789619..426058ef0fbe7 100644 --- a/aio/tools/examples/shared/boilerplate/cli/e2e/tsconfig.json +++ b/aio/tools/examples/shared/boilerplate/cli/e2e/tsconfig.json @@ -1,9 +1,10 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ { "extends": "../tsconfig.json", "compilerOptions": { "outDir": "../out-tsc/e2e", "module": "commonjs", - "target": "es5", + "target": "es2018", "types": [ "jasmine", "jasminewd2", diff --git a/aio/tools/examples/shared/boilerplate/cli/package.json b/aio/tools/examples/shared/boilerplate/cli/package.json index fbdd7de6f88e1..5c157c87f64c4 100644 --- a/aio/tools/examples/shared/boilerplate/cli/package.json +++ b/aio/tools/examples/shared/boilerplate/cli/package.json @@ -13,39 +13,38 @@ }, "private": true, "dependencies": { - "@angular/animations": "~9.1.4", - "@angular/common": "~9.1.4", - "@angular/compiler": "~9.1.4", - "@angular/core": "~9.1.4", - "@angular/forms": "~9.1.4", - "@angular/platform-browser": "~9.1.4", - "@angular/platform-browser-dynamic": "~9.1.4", - "@angular/router": "~9.1.4", + "@angular/animations": "~10.1.3", + "@angular/common": "~10.1.3", + "@angular/compiler": "~10.1.3", + "@angular/core": "~10.1.3", + "@angular/forms": "~10.1.3", + "@angular/platform-browser": "~10.1.3", + "@angular/platform-browser-dynamic": "~10.1.3", + "@angular/router": "~10.1.3", "angular-in-memory-web-api": "~0.11.0", - "rxjs": "~6.5.4", - "tslib": "^1.10.0", + "rxjs": "~6.6.0", + "tslib": "^2.0.0", "zone.js": "~0.10.3" }, "devDependencies": { - "@angular-devkit/build-angular": "~0.901.4", - "@angular/cli": "~9.1.4", - "@angular/compiler-cli": "~9.1.4", - "@angular/language-service": "~9.1.4", + "@angular-devkit/build-angular": "~0.1001.3", + "@angular/cli": "~10.1.3", + "@angular/compiler-cli": "~10.1.3", "@types/jasmine": "~3.5.0", "@types/jasminewd2": "~2.0.3", "@types/node": "^12.11.1", - "codelyzer": "^5.1.2", - "jasmine-core": "~3.5.0", + "codelyzer": "^6.0.0", + "jasmine-core": "~3.6.0", "jasmine-marbles": "~0.6.0", - "jasmine-spec-reporter": "~4.2.1", + "jasmine-spec-reporter": "~5.0.0", "karma": "~5.0.0", "karma-chrome-launcher": "~3.1.0", - "karma-coverage-istanbul-reporter": "~2.1.0", - "karma-jasmine": "~3.0.1", - "karma-jasmine-html-reporter": "^1.4.2", - "protractor": "~5.4.3", + "karma-coverage-istanbul-reporter": "~3.0.2", + "karma-jasmine": "~4.0.0", + "karma-jasmine-html-reporter": "^1.5.0", + "protractor": "~7.0.0", "ts-node": "~8.3.0", "tslint": "~6.1.0", - "typescript": "~3.8.3" + "typescript": "~4.0.3" } } diff --git a/aio/tools/examples/shared/boilerplate/cli/src/app/package.json b/aio/tools/examples/shared/boilerplate/cli/src/app/package.json new file mode 100644 index 0000000000000..5d098bf337448 --- /dev/null +++ b/aio/tools/examples/shared/boilerplate/cli/src/app/package.json @@ -0,0 +1,9 @@ +{ + "name": "angular.io-example", + "private": true, + "description_1": "This is a special package.json file that is not used by package managers.", + "description_2": "It is used to tell the tools and bundlers whether the code under this directory is free of code with non-local side-effect. Any code that does have non-local side-effects can't be well optimized (tree-shaken) and will result in unnecessary increased payload size.", + "description_3": "It should be safe to set this option to 'false' for new applications, but existing code bases could be broken when built with the production config if the application code does contain non-local side-effects that the application depends on.", + "description_4": "To learn more about this file see: https://angular.io/config/app-package-json.", + "sideEffects": false +} diff --git a/aio/tools/examples/shared/boilerplate/cli/src/polyfills.ts b/aio/tools/examples/shared/boilerplate/cli/src/polyfills.ts index cd7cfe977d651..f38ef7d0e5994 100644 --- a/aio/tools/examples/shared/boilerplate/cli/src/polyfills.ts +++ b/aio/tools/examples/shared/boilerplate/cli/src/polyfills.ts @@ -18,7 +18,7 @@ * BROWSER POLYFILLS */ -/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +/** IE11 requires the following for NgClass support on SVG elements */ // import 'classlist.js'; // Run `npm install --save classlist.js`. /** diff --git a/aio/tools/examples/shared/boilerplate/cli/tsconfig.app.json b/aio/tools/examples/shared/boilerplate/cli/tsconfig.app.json index eb271da2d8063..cf23efe4272a5 100644 --- a/aio/tools/examples/shared/boilerplate/cli/tsconfig.app.json +++ b/aio/tools/examples/shared/boilerplate/cli/tsconfig.app.json @@ -1,3 +1,4 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ { "extends": "./tsconfig.json", "compilerOptions": { diff --git a/aio/tools/examples/shared/boilerplate/cli/tsconfig.json b/aio/tools/examples/shared/boilerplate/cli/tsconfig.json index 30956ae7ea265..b7d7a9ad985b6 100644 --- a/aio/tools/examples/shared/boilerplate/cli/tsconfig.json +++ b/aio/tools/examples/shared/boilerplate/cli/tsconfig.json @@ -1,26 +1,31 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ { "compileOnSave": false, "compilerOptions": { "baseUrl": "./", "outDir": "./dist/out-tsc", + "forceConsistentCasingInFileNames": true, + // TODO(gkalpak): Fix the code and enable this. + // "strict": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, "sourceMap": true, "declaration": false, "downlevelIteration": true, "experimentalDecorators": true, - "module": "esnext", "moduleResolution": "node", "importHelpers": true, "target": "es2015", - "typeRoots": [ - "node_modules/@types" - ], + "module": "es2020", "lib": [ "es2018", "dom" ] }, "angularCompilerOptions": { - "fullTemplateTypeCheck": true, - "strictInjectionParameters": true + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + // TODO(gkalpak): Fix the code and enable this (i.e. switch from `fullTemplateTypeCheck` to `strictTemplates`). + "fullTemplateTypeCheck": true,// "strictTemplates": true } } diff --git a/aio/tools/examples/shared/boilerplate/cli/tsconfig.spec.json b/aio/tools/examples/shared/boilerplate/cli/tsconfig.spec.json index 6400fde7d5440..092345b02e807 100644 --- a/aio/tools/examples/shared/boilerplate/cli/tsconfig.spec.json +++ b/aio/tools/examples/shared/boilerplate/cli/tsconfig.spec.json @@ -1,10 +1,10 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ { "extends": "./tsconfig.json", "compilerOptions": { "outDir": "./out-tsc/spec", "types": [ - "jasmine", - "node" + "jasmine" ] }, "files": [ diff --git a/aio/tools/examples/shared/boilerplate/cli/tslint.json b/aio/tools/examples/shared/boilerplate/cli/tslint.json index bf1abc0372d71..4cfd9cae6bebd 100644 --- a/aio/tools/examples/shared/boilerplate/cli/tslint.json +++ b/aio/tools/examples/shared/boilerplate/cli/tslint.json @@ -1,5 +1,8 @@ { "extends": "tslint:recommended", + "rulesDirectory": [ + "codelyzer" + ], "rules": { "align": { "options": [ @@ -13,22 +16,6 @@ "deprecation": { "severity": "warning" }, - "component-class-suffix": true, - "component-selector": [ - true, - "element", - // TODO: Fix the code and change the prefix to `"app"` (or whatever makes sense). - "", - "kebab-case" - ], - "contextual-lifecycle": true, - "directive-class-suffix": true, - "directive-selector": [ - true, - "attribute", - ["app", "toh"], - "camelCase" - ], "eofline": true, "import-blacklist": [ true, @@ -56,6 +43,8 @@ ] } ], + // TODO(gkalpak): Fix the code and enable this. + // "no-any": true, "no-console": [ true, "debug", @@ -95,6 +84,11 @@ "named": "never" } }, + // TODO(gkalpak): Fix the code and enable this. + // "typedef": [ + // true, + // "call-signature" + // ], "typedef-whitespace": { "options": [ { @@ -130,6 +124,9 @@ "check-typecast" ] }, + "component-class-suffix": true, + "contextual-lifecycle": true, + "directive-class-suffix": true, "no-conflicting-lifecycle": true, "no-host-metadata-property": true, "no-input-rename": true, @@ -141,9 +138,19 @@ "template-banana-in-box": true, "template-no-negated-async": true, "use-lifecycle-interface": true, - "use-pipe-transform-interface": true - }, - "rulesDirectory": [ - "codelyzer" - ] + "use-pipe-transform-interface": true, + "directive-selector": [ + true, + "attribute", + ["app", "toh"], + "camelCase" + ], + "component-selector": [ + true, + "element", + // TODO: Fix the code and change the prefix to `"app"` (or whatever makes sense). + "", + "kebab-case" + ] + } } diff --git a/aio/tools/examples/shared/boilerplate/elements/package.json b/aio/tools/examples/shared/boilerplate/elements/package.json index a0b396cf8a0fd..94dbbe498107e 100644 --- a/aio/tools/examples/shared/boilerplate/elements/package.json +++ b/aio/tools/examples/shared/boilerplate/elements/package.json @@ -13,41 +13,40 @@ }, "private": true, "dependencies": { - "@angular/animations": "~9.1.4", - "@angular/common": "~9.1.4", - "@angular/compiler": "~9.1.4", - "@angular/core": "~9.1.4", - "@angular/elements": "~9.1.4", - "@angular/forms": "~9.1.4", - "@angular/platform-browser": "~9.1.4", - "@angular/platform-browser-dynamic": "~9.1.4", - "@angular/router": "~9.1.4", - "@webcomponents/custom-elements": "^1.4.1", + "@angular/animations": "~10.1.3", + "@angular/common": "~10.1.3", + "@angular/compiler": "~10.1.3", + "@angular/core": "~10.1.3", + "@angular/elements": "~10.1.3", + "@angular/forms": "~10.1.3", + "@angular/platform-browser": "~10.1.3", + "@angular/platform-browser-dynamic": "~10.1.3", + "@angular/router": "~10.1.3", + "@webcomponents/custom-elements": "^1.4.2", "angular-in-memory-web-api": "~0.11.0", - "rxjs": "~6.5.4", - "tslib": "^1.10.0", + "rxjs": "~6.6.0", + "tslib": "^2.0.0", "zone.js": "~0.10.3" }, "devDependencies": { - "@angular-devkit/build-angular": "~0.901.4", - "@angular/cli": "~9.1.4", - "@angular/compiler-cli": "~9.1.4", - "@angular/language-service": "~9.1.4", + "@angular-devkit/build-angular": "~0.1001.3", + "@angular/cli": "~10.1.3", + "@angular/compiler-cli": "~10.1.3", "@types/jasmine": "~3.5.0", "@types/jasminewd2": "~2.0.3", "@types/node": "^12.11.1", - "codelyzer": "^5.1.2", - "jasmine-core": "~3.5.0", + "codelyzer": "^6.0.0", + "jasmine-core": "~3.6.0", "jasmine-marbles": "~0.6.0", - "jasmine-spec-reporter": "~4.2.1", + "jasmine-spec-reporter": "~5.0.0", "karma": "~5.0.0", "karma-chrome-launcher": "~3.1.0", - "karma-coverage-istanbul-reporter": "~2.1.0", - "karma-jasmine": "~3.0.1", - "karma-jasmine-html-reporter": "^1.4.2", - "protractor": "~5.4.3", + "karma-coverage-istanbul-reporter": "~3.0.2", + "karma-jasmine": "~4.0.0", + "karma-jasmine-html-reporter": "^1.5.0", + "protractor": "~7.0.0", "ts-node": "~8.3.0", "tslint": "~6.1.0", - "typescript": "~3.8.3" + "typescript": "~4.0.3" } } diff --git a/aio/tools/examples/shared/boilerplate/elements/src/polyfills.ts b/aio/tools/examples/shared/boilerplate/elements/src/polyfills.ts index 031fc3d0c083a..08b4d9cd60651 100644 --- a/aio/tools/examples/shared/boilerplate/elements/src/polyfills.ts +++ b/aio/tools/examples/shared/boilerplate/elements/src/polyfills.ts @@ -18,7 +18,7 @@ * BROWSER POLYFILLS */ -/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +/** IE11 requires the following for NgClass support on SVG elements */ // import 'classlist.js'; // Run `npm install --save classlist.js`. /** diff --git a/aio/tools/examples/shared/boilerplate/i18n/angular.json b/aio/tools/examples/shared/boilerplate/i18n/angular.json index 8934ab45e6b77..63e865b85c87b 100644 --- a/aio/tools/examples/shared/boilerplate/i18n/angular.json +++ b/aio/tools/examples/shared/boilerplate/i18n/angular.json @@ -5,7 +5,11 @@ "projects": { "angular.io-example": { "projectType": "application", - "schematics": {}, + "schematics": { + "@schematics/angular:application": { + "strict": true + } + }, "root": "", "sourceRoot": "src", "prefix": "app", @@ -20,12 +24,12 @@ "builder": "@angular-devkit/build-angular:browser", "options": { "localize": true, - "aot": true, "outputPath": "dist", "index": "src/index.html", "main": "src/main.ts", "polyfills": "src/polyfills.ts", "tsConfig": "tsconfig.app.json", + "aot": true, "assets": [ "src/favicon.ico", "src/assets" @@ -48,20 +52,19 @@ "sourceMap": false, "extractCss": true, "namedChunks": false, - "aot": true, "extractLicenses": true, "vendorChunk": false, "buildOptimizer": true, "budgets": [ { "type": "initial", - "maximumWarning": "2mb", - "maximumError": "5mb" + "maximumWarning": "500kb", + "maximumError": "1mb" }, { "type": "anyComponentStyle", - "maximumWarning": "6kb", - "maximumError": "10kb" + "maximumWarning": "2kb", + "maximumError": "4kb" } ] }, diff --git a/aio/tools/examples/shared/boilerplate/i18n/package.json b/aio/tools/examples/shared/boilerplate/i18n/package.json index d0944e64c4b37..e1e511f0add4b 100644 --- a/aio/tools/examples/shared/boilerplate/i18n/package.json +++ b/aio/tools/examples/shared/boilerplate/i18n/package.json @@ -16,40 +16,39 @@ }, "private": true, "dependencies": { - "@angular/animations": "~9.1.4", - "@angular/common": "~9.1.4", - "@angular/compiler": "~9.1.4", - "@angular/core": "~9.1.4", - "@angular/forms": "~9.1.4", - "@angular/localize": "^9.1.4", - "@angular/platform-browser": "~9.1.4", - "@angular/platform-browser-dynamic": "~9.1.4", - "@angular/router": "~9.1.4", + "@angular/animations": "~10.1.3", + "@angular/common": "~10.1.3", + "@angular/compiler": "~10.1.3", + "@angular/core": "~10.1.3", + "@angular/forms": "~10.1.3", + "@angular/localize": "~10.1.3", + "@angular/platform-browser": "~10.1.3", + "@angular/platform-browser-dynamic": "~10.1.3", + "@angular/router": "~10.1.3", "angular-in-memory-web-api": "~0.11.0", - "rxjs": "~6.5.4", - "tslib": "^1.10.0", + "rxjs": "~6.6.0", + "tslib": "^2.0.0", "zone.js": "~0.10.3" }, "devDependencies": { - "@angular-devkit/build-angular": "~0.901.4", - "@angular/cli": "~9.1.4", - "@angular/compiler-cli": "~9.1.4", - "@angular/language-service": "~9.1.4", + "@angular-devkit/build-angular": "~0.1001.3", + "@angular/cli": "~10.1.3", + "@angular/compiler-cli": "~10.1.3", "@types/jasmine": "~3.5.0", "@types/jasminewd2": "~2.0.3", "@types/node": "^12.11.1", - "codelyzer": "^5.1.2", - "jasmine-core": "~3.5.0", + "codelyzer": "^6.0.0", + "jasmine-core": "~3.6.0", "jasmine-marbles": "~0.6.0", - "jasmine-spec-reporter": "~4.2.1", + "jasmine-spec-reporter": "~5.0.0", "karma": "~5.0.0", "karma-chrome-launcher": "~3.1.0", - "karma-coverage-istanbul-reporter": "~2.1.0", - "karma-jasmine": "~3.0.1", - "karma-jasmine-html-reporter": "^1.4.2", - "protractor": "~5.4.3", + "karma-coverage-istanbul-reporter": "~3.0.2", + "karma-jasmine": "~4.0.0", + "karma-jasmine-html-reporter": "^1.5.0", + "protractor": "~7.0.0", "ts-node": "~8.3.0", "tslint": "~6.1.0", - "typescript": "~3.8.3" + "typescript": "~4.0.3" } } diff --git a/aio/tools/examples/shared/boilerplate/i18n/src/polyfills.ts b/aio/tools/examples/shared/boilerplate/i18n/src/polyfills.ts index d06dbf69c5428..3424b9d3f41be 100644 --- a/aio/tools/examples/shared/boilerplate/i18n/src/polyfills.ts +++ b/aio/tools/examples/shared/boilerplate/i18n/src/polyfills.ts @@ -22,7 +22,7 @@ import '@angular/localize/init'; * BROWSER POLYFILLS */ -/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +/** IE11 requires the following for NgClass support on SVG elements */ // import 'classlist.js'; // Run `npm install --save classlist.js`. /** diff --git a/aio/tools/examples/shared/boilerplate/schematics/angular.json b/aio/tools/examples/shared/boilerplate/schematics/angular.json index 368c748ff0ade..bfdd1d0c857d9 100644 --- a/aio/tools/examples/shared/boilerplate/schematics/angular.json +++ b/aio/tools/examples/shared/boilerplate/schematics/angular.json @@ -5,7 +5,11 @@ "projects": { "angular.io-example": { "projectType": "application", - "schematics": {}, + "schematics": { + "@schematics/angular:application": { + "strict": true + } + }, "root": "", "sourceRoot": "src", "prefix": "app", @@ -18,6 +22,7 @@ "main": "src/main.ts", "polyfills": "src/polyfills.ts", "tsConfig": "tsconfig.app.json", + "aot": true, "assets": [ "src/favicon.ico", "src/assets" @@ -40,20 +45,19 @@ "sourceMap": false, "extractCss": true, "namedChunks": false, - "aot": true, "extractLicenses": true, "vendorChunk": false, "buildOptimizer": true, "budgets": [ { "type": "initial", - "maximumWarning": "2mb", - "maximumError": "5mb" + "maximumWarning": "500kb", + "maximumError": "1mb" }, { "type": "anyComponentStyle", - "maximumWarning": "6kb", - "maximumError": "10kb" + "maximumWarning": "2kb", + "maximumError": "4kb" } ] } diff --git a/aio/tools/examples/shared/boilerplate/service-worker/angular.json b/aio/tools/examples/shared/boilerplate/service-worker/angular.json index e9d884e0bfcb9..75f201a3941e8 100644 --- a/aio/tools/examples/shared/boilerplate/service-worker/angular.json +++ b/aio/tools/examples/shared/boilerplate/service-worker/angular.json @@ -5,7 +5,11 @@ "projects": { "angular.io-example": { "projectType": "application", - "schematics": {}, + "schematics": { + "@schematics/angular:application": { + "strict": true + } + }, "root": "", "sourceRoot": "src", "prefix": "app", @@ -18,6 +22,7 @@ "main": "src/main.ts", "polyfills": "src/polyfills.ts", "tsConfig": "tsconfig.app.json", + "aot": true, "assets": [ "src/favicon.ico", "src/assets" @@ -40,7 +45,6 @@ "sourceMap": false, "extractCss": true, "namedChunks": false, - "aot": true, "extractLicenses": true, "vendorChunk": false, "buildOptimizer": true, @@ -48,13 +52,13 @@ "budgets": [ { "type": "initial", - "maximumWarning": "2mb", - "maximumError": "5mb" + "maximumWarning": "500kb", + "maximumError": "1mb" }, { "type": "anyComponentStyle", - "maximumWarning": "6kb", - "maximumError": "10kb" + "maximumWarning": "2kb", + "maximumError": "4kb" } ] } diff --git a/aio/tools/examples/shared/boilerplate/service-worker/package.json b/aio/tools/examples/shared/boilerplate/service-worker/package.json index 9c30e90cea4d0..9dae5937ea8b0 100644 --- a/aio/tools/examples/shared/boilerplate/service-worker/package.json +++ b/aio/tools/examples/shared/boilerplate/service-worker/package.json @@ -13,40 +13,39 @@ }, "private": true, "dependencies": { - "@angular/animations": "~9.1.4", - "@angular/common": "~9.1.4", - "@angular/compiler": "~9.1.4", - "@angular/core": "~9.1.4", - "@angular/forms": "~9.1.4", - "@angular/platform-browser": "~9.1.4", - "@angular/platform-browser-dynamic": "~9.1.4", - "@angular/router": "~9.1.4", - "@angular/service-worker": "~9.1.4", + "@angular/animations": "~10.1.3", + "@angular/common": "~10.1.3", + "@angular/compiler": "~10.1.3", + "@angular/core": "~10.1.3", + "@angular/forms": "~10.1.3", + "@angular/platform-browser": "~10.1.3", + "@angular/platform-browser-dynamic": "~10.1.3", + "@angular/router": "~10.1.3", + "@angular/service-worker": "~10.1.3", "angular-in-memory-web-api": "~0.11.0", - "rxjs": "~6.5.4", - "tslib": "^1.10.0", + "rxjs": "~6.6.0", + "tslib": "^2.0.0", "zone.js": "~0.10.3" }, "devDependencies": { - "@angular-devkit/build-angular": "~0.901.4", - "@angular/cli": "~9.1.4", - "@angular/compiler-cli": "~9.1.4", - "@angular/language-service": "~9.1.4", + "@angular-devkit/build-angular": "~0.1001.3", + "@angular/cli": "~10.1.3", + "@angular/compiler-cli": "~10.1.3", "@types/jasmine": "~3.5.0", "@types/jasminewd2": "~2.0.3", "@types/node": "^12.11.1", - "codelyzer": "^5.1.2", - "jasmine-core": "~3.5.0", + "codelyzer": "^6.0.0", + "jasmine-core": "~3.6.0", "jasmine-marbles": "~0.6.0", - "jasmine-spec-reporter": "~4.2.1", + "jasmine-spec-reporter": "~5.0.0", "karma": "~5.0.0", "karma-chrome-launcher": "~3.1.0", - "karma-coverage-istanbul-reporter": "~2.1.0", - "karma-jasmine": "~3.0.1", - "karma-jasmine-html-reporter": "^1.4.2", - "protractor": "~5.4.3", + "karma-coverage-istanbul-reporter": "~3.0.2", + "karma-jasmine": "~4.0.0", + "karma-jasmine-html-reporter": "^1.5.0", + "protractor": "~7.0.0", "ts-node": "~8.3.0", "tslint": "~6.1.0", - "typescript": "~3.8.3" + "typescript": "~4.0.3" } } diff --git a/aio/tools/examples/shared/boilerplate/systemjs/package.json b/aio/tools/examples/shared/boilerplate/systemjs/package.json index 1a609f6626505..909e3d57567b1 100644 --- a/aio/tools/examples/shared/boilerplate/systemjs/package.json +++ b/aio/tools/examples/shared/boilerplate/systemjs/package.json @@ -27,45 +27,44 @@ }, "private": true, "dependencies": { - "@angular/animations": "~9.1.4", - "@angular/common": "~9.1.4", - "@angular/compiler": "~9.1.4", - "@angular/core": "~9.1.4", - "@angular/forms": "~9.1.4", - "@angular/platform-browser": "~9.1.4", - "@angular/platform-browser-dynamic": "~9.1.4", - "@angular/router": "~9.1.4", - "@angular/upgrade": "~9.1.4", + "@angular/animations": "~10.1.3", + "@angular/common": "~10.1.3", + "@angular/compiler": "~10.1.3", + "@angular/core": "~10.1.3", + "@angular/forms": "~10.1.3", + "@angular/platform-browser": "~10.1.3", + "@angular/platform-browser-dynamic": "~10.1.3", + "@angular/router": "~10.1.3", + "@angular/upgrade": "~10.1.3", "core-js": "^2.5.4", - "rxjs": "~6.5.4", - "tslib": "^1.10.0", + "rxjs": "~6.6.0", + "tslib": "^2.0.0", "zone.js": "~0.10.3" }, "devDependencies": { - "@angular/compiler-cli": "~9.1.4", - "@angular/language-service": "~9.1.4", - "@types/angular": "1.6.47", + "@angular/compiler-cli": "~10.1.3", + "@types/angular": "1.7.3", "@types/angular-animate": "1.5.10", - "@types/angular-mocks": "1.6.0", - "@types/angular-resource": "1.5.14", - "@types/angular-route": "1.3.5", + "@types/angular-mocks": "1.7.0", + "@types/angular-resource": "1.5.16", + "@types/angular-route": "1.7.1", "@types/jasmine": "~3.5.0", "@types/jasminewd2": "~2.0.3", "@types/node": "^12.11.1", "concurrently": "^5.0.1", "http-server": "^0.12.0", - "jasmine-core": "~3.5.0", - "karma": "~4.3.0", + "jasmine-core": "~3.6.0", + "karma": "~5.0.0", "karma-chrome-launcher": "~3.1.0", - "karma-jasmine": "~2.0.1", - "karma-jasmine-html-reporter": "^1.4.2", + "karma-jasmine": "~4.0.0", + "karma-jasmine-html-reporter": "^1.5.0", "lite-server": "^2.2.2", - "protractor": "~5.4.3", + "protractor": "~7.0.0", "rollup": "^1.1.0", "rollup-plugin-commonjs": "^9.2.1", "rollup-plugin-node-resolve": "^4.0.0", "rollup-plugin-terser": "^5.3.0", - "tslint": "~5.18.0", - "typescript": "~3.7.5" + "tslint": "~6.1.0", + "typescript": "~4.0.3" } } diff --git a/aio/tools/examples/shared/boilerplate/systemjs/tslint.json b/aio/tools/examples/shared/boilerplate/systemjs/tslint.json index bf1abc0372d71..4cfd9cae6bebd 100644 --- a/aio/tools/examples/shared/boilerplate/systemjs/tslint.json +++ b/aio/tools/examples/shared/boilerplate/systemjs/tslint.json @@ -1,5 +1,8 @@ { "extends": "tslint:recommended", + "rulesDirectory": [ + "codelyzer" + ], "rules": { "align": { "options": [ @@ -13,22 +16,6 @@ "deprecation": { "severity": "warning" }, - "component-class-suffix": true, - "component-selector": [ - true, - "element", - // TODO: Fix the code and change the prefix to `"app"` (or whatever makes sense). - "", - "kebab-case" - ], - "contextual-lifecycle": true, - "directive-class-suffix": true, - "directive-selector": [ - true, - "attribute", - ["app", "toh"], - "camelCase" - ], "eofline": true, "import-blacklist": [ true, @@ -56,6 +43,8 @@ ] } ], + // TODO(gkalpak): Fix the code and enable this. + // "no-any": true, "no-console": [ true, "debug", @@ -95,6 +84,11 @@ "named": "never" } }, + // TODO(gkalpak): Fix the code and enable this. + // "typedef": [ + // true, + // "call-signature" + // ], "typedef-whitespace": { "options": [ { @@ -130,6 +124,9 @@ "check-typecast" ] }, + "component-class-suffix": true, + "contextual-lifecycle": true, + "directive-class-suffix": true, "no-conflicting-lifecycle": true, "no-host-metadata-property": true, "no-input-rename": true, @@ -141,9 +138,19 @@ "template-banana-in-box": true, "template-no-negated-async": true, "use-lifecycle-interface": true, - "use-pipe-transform-interface": true - }, - "rulesDirectory": [ - "codelyzer" - ] + "use-pipe-transform-interface": true, + "directive-selector": [ + true, + "attribute", + ["app", "toh"], + "camelCase" + ], + "component-selector": [ + true, + "element", + // TODO: Fix the code and change the prefix to `"app"` (or whatever makes sense). + "", + "kebab-case" + ] + } } diff --git a/aio/tools/examples/shared/boilerplate/testing/angular.json b/aio/tools/examples/shared/boilerplate/testing/angular.json index 6c1cb0b102500..3226b2e5155f2 100644 --- a/aio/tools/examples/shared/boilerplate/testing/angular.json +++ b/aio/tools/examples/shared/boilerplate/testing/angular.json @@ -5,7 +5,11 @@ "projects": { "angular.io-example": { "projectType": "application", - "schematics": {}, + "schematics": { + "@schematics/angular:application": { + "strict": true + } + }, "root": "", "sourceRoot": "src", "prefix": "app", @@ -18,6 +22,7 @@ "main": "src/main.ts", "polyfills": "src/polyfills.ts", "tsConfig": "tsconfig.app.json", + "aot": true, "assets": [ "src/favicon.ico", "src/assets" @@ -41,20 +46,19 @@ "sourceMap": false, "extractCss": true, "namedChunks": false, - "aot": true, "extractLicenses": true, "vendorChunk": false, "buildOptimizer": true, "budgets": [ { "type": "initial", - "maximumWarning": "2mb", - "maximumError": "5mb" + "maximumWarning": "500kb", + "maximumError": "1mb" }, { "type": "anyComponentStyle", - "maximumWarning": "6kb", - "maximumError": "10kb" + "maximumWarning": "2kb", + "maximumError": "4kb" } ] } diff --git a/aio/tools/examples/shared/boilerplate/testing/tsconfig.app.json b/aio/tools/examples/shared/boilerplate/testing/tsconfig.app.json index fdc41f9303fc6..dd00a4b966d76 100644 --- a/aio/tools/examples/shared/boilerplate/testing/tsconfig.app.json +++ b/aio/tools/examples/shared/boilerplate/testing/tsconfig.app.json @@ -1,3 +1,4 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ { "extends": "./tsconfig.json", "compilerOptions": { diff --git a/aio/tools/examples/shared/boilerplate/testing/tsconfig.spec.json b/aio/tools/examples/shared/boilerplate/testing/tsconfig.spec.json index 0e279f52310df..04c116ecd68b7 100644 --- a/aio/tools/examples/shared/boilerplate/testing/tsconfig.spec.json +++ b/aio/tools/examples/shared/boilerplate/testing/tsconfig.spec.json @@ -1,10 +1,10 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ { "extends": "./tsconfig.json", "compilerOptions": { "outDir": "./out-tsc/spec", "types": [ - "jasmine", - "node" + "jasmine" ] }, "files": [ diff --git a/aio/tools/examples/shared/boilerplate/universal/angular.json b/aio/tools/examples/shared/boilerplate/universal/angular.json index 1816501f6cf62..f763842ea5da4 100644 --- a/aio/tools/examples/shared/boilerplate/universal/angular.json +++ b/aio/tools/examples/shared/boilerplate/universal/angular.json @@ -5,7 +5,11 @@ "projects": { "angular.io-example": { "projectType": "application", - "schematics": {}, + "schematics": { + "@schematics/angular:application": { + "strict": true + } + }, "root": "", "sourceRoot": "src", "prefix": "app", @@ -18,6 +22,7 @@ "main": "src/main.ts", "polyfills": "src/polyfills.ts", "tsConfig": "tsconfig.app.json", + "aot": true, "assets": [ "src/favicon.ico", "src/assets" @@ -40,20 +45,19 @@ "sourceMap": false, "extractCss": true, "namedChunks": false, - "aot": true, "extractLicenses": true, "vendorChunk": false, "buildOptimizer": true, "budgets": [ { "type": "initial", - "maximumWarning": "2mb", - "maximumError": "5mb" + "maximumWarning": "500kb", + "maximumError": "1mb" }, { "type": "anyComponentStyle", - "maximumWarning": "6kb", - "maximumError": "10kb" + "maximumWarning": "2kb", + "maximumError": "4kb" } ] } diff --git a/aio/tools/examples/shared/boilerplate/universal/package.json b/aio/tools/examples/shared/boilerplate/universal/package.json index 9b503635f9998..f1d1348fb9518 100644 --- a/aio/tools/examples/shared/boilerplate/universal/package.json +++ b/aio/tools/examples/shared/boilerplate/universal/package.json @@ -17,44 +17,43 @@ }, "private": true, "dependencies": { - "@angular/animations": "~9.1.4", - "@angular/common": "~9.1.4", - "@angular/compiler": "~9.1.4", - "@angular/core": "~9.1.4", - "@angular/forms": "~9.1.4", - "@angular/platform-browser": "~9.1.4", - "@angular/platform-browser-dynamic": "~9.1.4", - "@angular/platform-server": "~9.1.4", - "@angular/router": "~9.1.4", - "@nguniversal/express-engine": "~9.0.1", + "@angular/animations": "~10.1.3", + "@angular/common": "~10.1.3", + "@angular/compiler": "~10.1.3", + "@angular/core": "~10.1.3", + "@angular/forms": "~10.1.3", + "@angular/platform-browser": "~10.1.3", + "@angular/platform-browser-dynamic": "~10.1.3", + "@angular/platform-server": "~10.1.3", + "@angular/router": "~10.1.3", + "@nguniversal/express-engine": "~10.1.0", "angular-in-memory-web-api": "~0.11.0", "express": "^4.15.2", - "rxjs": "~6.5.4", - "tslib": "^1.10.0", + "rxjs": "~6.6.0", + "tslib": "^2.0.0", "zone.js": "~0.10.3" }, "devDependencies": { - "@angular-devkit/build-angular": "~0.901.4", - "@angular/cli": "~9.1.4", - "@angular/compiler-cli": "~9.1.4", - "@angular/language-service": "~9.1.4", - "@nguniversal/builders": "^9.0.2", - "@types/express": "^4.17.0", + "@angular-devkit/build-angular": "~0.1001.3", + "@angular/cli": "~10.1.3", + "@angular/compiler-cli": "~10.1.3", + "@nguniversal/builders": "~10.1.0", + "@types/express": "^4.17.8", "@types/jasmine": "~3.5.0", "@types/jasminewd2": "~2.0.3", "@types/node": "^12.11.1", - "codelyzer": "^5.1.2", - "jasmine-core": "~3.5.0", + "codelyzer": "^6.0.0", + "jasmine-core": "~3.6.0", "jasmine-marbles": "~0.6.0", - "jasmine-spec-reporter": "~4.2.1", + "jasmine-spec-reporter": "~5.0.0", "karma": "~5.0.0", "karma-chrome-launcher": "~3.1.0", - "karma-coverage-istanbul-reporter": "~2.1.0", - "karma-jasmine": "~3.0.1", - "karma-jasmine-html-reporter": "^1.4.2", - "protractor": "~5.4.3", + "karma-coverage-istanbul-reporter": "~3.0.2", + "karma-jasmine": "~4.0.0", + "karma-jasmine-html-reporter": "^1.5.0", + "protractor": "~7.0.0", "ts-node": "~8.3.0", "tslint": "~6.1.0", - "typescript": "~3.8.3" + "typescript": "~4.0.3" } } diff --git a/aio/tools/examples/shared/boilerplate/viewengine/cli/tsconfig.json b/aio/tools/examples/shared/boilerplate/viewengine/cli/tsconfig.json index e4816a58e77b2..2394d7fc83811 100644 --- a/aio/tools/examples/shared/boilerplate/viewengine/cli/tsconfig.json +++ b/aio/tools/examples/shared/boilerplate/viewengine/cli/tsconfig.json @@ -1,19 +1,22 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ { "compileOnSave": false, "compilerOptions": { "baseUrl": "./", "outDir": "./dist/out-tsc", + "forceConsistentCasingInFileNames": true, + // TODO(gkalpak): Fix the code and enable this. + // "strict": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, "sourceMap": true, "declaration": false, "downlevelIteration": true, "experimentalDecorators": true, - "module": "esnext", "moduleResolution": "node", "importHelpers": true, "target": "es2015", - "typeRoots": [ - "node_modules/@types" - ], + "module": "es2020", "lib": [ "es2018", "dom" @@ -21,7 +24,9 @@ }, "angularCompilerOptions": { "enableIvy": false, - "fullTemplateTypeCheck": true, - "strictInjectionParameters": true + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + // TODO(gkalpak): Fix the code and enable this (i.e. switch from `fullTemplateTypeCheck` to `strictTemplates`). + "fullTemplateTypeCheck": true,// "strictTemplates": true } } diff --git a/aio/tools/examples/shared/boilerplate/viewengine/systemjs/tsconfig-aot.json b/aio/tools/examples/shared/boilerplate/viewengine/systemjs/tsconfig-aot.json index 068667697026a..b56690d6bb687 100644 --- a/aio/tools/examples/shared/boilerplate/viewengine/systemjs/tsconfig-aot.json +++ b/aio/tools/examples/shared/boilerplate/viewengine/systemjs/tsconfig-aot.json @@ -1,7 +1,7 @@ { "compilerOptions": { "target": "es5", - "module": "es2015", + "module": "es2020", "moduleResolution": "node", "sourceMap": true, "emitDecoratorMetadata": true, diff --git a/aio/tools/examples/shared/example-scaffold/e2e/src/app.e2e-spec.ts b/aio/tools/examples/shared/example-scaffold/e2e/src/app.e2e-spec.ts new file mode 100644 index 0000000000000..bd99243f89232 --- /dev/null +++ b/aio/tools/examples/shared/example-scaffold/e2e/src/app.e2e-spec.ts @@ -0,0 +1,20 @@ +import { AppPage } from './app.po'; +import { browser, logging } from 'protractor'; + +describe('workspace-project App', () => { + let page: AppPage; + + beforeEach(() => { + page = new AppPage(); + }); + + // Add your e2e tests here + + afterEach(async () => { + // Assert that there are no errors emitted from the browser + const logs = await browser.manage().logs().get(logging.Type.BROWSER); + expect(logs).not.toContain(jasmine.objectContaining({ + level: logging.Level.SEVERE, + } as logging.Entry)); + }); +}); diff --git a/aio/tools/examples/shared/example-scaffold/src/app/app.component.css b/aio/tools/examples/shared/example-scaffold/src/app/app.component.css new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/aio/tools/examples/shared/example-scaffold/src/app/app.component.html b/aio/tools/examples/shared/example-scaffold/src/app/app.component.html new file mode 100644 index 0000000000000..60dbe3a500a19 --- /dev/null +++ b/aio/tools/examples/shared/example-scaffold/src/app/app.component.html @@ -0,0 +1 @@ +

      Replace the src folder in this {{title}} with yours.

      \ No newline at end of file diff --git a/aio/tools/examples/shared/example-scaffold/src/app/app.component.spec.ts b/aio/tools/examples/shared/example-scaffold/src/app/app.component.spec.ts new file mode 100644 index 0000000000000..0509746ff0487 --- /dev/null +++ b/aio/tools/examples/shared/example-scaffold/src/app/app.component.spec.ts @@ -0,0 +1,20 @@ +import { TestBed } from '@angular/core/testing'; +import { AppComponent } from './app.component'; + +describe('AppComponent', () => { + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + AppComponent + ], + }).compileComponents(); + }); + + it('should create the app', () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.componentInstance; + expect(app).toBeTruthy(); + }); + + // Add your unit tests here +}); diff --git a/aio/tools/examples/shared/example-scaffold/src/app/app.component.ts b/aio/tools/examples/shared/example-scaffold/src/app/app.component.ts new file mode 100644 index 0000000000000..ea1aba85a9565 --- /dev/null +++ b/aio/tools/examples/shared/example-scaffold/src/app/app.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.css'], +}) +export class AppComponent { + title = 'example'; +} diff --git a/aio/tools/examples/shared/example-scaffold/src/app/app.module.ts b/aio/tools/examples/shared/example-scaffold/src/app/app.module.ts new file mode 100644 index 0000000000000..f65716351aa59 --- /dev/null +++ b/aio/tools/examples/shared/example-scaffold/src/app/app.module.ts @@ -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 { } diff --git a/aio/tools/examples/shared/example-scaffold/src/index.html b/aio/tools/examples/shared/example-scaffold/src/index.html new file mode 100644 index 0000000000000..3e64774523c01 --- /dev/null +++ b/aio/tools/examples/shared/example-scaffold/src/index.html @@ -0,0 +1,13 @@ + + + + + Ponyracer + + + + + + + + diff --git a/aio/tools/examples/shared/example-scaffold/src/main.ts b/aio/tools/examples/shared/example-scaffold/src/main.ts new file mode 100644 index 0000000000000..c7b673cf44b38 --- /dev/null +++ b/aio/tools/examples/shared/example-scaffold/src/main.ts @@ -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)); diff --git a/aio/tools/examples/shared/package.json b/aio/tools/examples/shared/package.json index 4c64be04aa6b2..b998750eb9ae7 100644 --- a/aio/tools/examples/shared/package.json +++ b/aio/tools/examples/shared/package.json @@ -8,7 +8,8 @@ "protractor": "protractor", "webdriver:update": "node ../../../../scripts/webdriver-manager-update.js", "preinstall": "node ../../../../tools/yarn/check-yarn.js", - "postinstall": "yarn webdriver:update" + "postinstall": "yarn webdriver:update", + "sync-deps": "node sync-boilerplate-dependencies" }, "//engines-comment": "Keep this in sync with /package.json and /aio/package.json", "engines": { @@ -20,63 +21,62 @@ "license": "MIT", "repository": {}, "dependencies": { - "@angular/animations": "~9.1.4", - "@angular/common": "~9.1.4", - "@angular/compiler": "~9.1.4", - "@angular/core": "~9.1.4", - "@angular/elements": "~9.1.4", - "@angular/forms": "~9.1.4", - "@angular/localize": "~9.1.4", - "@angular/platform-browser": "~9.1.4", - "@angular/platform-browser-dynamic": "~9.1.4", - "@angular/platform-server": "~9.1.4", - "@angular/router": "~9.1.4", - "@angular/service-worker": "~9.1.4", - "@angular/upgrade": "~9.1.4", - "@nguniversal/express-engine": "~9.0.1", - "@webcomponents/custom-elements": "^1.4.1", - "angular": "1.7.9", + "@angular/animations": "~10.1.3", + "@angular/common": "~10.1.3", + "@angular/compiler": "~10.1.3", + "@angular/core": "~10.1.3", + "@angular/elements": "~10.1.3", + "@angular/forms": "~10.1.3", + "@angular/localize": "~10.1.3", + "@angular/platform-browser": "~10.1.3", + "@angular/platform-browser-dynamic": "~10.1.3", + "@angular/platform-server": "~10.1.3", + "@angular/router": "~10.1.3", + "@angular/service-worker": "~10.1.3", + "@angular/upgrade": "~10.1.3", + "@nguniversal/express-engine": "~10.1.0", + "@webcomponents/custom-elements": "^1.4.2", + "angular": "1.8.0", "angular-in-memory-web-api": "~0.11.0", - "angular-route": "1.7.9", + "angular-route": "1.8.0", "core-js": "^2.5.4", "express": "^4.15.2", - "rxjs": "~6.5.4", + "rxjs": "~6.6.0", "systemjs": "0.19.39", - "tslib": "^1.10.0", + "tslib": "^2.0.0", "zone.js": "~0.10.3" }, "devDependencies": { - "@angular-devkit/build-angular": "~0.901.4", - "@angular/cli": "~9.1.4", - "@angular/compiler-cli": "~9.1.4", - "@angular/language-service": "~9.1.4", - "@nguniversal/builders": "^9.0.2", - "@types/angular": "1.6.47", + "@angular-devkit/build-angular": "~0.1001.3", + "@angular/cli": "~10.1.3", + "@angular/compiler-cli": "~10.1.3", + "@nguniversal/builders": "~10.1.0", + "@types/angular": "1.7.3", "@types/angular-animate": "1.5.10", - "@types/angular-mocks": "1.6.0", - "@types/angular-resource": "1.5.14", - "@types/angular-route": "1.3.5", - "@types/express": "^4.17.0", + "@types/angular-mocks": "1.7.0", + "@types/angular-resource": "1.5.16", + "@types/angular-route": "1.7.1", + "@types/express": "^4.17.8", "@types/jasmine": "~3.5.0", "@types/jasminewd2": "~2.0.3", - "@types/jquery": "3.3.28", + "@types/jquery": "3.5.1", "@types/node": "^12.11.1", "canonical-path": "1.0.0", - "codelyzer": "^5.1.2", + "codelyzer": "^6.0.0", "concurrently": "^5.0.1", "http-server": "^0.12.0", - "jasmine-core": "~3.5.0", + "jasmine-core": "~3.6.0", "jasmine-marbles": "~0.6.0", - "jasmine-spec-reporter": "~4.2.1", + "jasmine-spec-reporter": "~5.0.0", "karma": "~5.0.0", "karma-chrome-launcher": "~3.1.0", - "karma-coverage-istanbul-reporter": "~2.1.0", - "karma-jasmine": "~3.0.1", - "karma-jasmine-html-reporter": "^1.4.2", + "karma-coverage-istanbul-reporter": "~3.0.2", + "karma-jasmine": "~4.0.0", + "karma-jasmine-html-reporter": "^1.5.0", "lite-server": "^2.2.2", "lodash": "^4.16.2", - "protractor": "~5.4.3", - "puppeteer": "3.3.0", + "protractor": "~7.0.0", + "puppeteer": "5.1.0", "rimraf": "^2.5.4", "rollup": "^1.1.0", "rollup-plugin-commonjs": "^9.2.1", @@ -85,6 +85,6 @@ "source-map-explorer": "^1.3.2", "ts-node": "~8.3.0", "tslint": "~6.1.0", - "typescript": "~3.8.3" + "typescript": "~4.0.3" } } diff --git a/aio/tools/examples/shared/sync-boilerplate-dependencies.js b/aio/tools/examples/shared/sync-boilerplate-dependencies.js new file mode 100644 index 0000000000000..439c627fe93c0 --- /dev/null +++ b/aio/tools/examples/shared/sync-boilerplate-dependencies.js @@ -0,0 +1,64 @@ +#!/usr/bin/env node + +/** + * Usage: + * ```sh + * node sync-boilerplate-dependencies + * ``` + * + * Updates the dependency versions of the top-level `package.json` files in each sub-folder of + * `./boilerplate/` and `./boilerplate/viewengine/` to match the ones in `./package.json`. + */ +const fs = require('fs'); +const path = require('path'); + + +const BOILERPLATE_DIR = `${__dirname}/boilerplate`; +const VIEWENGINE_DIR = `${BOILERPLATE_DIR}/viewengine`; +const SHARED_PACKAGE_JSON_PATH = `${__dirname}/package.json`; + +const sharedPkgJson = loadJsonFile(SHARED_PACKAGE_JSON_PATH); +const boilerplatePkgJsonPaths = [ + ...collectPackageJsonFiles(BOILERPLATE_DIR), + ...collectPackageJsonFiles(VIEWENGINE_DIR), +]; + +boilerplatePkgJsonPaths.forEach(syncDependencies); + +// Helpers +function collectPackageJsonFiles(dirPath) { + return fs.readdirSync(dirPath) + .map(childName => `${dirPath}/${childName}`) + .filter(childPath => fs.statSync(childPath).isDirectory()) + .map(subDirPath => `${subDirPath}/package.json`) + .filter(pkgJsonPath => fs.existsSync(pkgJsonPath)); +} + +function loadJsonFile(filePath) { + return JSON.parse(fs.readFileSync(filePath, 'utf8')); +} + +function syncDependencies(boilerplatePkgJsonPath) { + console.log(`Syncing '${path.relative(__dirname, boilerplatePkgJsonPath)}'...`); + + const boilerplatePkgJson = loadJsonFile(boilerplatePkgJsonPath); + + ['dependencies', 'devDependencies', 'peerDependencies'] + .filter(depsProp => boilerplatePkgJson.hasOwnProperty(depsProp)) + .forEach(depsProp => { + const srcDeps = sharedPkgJson[depsProp]; + const dstDeps = boilerplatePkgJson[depsProp]; + + for (const dep of Object.keys(dstDeps)) { + if (!srcDeps.hasOwnProperty(dep)) { + throw new Error( + `Unable to update dependency '${dep}' in '${boilerplatePkgJsonPath} > ${depsProp}'. ` + + `The dependency is missing from '${SHARED_PACKAGE_JSON_PATH}'.`); + } + + dstDeps[dep] = srcDeps[dep]; + } + }); + + fs.writeFileSync(boilerplatePkgJsonPath, `${JSON.stringify(boilerplatePkgJson, null, 2)}\n`); +} diff --git a/aio/tools/examples/shared/yarn.lock b/aio/tools/examples/shared/yarn.lock index 714f688230d05..3a6f6fbf6566f 100644 --- a/aio/tools/examples/shared/yarn.lock +++ b/aio/tools/examples/shared/yarn.lock @@ -2,180 +2,188 @@ # yarn lockfile v1 -"@angular-devkit/architect@0.901.4": - version "0.901.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.901.4.tgz#10bef514b1101900f1e404d9bd991a6c0b221afe" - integrity sha512-w4RMj7eLhUSh70HUy5tW4EXjLQFXk0Lfr9WiSy5gvPGp+zzYxknI+Wn4Xid1wU/WS+4tuMv5nJIaNaH2sABESQ== - dependencies: - "@angular-devkit/core" "9.1.4" - rxjs "6.5.4" - -"@angular-devkit/architect@^0.900.6": - version "0.900.6" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.900.6.tgz#f82746975e1aa6593b66b3ceb742bcc0ff90b9a1" - integrity sha512-WK8e09DgNP1NHP1gqVQ9w+9rlRMVDJxAh4qZGJRjZBXd3LY7y84WWRmTpfuhOSu+82fR3/n76+urxraU3ZVphw== - dependencies: - "@angular-devkit/core" "9.0.6" - rxjs "6.5.3" - -"@angular-devkit/build-angular@~0.901.4": - version "0.901.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.901.4.tgz#0b9b9edb8a152ba37ed29a48ca046263a71ff6d0" - integrity sha512-Vod4bc6d38fuvqauIDQxKMe9hKW9m4QNzPKxEc+Dv5Xkv95WaGzkbUVu8M8t4E//sDDMpmcPdYOXSdR27WBi2Q== - dependencies: - "@angular-devkit/architect" "0.901.4" - "@angular-devkit/build-optimizer" "0.901.4" - "@angular-devkit/build-webpack" "0.901.4" - "@angular-devkit/core" "9.1.4" - "@babel/core" "7.9.0" - "@babel/generator" "7.9.3" - "@babel/preset-env" "7.9.0" - "@babel/template" "7.8.6" - "@jsdevtools/coverage-istanbul-loader" "3.0.3" - "@ngtools/webpack" "9.1.4" - ajv "6.12.0" - autoprefixer "9.7.4" - babel-loader "8.0.6" +"@angular-devkit/architect@0.1001.3": + version "0.1001.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1001.3.tgz#168aa424be9d0dad90d1a03129c3999fbf76a1cc" + integrity sha512-WS5IAN6I73jKapiHKYz3U05Kka4eVRmwCk++GWM2uGChluiZsI87eK8vxMS3KWDIqTnAOuMpDt3XWxlASv1nlQ== + dependencies: + "@angular-devkit/core" "10.1.3" + rxjs "6.6.2" + +"@angular-devkit/architect@^0.1001.0": + version "0.1001.2" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1001.2.tgz#9f4d1f95e85a2b85d26bf8f5c06909552d703a02" + integrity sha512-05o12amjZ8NNIFehKm/lFYf12xvCclC7V5tGl/9+V7g/3pQqakwAjCysgb9T+ETffhmKhMnE8XdAJZqF7YrDcw== + dependencies: + "@angular-devkit/core" "10.1.2" + rxjs "6.6.2" + +"@angular-devkit/build-angular@~0.1001.3": + version "0.1001.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.1001.3.tgz#8085bcb26394c5dc47ecc4b9d9c7a47dfe9e1df4" + integrity sha512-TQhNNfBeWLLOcXitmBTl2l95/9/2OcVVGyI5bxbpcCn8f9ioRVa2DvIxQLR92aoGkTrp7Vgd12xu07DSuuQwvg== + dependencies: + "@angular-devkit/architect" "0.1001.3" + "@angular-devkit/build-optimizer" "0.1001.3" + "@angular-devkit/build-webpack" "0.1001.3" + "@angular-devkit/core" "10.1.3" + "@babel/core" "7.11.1" + "@babel/generator" "7.11.0" + "@babel/plugin-transform-runtime" "7.11.0" + "@babel/preset-env" "7.11.0" + "@babel/runtime" "7.11.2" + "@babel/template" "7.10.4" + "@jsdevtools/coverage-istanbul-loader" "3.0.5" + "@ngtools/webpack" "10.1.3" + autoprefixer "9.8.6" + babel-loader "8.1.0" browserslist "^4.9.1" - cacache "15.0.0" + cacache "15.0.5" caniuse-lite "^1.0.30001032" circular-dependency-plugin "5.2.0" - copy-webpack-plugin "5.1.1" + copy-webpack-plugin "6.0.3" core-js "3.6.4" - css-loader "3.5.1" + css-loader "4.2.2" cssnano "4.1.10" file-loader "6.0.0" find-cache-dir "3.3.1" glob "7.1.6" - jest-worker "25.1.0" + jest-worker "26.3.0" karma-source-map-support "1.4.0" - less "3.11.1" - less-loader "5.0.0" - license-webpack-plugin "2.1.4" + less-loader "6.2.0" + license-webpack-plugin "2.3.0" loader-utils "2.0.0" - mini-css-extract-plugin "0.9.0" + mini-css-extract-plugin "0.10.0" minimatch "3.0.4" - open "7.0.3" - parse5 "4.0.0" - postcss "7.0.27" + open "7.2.0" + parse5 "6.0.1" + parse5-htmlparser2-tree-adapter "6.0.1" + pnp-webpack-plugin "1.6.4" + postcss "7.0.32" postcss-import "12.0.1" postcss-loader "3.0.0" - raw-loader "4.0.0" - regenerator-runtime "0.13.5" + raw-loader "4.0.1" + regenerator-runtime "0.13.7" + resolve-url-loader "3.1.1" rimraf "3.0.2" - rollup "2.1.0" - rxjs "6.5.4" - sass "1.26.3" - sass-loader "8.0.2" - semver "7.1.3" + rollup "2.26.5" + rxjs "6.6.2" + sass "1.26.10" + sass-loader "10.0.1" + semver "7.3.2" source-map "0.7.3" - source-map-loader "0.2.4" - speed-measure-webpack-plugin "1.3.1" - style-loader "1.1.3" - stylus "0.54.7" + source-map-loader "1.0.2" + source-map-support "0.5.19" + speed-measure-webpack-plugin "1.3.3" + style-loader "1.2.1" + stylus "0.54.8" stylus-loader "3.0.2" - terser "4.6.10" - terser-webpack-plugin "2.3.5" + terser "5.3.0" + terser-webpack-plugin "4.1.0" tree-kill "1.2.2" - webpack "4.42.0" + webpack "4.44.1" webpack-dev-middleware "3.7.2" - webpack-dev-server "3.10.3" + webpack-dev-server "3.11.0" webpack-merge "4.2.2" webpack-sources "1.4.3" - webpack-subresource-integrity "1.4.0" - worker-plugin "4.0.2" + webpack-subresource-integrity "1.4.1" + worker-plugin "5.0.0" -"@angular-devkit/build-optimizer@0.901.4": - version "0.901.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.901.4.tgz#a8e836d6aa687a78cf2e2b0f888e777f51ca5ad9" - integrity sha512-iDMlNRwd8ICMBKnycfw55hdnL5kCiqUjQn+aK/4uOMJMz49tiYMNJAaznXX2BFKmYSmbapKjEbzx9yMYRi9Y7w== +"@angular-devkit/build-optimizer@0.1001.3": + version "0.1001.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.1001.3.tgz#11e6ea59ab0d6f6c0724c9453c82a2f15653534d" + integrity sha512-tQy4ADOVDL0hJcykpZzqfInQV6ft499E3g+D0jcZL/imSsxH4EaaBA2HCc0JTeAFjmkI32OhD9T8G/swqqBcVw== dependencies: loader-utils "2.0.0" source-map "0.7.3" - tslib "1.11.1" - typescript "3.6.5" + tslib "2.0.1" + typescript "4.0.2" webpack-sources "1.4.3" -"@angular-devkit/build-webpack@0.901.4": - version "0.901.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.901.4.tgz#d6b7b3f05288c31c4ed9e5dfd5370c7d6c5a0a02" - integrity sha512-YBOufI4TGAtIDCS6erFygYJX/fkd8xwI58d+7iFIBmtIJC4/fpGjX6qkHMCBgh8HXAkEPSORBCYQn9O44J1ZXQ== +"@angular-devkit/build-webpack@0.1001.3": + version "0.1001.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1001.3.tgz#889aaa2dde7daacb88969d9ede5ba2df94250df3" + integrity sha512-XpAEWRWIdh/bk2UHkP7iIjEiVwkQkAWoZPNYMJzg3iN/iAAdUDPiNBTXhFZEZjFEWT0RXl4iKW2hr5LFvpe6lw== dependencies: - "@angular-devkit/architect" "0.901.4" - "@angular-devkit/core" "9.1.4" - rxjs "6.5.4" + "@angular-devkit/architect" "0.1001.3" + "@angular-devkit/core" "10.1.3" + rxjs "6.6.2" -"@angular-devkit/core@9.0.6", "@angular-devkit/core@^9.0.6": - version "9.0.6" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-9.0.6.tgz#cd4862e54f4dad9b47f515abf24e4d440cf8ba13" - integrity sha512-hCZJbnqLEm1F5Bx+ILcdd3LPgQTn4WFWpfUqMEGGj7UirRInWcz+6UpYotKGTJw85/mV01LrIbtWIkAUXbkkhg== +"@angular-devkit/core@10.1.2", "@angular-devkit/core@^10.1.0": + version "10.1.2" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-10.1.2.tgz#3deb429596a6127c5b68bbc3bbd49cf00aeac966" + integrity sha512-LMxesiCuXRe3UzPdRouXsC1W73/q6rVtACVoD5GdzmmnZ7cRh7oiwonqT0lEXIKQikMsZUasUOXHD2HoKV6BoA== dependencies: - ajv "6.10.2" - fast-json-stable-stringify "2.0.0" - magic-string "0.25.4" - rxjs "6.5.3" + ajv "6.12.4" + fast-json-stable-stringify "2.1.0" + magic-string "0.25.7" + rxjs "6.6.2" source-map "0.7.3" -"@angular-devkit/core@9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-9.1.4.tgz#97bb5681471ac40843167f2387b23e92a3e21ce4" - integrity sha512-OPFQDmT4XabLMSRDgmnzedlOrc83DzQIgLcfoh/UhZ7aJKf/2Vq4l09p/DkMNI36vN5BRL0zDZt7TjvKNgyYgA== +"@angular-devkit/core@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-10.1.3.tgz#48776a87253b40f6005b14413e089a1fee6b7227" + integrity sha512-Ub31/eqFtSuQy3V+B74Jt0jAUw8fs8sbd0ZL2UHYUJyrwm20iIRam+mOD3Sj8HFrDGLR8m56KsxJ12KvC1oxtQ== dependencies: - ajv "6.12.0" + ajv "6.12.4" fast-json-stable-stringify "2.1.0" magic-string "0.25.7" - rxjs "6.5.4" + rxjs "6.6.2" source-map "0.7.3" -"@angular-devkit/schematics@9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-9.1.4.tgz#f493eebfae71f609b4ea81402013efe926acc76d" - integrity sha512-RAbdnUEZ3JTLmWSBiXT5trsVx8Fi72fxN9CiRaluM09Cytg6BUc1wC5XCO0YPvhI400+3Ro1nwjPXezjg7LXzQ== - dependencies: - "@angular-devkit/core" "9.1.4" - ora "4.0.3" - rxjs "6.5.4" - -"@angular/animations@~9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-9.1.4.tgz#22f64a062103d4903f2c7d862889a88fc6553bc7" - integrity sha512-gMo/DbCm5BDArladMAeC7/75T2DvhLr4CSUGJt/P/aimTEG2ywoAALs3pzwSSe4qxrHiR0OIksVW3l4km3iXEw== - -"@angular/cli@~9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-9.1.4.tgz#0c1938e2342bb3bcd978b32458ab20f1bf007ba5" - integrity sha512-H9MqoT4zyIv+Yo3cvRVkzafWGHsqt7jUvtvGwMHIDMTfEX+Q8yiYlDLL6WM3Eb6/hDmLcRGC/GI495sKS1z5qA== - dependencies: - "@angular-devkit/architect" "0.901.4" - "@angular-devkit/core" "9.1.4" - "@angular-devkit/schematics" "9.1.4" - "@schematics/angular" "9.1.4" - "@schematics/update" "0.901.4" +"@angular-devkit/schematics@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-10.1.3.tgz#49ccf51a1a8e71625b5ec1a0d24adfc24c31c903" + integrity sha512-5+E2bBBsphuz1KfloC5yA+hXSEbxMokkp5UEp+X9VC7zUGTXV8sxuvcbBo+JVutaoNHezJGu2JUx/LqNrKd58w== + dependencies: + "@angular-devkit/core" "10.1.3" + ora "5.0.0" + rxjs "6.6.2" + +"@angular/animations@~10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-10.1.3.tgz#2047dae5fc1bf0f5173a410f0103fb003113d1b9" + integrity sha512-qIdxP28iF6qaoGBB3C6VvHt22nR3FMK5kh+no+jYmmy6z5cBVhwS/Vb6nkx+XRqivKBVHxWNZQ4ae6xmTg/k7A== + dependencies: + tslib "^2.0.0" + +"@angular/cli@~10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-10.1.3.tgz#188f99583814e97727787869065d228c1b1f4407" + integrity sha512-wj+ZcTLRzM94asLUZRO5U96CLEsnWosa3Iqub+1AH1/C8Wv2w/2njUKDM7ifQeebYzjPb5EcN4EIAGcHAGyeWw== + dependencies: + "@angular-devkit/architect" "0.1001.3" + "@angular-devkit/core" "10.1.3" + "@angular-devkit/schematics" "10.1.3" + "@schematics/angular" "10.1.3" + "@schematics/update" "0.1001.3" "@yarnpkg/lockfile" "1.1.0" ansi-colors "4.1.1" debug "4.1.1" ini "1.3.5" - inquirer "7.1.0" + inquirer "7.3.3" npm-package-arg "8.0.1" - npm-pick-manifest "6.0.0" - open "7.0.3" + npm-pick-manifest "6.1.0" + open "7.2.0" pacote "9.5.12" read-package-tree "5.3.1" rimraf "3.0.2" - semver "7.1.3" + semver "7.3.2" symbol-observable "1.2.0" - universal-analytics "0.4.20" - uuid "7.0.2" + universal-analytics "0.4.23" + uuid "8.3.0" -"@angular/common@~9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@angular/common/-/common-9.1.4.tgz#23d7b42cd87aba634b78b8d73e12c6ebffe86043" - integrity sha512-JvCoCWVbx0tF7l/0WTi24ui/mc2SElyVSNchR4VK/FViARnkvnSBdI/Ef5QWXrsPyKU4PYBtnWWgyxRspH+FBA== +"@angular/common@~10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/common/-/common-10.1.3.tgz#43b63609e3ef321d8b6835a5cd339587bf0aecbe" + integrity sha512-+9UsK+ZTCLO3MvTYlDTbjJGAZxtK9WftHWxbT3NTAJ8tisDfb+MwXB0xNw7qLOysMe3u04zShT0YXYZo5aJBrw== + dependencies: + tslib "^2.0.0" -"@angular/compiler-cli@~9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-9.1.4.tgz#24c7c7060bb13f65337fb2998322d56021e185c1" - integrity sha512-n3PzqNnPD7s/AF9mv5CnarK0sgfoq4txFncHjJWBSltuTQoz6BDZyjuEdqsSLUvgAZPeLsmohemOzEE38HYHZA== +"@angular/compiler-cli@~10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-10.1.3.tgz#e3b7dc11a362ec9fe70060e3730547a7e57cb69a" + integrity sha512-31XZ6jv4Vjsaa0kF+gzeHMyQiMILpaaZa+j1f5IqeS+HBl1ThxLTCpAhR1TVfZ/2EZV6uAM8o8FTYrhscy9qTA== dependencies: canonical-path "1.0.0" chokidar "^3.0.0" @@ -188,74 +196,99 @@ semver "^6.3.0" source-map "^0.6.1" sourcemap-codec "^1.4.8" + tslib "^2.0.0" yargs "15.3.0" -"@angular/compiler@~9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-9.1.4.tgz#fe833fc3b74768bdd56b1bdd0010870f38ffaedc" - integrity sha512-B+f3lviFNEJtL9V9exSKYPSz2Ddb6dxgPzQR7GSjGikDo+fKMtC1PjNwgJooS9gavhQx30uwkEEMIPYQbM6nNA== +"@angular/compiler@9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-9.0.0.tgz#87e0bef4c369b6cadae07e3a4295778fc93799d5" + integrity sha512-ctjwuntPfZZT2mNj2NDIVu51t9cvbhl/16epc5xEwyzyDt76pX9UgwvY+MbXrf/C/FWwdtmNtfP698BKI+9leQ== + +"@angular/compiler@~10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-10.1.3.tgz#84c2da8c37d02a7b7337ae34c173ce1d90d57d9a" + integrity sha512-rfiXkf6BPFWHLU0rg+c5BgTdrxVJcyOQipKw3iI2W00RsU3VCFTXKYpm10DamhRrNOf8rJcboqMbdi34awy6xA== + dependencies: + tslib "^2.0.0" -"@angular/core@~9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@angular/core/-/core-9.1.4.tgz#85f5322f42cf8add597fc6b02913e8fc3308c361" - integrity sha512-ND240vncmVD2KVe/KSQU3d/DxxoRipFg1+jFOFZGt0n0orCBHk/V1fu9iaG1sRyldL0+rCQ+fTI+1N4DTmMnxA== +"@angular/core@9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-9.0.0.tgz#227dc53e1ac81824f998c6e76000b7efc522641e" + integrity sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w== -"@angular/elements@~9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@angular/elements/-/elements-9.1.4.tgz#b3bedbce72a2d61493f2cab4a09dadd1117cd91a" - integrity sha512-VXb+/eZv2x8CsDESnk8ICysDE3C2Htuj76WiG6NO4X1aX26XLTvnT5YLnOJ+8l8L88eh6s80Rphw6Gr6amUXHA== +"@angular/core@~10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-10.1.3.tgz#7dbc38eb73a1d526d9c2aca3025c42e38c4acdc3" + integrity sha512-2rnNa8bSH1JoQRzUWXXvPGgxtNA6mSiIqDZs1tHdQZxJI15NbyAJhw6lglgBFahE/nOcUx+11ZhxaPJWSsbEOg== + dependencies: + tslib "^2.0.0" -"@angular/forms@~9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-9.1.4.tgz#7cb75b5731bd6cbcf4a45b7b2cc68b3581de8cc1" - integrity sha512-Njt+pMLfPBchL0/ayIjJqXL6ZfM4Ccvf7KO1wS1HMzh3QlmfNa0JSgc4pfrbRJAMN9g7V/FYLyKejs1bJZkenA== +"@angular/elements@~10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/elements/-/elements-10.1.3.tgz#a1b63a55f9f0f6bf150a7511a4fb20639869a767" + integrity sha512-eKgXIQlt1aRQc7QyoEZI0D0qsPn2banQuhJmLxKqjELNO8WJZt8VNEAvFMa3a2LO+OaVr6rv0YZhYYki5hkLiQ== + dependencies: + tslib "^2.0.0" -"@angular/language-service@~9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-9.1.4.tgz#2fa2c444e5a5a6036d5ca43d2887826df17d0553" - integrity sha512-eyVxxiegdb4ESdFGfkuDN+YfUbOVHRQLjIl6ACFJQDNHzVXzbmuqpyr5hIJANIVady103/7+dqRxxJo1DdIdTQ== +"@angular/forms@~10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-10.1.3.tgz#c48a9c79bc50b21017685037ad628ff0bc8d5e61" + integrity sha512-ntLnIZnEo+9ziajnjQPYvVR5m0gRfQBbXx5dug4EuUI5SzE2WzcTEZTnltgw4cLqOy/fOt8cXMiW0YeRBHsjKA== + dependencies: + tslib "^2.0.0" -"@angular/localize@~9.1.4": - version "9.1.11" - resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-9.1.11.tgz#25921d794836fb7a07d284c1ac0ed06c10e77d50" - integrity sha512-CrR7RniwJIK3+QKH8nHl35KDAHZn1mp1QAd5vujTWKw6YRLfio7SjM9qIfzw5y4WZuUitTsqKlQT/m/NK146Ag== +"@angular/localize@~10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/localize/-/localize-10.1.3.tgz#791bf79f8d14872c87f88be6bce4de718cded1e9" + integrity sha512-OJTCUTd7qF3JoqCM7+lNTNUErzHpm5TvGObFthXvP2V+u1ipsFeqTffzqEv7SrZ5+PkabRUditUrPOVAkFIlyw== dependencies: "@babel/core" "7.8.3" glob "7.1.2" yargs "15.3.0" -"@angular/platform-browser-dynamic@~9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-9.1.4.tgz#bf1cde9156bd29eeeef932b683b0c993614f75d5" - integrity sha512-YtVbnxyS6FU7xNpA6A95tmSfrB8+WC7OH3mbP8M9NaGk0OYz8B/JOe1HByP4JRpEGCvBtXdJ2NSW/MpLIT8SiQ== +"@angular/platform-browser-dynamic@~10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-10.1.3.tgz#e90f9329f2ccbfe817680f16a00686440653ee06" + integrity sha512-JGVz0XxiZuF1FGJ2zUk1/TogIlBFgFCUgNbSyULIfE/UXcuuvvLlzF+ls26tHK06lFHRAVHFjjDpyA270UzRTQ== + dependencies: + tslib "^2.0.0" -"@angular/platform-browser@~9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-9.1.4.tgz#c4fe868f12a6593702967a957a6bc8aa50c34f3b" - integrity sha512-mBCHfTl+5tQfaUiGlDujP7mFBzovFc54Zi2kcCE8DSdSSVQ2TPBo6hXa6y2cL3hJPFZzQ7mC4ORFrsGADhHn/w== +"@angular/platform-browser@~10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-10.1.3.tgz#f6a5c5098e878b964cfddc296fb63eb147710211" + integrity sha512-Y5/M9NEmQceda96a9ntmxidfgJTf23DmEvGw0SJ1TAn2X9EjlM4s7H8KNH9R/tDPK9QcuvzX9FTZsxQ9b6kCFQ== + dependencies: + tslib "^2.0.0" -"@angular/platform-server@~9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-9.1.4.tgz#61c704dffb250d244d6286813537b40edbf70f59" - integrity sha512-FynxZ1bmR2itvwKanUVzuUjugfZcIxZcT0Dx98BRol0Oc30RitRz8paJk9xAxySKSpZacwGJ/HkSxQdjIYWJOw== +"@angular/platform-server@~10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-10.1.3.tgz#4c4c5f071018406dd5150bee5ea6936030493b57" + integrity sha512-r7wcczPdvxAAZsblrfRbp/UsMBO1Uu0iK5YaAowpF6q8axgjYVxriV5k9IA2T2V+k+jTGUdI3XZwgrAkkbe7gg== dependencies: domino "^2.1.2" + tslib "^2.0.0" xhr2 "^0.2.0" -"@angular/router@~9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@angular/router/-/router-9.1.4.tgz#1bd09c84d1ec75bdc7cc75e80014eda5041ffeb7" - integrity sha512-yUyjCgG2P2Jh8MvoyC6yirmAtx1Qe7MKLuLvsa9WOB571QNEcNLTYMfAMHUKsQTcE/+o984QyLlneoibgI9wFA== +"@angular/router@~10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/router/-/router-10.1.3.tgz#42b4c173bba8441a3e1eb6f1ca60e3b2a4eb3e86" + integrity sha512-CAd6u1y+NjB8edtuC2j2OpS6xFO+s90bg4kyu7zr9i0wIQX8xI+neFzkTeoYWJ0PNfi05cCGelyQnLZPZFsyvw== + dependencies: + tslib "^2.0.0" -"@angular/service-worker@~9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@angular/service-worker/-/service-worker-9.1.4.tgz#acafd57fae1f745c42f6a3adf461c8bb032013c7" - integrity sha512-q3MIgWOeCg9DhQGDk81bDJYjauBtf3GxvtGnnZG6XEjw3r3k/ykTyRPGHgC5MTw/XFF4Y6dfpgLIXT42AXLhaw== +"@angular/service-worker@~10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/service-worker/-/service-worker-10.1.3.tgz#f5e8aa4663d6aae059c338cf796ae49ccd827c14" + integrity sha512-Zs8W+CCPxGGQFpF8BahF/ngwAnUOeFZIICfEdZaYnwwxFNWuJcwBRTc8DARyR58Ggc3wncZYd6KbHs+oa1n6Lg== + dependencies: + tslib "^2.0.0" -"@angular/upgrade@~9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@angular/upgrade/-/upgrade-9.1.4.tgz#d65e9d9eafb6884768e8953011d481334d59be04" - integrity sha512-kqmsX27qukWDJpxvEBpGm+QRdosLzPqSx8pXD7aykcOp3//O/GVnKOJFh6w//WrYRtCe4+PFNckM5uN01BqnPw== +"@angular/upgrade@~10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/upgrade/-/upgrade-10.1.3.tgz#5ccd51f77aeac21439007a5af69c2546cb6b78e4" + integrity sha512-VREb98W4I/ldc0lTbq7sWrrb3hQLtgvXe6VpUWMSlAEtPbaXUnHWz/utVm1+hXZlCMRpoJUMxw5u9+M1odFm7w== + dependencies: + tslib "^2.0.0" "@babel/code-frame@^7.0.0": version "7.0.0" @@ -270,6 +303,13 @@ dependencies: "@babel/highlight" "^7.10.1" +"@babel/code-frame@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" + integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== + dependencies: + "@babel/highlight" "^7.10.4" + "@babel/code-frame@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" @@ -284,15 +324,37 @@ dependencies: "@babel/highlight" "^7.8.3" -"@babel/compat-data@^7.9.0", "@babel/compat-data@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.9.6.tgz#3f604c40e420131affe6f2c8052e9a275ae2049b" - integrity sha512-5QPTrNen2bm7RBc7dsOmcA5hbrS4O2Vhmk5XOL4zWW/zD/hV0iinpefDlkm+tBBy8kDtFaaeEvmAqt+nURAV2g== +"@babel/compat-data@^7.10.4", "@babel/compat-data@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.11.0.tgz#e9f73efe09af1355b723a7f39b11bad637d7c99c" + integrity sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ== dependencies: - browserslist "^4.11.1" + browserslist "^4.12.0" invariant "^2.2.4" semver "^5.5.0" +"@babel/core@7.11.1": + version "7.11.1" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.1.tgz#2c55b604e73a40dc21b0e52650b11c65cf276643" + integrity sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.0" + "@babel/helper-module-transforms" "^7.11.0" + "@babel/helpers" "^7.10.4" + "@babel/parser" "^7.11.1" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.11.0" + "@babel/types" "^7.11.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.19" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + "@babel/core@7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.3.tgz#30b0ebb4dd1585de6923a0b4d179e0b9f5d82941" @@ -314,28 +376,6 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.0.tgz#ac977b538b77e132ff706f3b8a4dbad09c03c56e" - integrity sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.9.0" - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helpers" "^7.9.0" - "@babel/parser" "^7.9.0" - "@babel/template" "^7.8.6" - "@babel/traverse" "^7.9.0" - "@babel/types" "^7.9.0" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.1" - json5 "^2.1.2" - lodash "^4.17.13" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - "@babel/core@^7.7.5": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.4.tgz#d496799e5c12195b3602d0fddd77294e3e38e80e" @@ -357,14 +397,13 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@7.9.3": - version "7.9.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.3.tgz#7c8b2956c6f68b3ab732bd16305916fbba521d94" - integrity sha512-RpxM252EYsz9qLUIq6F7YJyK1sv0wWDBFuztfDGWaQKzHjqDHysxSiRUpA/X9jmfqo+WzkAVKFaUily5h+gDCQ== +"@babel/generator@7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.0.tgz#4b90c78d8c12825024568cbe83ee6c9af193585c" + integrity sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ== dependencies: - "@babel/types" "^7.9.0" + "@babel/types" "^7.11.0" jsesc "^2.5.1" - lodash "^4.17.13" source-map "^0.5.0" "@babel/generator@^7.10.1", "@babel/generator@^7.8.3": @@ -377,14 +416,13 @@ lodash "^4.17.13" source-map "^0.5.0" -"@babel/generator@^7.4.0", "@babel/generator@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.4.tgz#db651e2840ca9aa66f327dcec1dc5f5fa9611369" - integrity sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg== +"@babel/generator@^7.11.0", "@babel/generator@^7.11.5": + version "7.11.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.6.tgz#b868900f81b163b4d464ea24545c61cbac4dc620" + integrity sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA== dependencies: - "@babel/types" "^7.7.4" + "@babel/types" "^7.11.5" jsesc "^2.5.1" - lodash "^4.17.13" source-map "^0.5.0" "@babel/generator@^7.8.4": @@ -397,15 +435,12 @@ lodash "^4.17.13" source-map "^0.5.0" -"@babel/generator@^7.9.0", "@babel/generator@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.6.tgz#5408c82ac5de98cda0d77d8124e99fa1f2170a43" - integrity sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ== +"@babel/helper-annotate-as-pure@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3" + integrity sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA== dependencies: - "@babel/types" "^7.9.6" - jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" + "@babel/types" "^7.10.4" "@babel/helper-annotate-as-pure@^7.8.3": version "7.8.3" @@ -414,25 +449,46 @@ dependencies: "@babel/types" "^7.8.3" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz#c84097a427a061ac56a1c30ebf54b7b22d241503" - integrity sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" + integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg== dependencies: - "@babel/helper-explode-assignable-expression" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/helper-explode-assignable-expression" "^7.10.4" + "@babel/types" "^7.10.4" -"@babel/helper-compilation-targets@^7.8.7": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.9.6.tgz#1e05b7ccc9d38d2f8b40b458b380a04dcfadd38a" - integrity sha512-x2Nvu0igO0ejXzx09B/1fGBxY9NXQlBW2kZsSxCJft+KHN8t9XWzIvFxtPHnBOAXpVsdxZKZFbRUC8TsNKajMw== +"@babel/helper-compilation-targets@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz#804ae8e3f04376607cc791b9d47d540276332bd2" + integrity sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ== dependencies: - "@babel/compat-data" "^7.9.6" - browserslist "^4.11.1" + "@babel/compat-data" "^7.10.4" + browserslist "^4.12.0" invariant "^2.2.4" levenary "^1.1.1" semver "^5.5.0" +"@babel/helper-create-class-features-plugin@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d" + integrity sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.10.5" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + +"@babel/helper-create-regexp-features-plugin@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8" + integrity sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-regex" "^7.10.4" + regexpu-core "^4.7.0" + "@babel/helper-create-regexp-features-plugin@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.3.tgz#c774268c95ec07ee92476a3862b75cc2839beb79" @@ -450,22 +506,21 @@ "@babel/helper-regex" "^7.8.3" regexpu-core "^4.7.0" -"@babel/helper-define-map@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz#a0655cad5451c3760b726eba875f1cd8faa02c15" - integrity sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g== +"@babel/helper-define-map@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" + integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ== dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/types" "^7.8.3" - lodash "^4.17.13" + "@babel/helper-function-name" "^7.10.4" + "@babel/types" "^7.10.5" + lodash "^4.17.19" -"@babel/helper-explode-assignable-expression@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz#a728dc5b4e89e30fc2dfc7d04fa28a930653f982" - integrity sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw== +"@babel/helper-explode-assignable-expression@^7.10.4": + version "7.11.4" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz#2d8e3470252cc17aba917ede7803d4a7a276a41b" + integrity sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ== dependencies: - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/types" "^7.10.4" "@babel/helper-function-name@^7.10.1": version "7.10.1" @@ -476,14 +531,14 @@ "@babel/template" "^7.10.1" "@babel/types" "^7.10.1" -"@babel/helper-function-name@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e" - integrity sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ== +"@babel/helper-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" + integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== dependencies: - "@babel/helper-get-function-arity" "^7.7.4" - "@babel/template" "^7.7.4" - "@babel/types" "^7.7.4" + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helper-function-name@^7.8.3": version "7.8.3" @@ -494,15 +549,6 @@ "@babel/template" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helper-function-name@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c" - integrity sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw== - dependencies: - "@babel/helper-get-function-arity" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/types" "^7.9.5" - "@babel/helper-get-function-arity@^7.10.1": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz#7303390a81ba7cb59613895a192b93850e373f7d" @@ -510,12 +556,12 @@ dependencies: "@babel/types" "^7.10.1" -"@babel/helper-get-function-arity@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0" - integrity sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA== +"@babel/helper-get-function-arity@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" + integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== dependencies: - "@babel/types" "^7.7.4" + "@babel/types" "^7.10.4" "@babel/helper-get-function-arity@^7.8.3": version "7.8.3" @@ -524,57 +570,69 @@ dependencies: "@babel/types" "^7.8.3" -"@babel/helper-hoist-variables@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz#1dbe9b6b55d78c9b4183fc8cdc6e30ceb83b7134" - integrity sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg== +"@babel/helper-hoist-variables@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" + integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA== dependencies: - "@babel/types" "^7.8.3" + "@babel/types" "^7.10.4" -"@babel/helper-member-expression-to-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" - integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA== +"@babel/helper-member-expression-to-functions@^7.10.4", "@babel/helper-member-expression-to-functions@^7.10.5": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df" + integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q== dependencies: - "@babel/types" "^7.8.3" + "@babel/types" "^7.11.0" -"@babel/helper-module-imports@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498" - integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg== +"@babel/helper-module-imports@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" + integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw== dependencies: - "@babel/types" "^7.8.3" + "@babel/types" "^7.10.4" -"@babel/helper-module-transforms@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz#43b34dfe15961918707d247327431388e9fe96e5" - integrity sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA== +"@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.10.5", "@babel/helper-module-transforms@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359" + integrity sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg== dependencies: - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.6" - "@babel/helper-simple-access" "^7.8.3" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/template" "^7.8.6" - "@babel/types" "^7.9.0" - lodash "^4.17.13" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/template" "^7.10.4" + "@babel/types" "^7.11.0" + lodash "^4.17.19" -"@babel/helper-optimise-call-expression@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9" - integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ== +"@babel/helper-optimise-call-expression@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" + integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== dependencies: - "@babel/types" "^7.8.3" + "@babel/types" "^7.10.4" "@babel/helper-plugin-utils@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== +"@babel/helper-plugin-utils@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" + integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== + "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== +"@babel/helper-regex@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.5.tgz#32dfbb79899073c415557053a19bd055aae50ae0" + integrity sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg== + dependencies: + lodash "^4.17.19" + "@babel/helper-regex@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.8.3.tgz#139772607d51b93f23effe72105b319d2a4c6965" @@ -582,44 +640,40 @@ dependencies: lodash "^4.17.13" -"@babel/helper-remap-async-to-generator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz#273c600d8b9bf5006142c1e35887d555c12edd86" - integrity sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA== +"@babel/helper-remap-async-to-generator@^7.10.4": + version "7.11.4" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz#4474ea9f7438f18575e30b0cac784045b402a12d" + integrity sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA== dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-wrap-function" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-wrap-function" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" -"@babel/helper-replace-supers@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz#91192d25f6abbcd41da8a989d4492574fb1530bc" - integrity sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA== +"@babel/helper-replace-supers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" + integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A== dependencies: - "@babel/helper-member-expression-to-functions" "^7.8.3" - "@babel/helper-optimise-call-expression" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/helper-member-expression-to-functions" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" -"@babel/helper-replace-supers@^7.8.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.9.6.tgz#03149d7e6a5586ab6764996cd31d6981a17e1444" - integrity sha512-qX+chbxkbArLyCImk3bWV+jB5gTNU/rsze+JlcF6Nf8tVTigPJSI1o1oBow/9Resa1yehUO9lIipsmu9oG4RzA== +"@babel/helper-simple-access@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz#0f5ccda2945277a2a7a2d3a821e15395edcf3461" + integrity sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw== dependencies: - "@babel/helper-member-expression-to-functions" "^7.8.3" - "@babel/helper-optimise-call-expression" "^7.8.3" - "@babel/traverse" "^7.9.6" - "@babel/types" "^7.9.6" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" -"@babel/helper-simple-access@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz#7f8109928b4dab4654076986af575231deb639ae" - integrity sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw== +"@babel/helper-skip-transparent-expression-wrappers@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz#eec162f112c2f58d3af0af125e3bb57665146729" + integrity sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q== dependencies: - "@babel/template" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/types" "^7.11.0" "@babel/helper-split-export-declaration@^7.10.1": version "7.10.1" @@ -628,12 +682,12 @@ dependencies: "@babel/types" "^7.10.1" -"@babel/helper-split-export-declaration@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8" - integrity sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug== +"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" + integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== dependencies: - "@babel/types" "^7.7.4" + "@babel/types" "^7.11.0" "@babel/helper-split-export-declaration@^7.8.3": version "7.8.3" @@ -647,20 +701,34 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz#5770b0c1a826c4f53f5ede5e153163e0318e94b5" integrity sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw== +"@babel/helper-validator-identifier@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" + integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== + "@babel/helper-validator-identifier@^7.9.5": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80" integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g== -"@babel/helper-wrap-function@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610" - integrity sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ== +"@babel/helper-wrap-function@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" + integrity sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug== dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/helper-function-name" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helpers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044" + integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA== + dependencies: + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helpers@^7.8.3": version "7.10.1" @@ -680,15 +748,6 @@ "@babel/traverse" "^7.8.4" "@babel/types" "^7.8.3" -"@babel/helpers@^7.9.0": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.9.6.tgz#092c774743471d0bb6c7de3ad465ab3d3486d580" - integrity sha512-tI4bUbldloLcHWoRUMAj4g1bF313M/o6fBKhIsb3QnGVPwRm9JsNf/gqMkQ7zjqReABiffPV6RWj7hEglID5Iw== - dependencies: - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.9.6" - "@babel/types" "^7.9.6" - "@babel/highlight@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" @@ -706,6 +765,15 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/highlight@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + chalk "^2.0.0" + js-tokens "^4.0.0" + "@babel/highlight@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797" @@ -720,88 +788,124 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.2.tgz#871807f10442b92ff97e4783b9b54f6a0ca812d0" integrity sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ== -"@babel/parser@^7.4.3", "@babel/parser@^7.7.4": - version "7.7.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.5.tgz#cbf45321619ac12d83363fcf9c94bb67fa646d71" - integrity sha512-KNlOe9+/nk4i29g0VXgl8PEXIRms5xKLJeuZ6UptN0fHv+jDiriG+y94X6qAgWTR0h3KaoM1wK5G5h7MHFRSig== +"@babel/parser@^7.10.4", "@babel/parser@^7.11.1", "@babel/parser@^7.11.5": + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037" + integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q== -"@babel/parser@^7.7.5", "@babel/parser@^7.8.3", "@babel/parser@^7.8.4": +"@babel/parser@^7.8.3", "@babel/parser@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.4.tgz#d1dbe64691d60358a974295fa53da074dd2ce8e8" integrity sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw== -"@babel/parser@^7.8.6", "@babel/parser@^7.9.0", "@babel/parser@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.6.tgz#3b1bbb30dabe600cd72db58720998376ff653bc7" - integrity sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q== - -"@babel/plugin-proposal-async-generator-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f" - integrity sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw== +"@babel/plugin-proposal-async-generator-functions@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz#3491cabf2f7c179ab820606cec27fed15e0e8558" + integrity sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-remap-async-to-generator" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.10.4" "@babel/plugin-syntax-async-generators" "^7.8.0" -"@babel/plugin-proposal-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz#38c4fe555744826e97e2ae930b0fb4cc07e66054" - integrity sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w== +"@babel/plugin-proposal-class-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz#a33bf632da390a59c7a8c570045d1115cd778807" + integrity sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-proposal-dynamic-import@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz#ba57a26cb98b37741e9d5bca1b8b0ddf8291f17e" + integrity sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-dynamic-import" "^7.8.0" -"@babel/plugin-proposal-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz#da5216b238a98b58a1e05d6852104b10f9a70d6b" - integrity sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q== +"@babel/plugin-proposal-export-namespace-from@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz#570d883b91031637b3e2958eea3c438e62c05f54" + integrity sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-proposal-json-strings@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz#593e59c63528160233bd321b1aebe0820c2341db" + integrity sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.0" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" - integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw== +"@babel/plugin-proposal-logical-assignment-operators@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz#9f80e482c03083c87125dee10026b58527ea20c8" + integrity sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz#02a7e961fc32e6d5b2db0649e01bf80ddee7e04a" + integrity sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@babel/plugin-proposal-numeric-separator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz#5d6769409699ec9b3b68684cd8116cedff93bad8" - integrity sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ== +"@babel/plugin-proposal-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz#ce1590ff0a65ad12970a609d78855e9a4c1aef06" + integrity sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@^7.9.0": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.6.tgz#7a093586fcb18b08266eb1a7177da671ac575b63" - integrity sha512-Ga6/fhGqA9Hj+y6whNpPv8psyaK5xzrQwSPsGPloVkvmH+PqW1ixdnfJ9uIO06OjQNYol3PMnfmJ8vfZtkzF+A== +"@babel/plugin-proposal-object-rest-spread@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz#bd81f95a1f746760ea43b6c2d3d62b11790ad0af" + integrity sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.9.5" + "@babel/plugin-transform-parameters" "^7.10.4" -"@babel/plugin-proposal-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz#9dee96ab1650eed88646ae9734ca167ac4a9c5c9" - integrity sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw== +"@babel/plugin-proposal-optional-catch-binding@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz#31c938309d24a78a49d68fdabffaa863758554dd" + integrity sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz#31db16b154c39d6b8a645292472b98394c292a58" - integrity sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w== +"@babel/plugin-proposal-optional-chaining@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz#de5866d0646f6afdaab8a566382fe3a221755076" + integrity sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3": +"@babel/plugin-proposal-private-methods@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz#b160d972b8fdba5c7d111a145fc8c421fc2a6909" + integrity sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-proposal-unicode-property-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz#4483cda53041ce3413b7fe2f00022665ddfaa75d" + integrity sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.8.8" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz#ee3a95e90cdc04fe8cd92ec3279fa017d68a0d1d" integrity sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A== @@ -816,6 +920,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-class-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz#6644e6a0baa55a61f9e3231f6c9eeb6ee46c124c" + integrity sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-dynamic-import@^7.8.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" @@ -823,6 +934,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-json-strings@^7.8.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" @@ -830,6 +948,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" @@ -837,12 +962,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.8.0", "@babel/plugin-syntax-numeric-separator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz#0e3fb63e09bea1b11e96467271c8308007e7c41f" - integrity sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw== +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread@^7.8.0": version "7.8.3" @@ -865,73 +990,80 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz#3acdece695e6b13aaf57fc291d1a800950c71391" - integrity sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g== +"@babel/plugin-syntax-top-level-await@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz#4bbeb8917b54fcf768364e0a81f560e33a3ef57d" + integrity sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-arrow-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz#82776c2ed0cd9e1a49956daeb896024c9473b8b6" - integrity sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg== +"@babel/plugin-transform-arrow-functions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd" + integrity sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-async-to-generator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz#4308fad0d9409d71eafb9b1a6ee35f9d64b64086" - integrity sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ== +"@babel/plugin-transform-async-to-generator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz#41a5017e49eb6f3cda9392a51eef29405b245a37" + integrity sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ== dependencies: - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-remap-async-to-generator" "^7.8.3" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.10.4" -"@babel/plugin-transform-block-scoped-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz#437eec5b799b5852072084b3ae5ef66e8349e8a3" - integrity sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg== +"@babel/plugin-transform-block-scoped-functions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz#1afa595744f75e43a91af73b0d998ecfe4ebc2e8" + integrity sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-block-scoping@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz#97d35dab66857a437c166358b91d09050c868f3a" - integrity sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w== +"@babel/plugin-transform-block-scoping@^7.10.4": + version "7.11.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz#5b7efe98852bef8d652c0b28144cd93a9e4b5215" + integrity sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - lodash "^4.17.13" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-classes@^7.9.0": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.5.tgz#800597ddb8aefc2c293ed27459c1fcc935a26c2c" - integrity sha512-x2kZoIuLC//O5iA7PEvecB105o7TLzZo8ofBVhP79N+DO3jaX+KYfww9TQcfBEZD0nikNyYcGB1IKtRq36rdmg== +"@babel/plugin-transform-classes@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz#405136af2b3e218bc4a1926228bc917ab1a0adc7" + integrity sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA== dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-define-map" "^7.8.3" - "@babel/helper-function-name" "^7.9.5" - "@babel/helper-optimise-call-expression" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.6" - "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-define-map" "^7.10.4" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz#96d0d28b7f7ce4eb5b120bb2e0e943343c86f81b" - integrity sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA== +"@babel/plugin-transform-computed-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz#9ded83a816e82ded28d52d4b4ecbdd810cdfc0eb" + integrity sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-destructuring@^7.8.3": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.9.5.tgz#72c97cf5f38604aea3abf3b935b0e17b1db76a50" - integrity sha512-j3OEsGel8nHL/iusv/mRd5fYZ3DrOxWC82x0ogmdN/vHfAP4MYw+AFKYanzWlktNwikKvlzUV//afBW5FTp17Q== +"@babel/plugin-transform-destructuring@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz#70ddd2b3d1bea83d01509e9bb25ddb3a74fc85e5" + integrity sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-dotall-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz#469c2062105c1eb6a040eaf4fac4b488078395ee" + integrity sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": +"@babel/plugin-transform-dotall-regex@^7.4.4": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" integrity sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw== @@ -939,244 +1071,270 @@ "@babel/helper-create-regexp-features-plugin" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-duplicate-keys@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz#8d12df309aa537f272899c565ea1768e286e21f1" - integrity sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ== +"@babel/plugin-transform-duplicate-keys@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz#697e50c9fee14380fe843d1f306b295617431e47" + integrity sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-exponentiation-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz#581a6d7f56970e06bf51560cd64f5e947b70d7b7" - integrity sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ== +"@babel/plugin-transform-exponentiation-operator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz#5ae338c57f8cf4001bdb35607ae66b92d665af2e" + integrity sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-for-of@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz#0f260e27d3e29cd1bb3128da5e76c761aa6c108e" - integrity sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ== +"@babel/plugin-transform-for-of@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz#c08892e8819d3a5db29031b115af511dbbfebae9" + integrity sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-function-name@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz#279373cb27322aaad67c2683e776dfc47196ed8b" - integrity sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ== +"@babel/plugin-transform-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz#6a467880e0fc9638514ba369111811ddbe2644b7" + integrity sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg== dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz#aef239823d91994ec7b68e55193525d76dbd5dc1" - integrity sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A== +"@babel/plugin-transform-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz#9f42ba0841100a135f22712d0e391c462f571f3c" + integrity sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-member-expression-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz#963fed4b620ac7cbf6029c755424029fa3a40410" - integrity sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA== +"@babel/plugin-transform-member-expression-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz#b1ec44fcf195afcb8db2c62cd8e551c881baf8b7" + integrity sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-modules-amd@^7.9.0": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.6.tgz#8539ec42c153d12ea3836e0e3ac30d5aae7b258e" - integrity sha512-zoT0kgC3EixAyIAU+9vfaUVKTv9IxBDSabgHoUCBP6FqEJ+iNiN7ip7NBKcYqbfUDfuC2mFCbM7vbu4qJgOnDw== +"@babel/plugin-transform-modules-amd@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz#1b9cddaf05d9e88b3aad339cb3e445c4f020a9b1" + integrity sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw== dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-module-transforms" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.9.0": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.6.tgz#64b7474a4279ee588cacd1906695ca721687c277" - integrity sha512-7H25fSlLcn+iYimmsNe3uK1at79IE6SKW9q0/QeEHTMC9MdOZ+4bA+T1VFB5fgOqBWoqlifXRzYD0JPdmIrgSQ== +"@babel/plugin-transform-modules-commonjs@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz#66667c3eeda1ebf7896d41f1f16b17105a2fbca0" + integrity sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w== dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-simple-access" "^7.8.3" + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.9.0": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.6.tgz#207f1461c78a231d5337a92140e52422510d81a4" - integrity sha512-NW5XQuW3N2tTHim8e1b7qGy7s0kZ2OH3m5octc49K1SdAKGxYxeIx7hiIz05kS1R2R+hOWcsr1eYwcGhrdHsrg== +"@babel/plugin-transform-modules-systemjs@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz#6270099c854066681bae9e05f87e1b9cadbe8c85" + integrity sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw== dependencies: - "@babel/helper-hoist-variables" "^7.8.3" - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-hoist-variables" "^7.10.4" + "@babel/helper-module-transforms" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-umd@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz#e909acae276fec280f9b821a5f38e1f08b480697" - integrity sha512-uTWkXkIVtg/JGRSIABdBoMsoIeoHQHPTL0Y2E7xf5Oj7sLqwVsNXOkNk0VJc7vF0IMBsPeikHxFjGe+qmwPtTQ== +"@babel/plugin-transform-modules-umd@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz#9a8481fe81b824654b3a0b65da3df89f3d21839e" + integrity sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA== dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz#a2a72bffa202ac0e2d0506afd0939c5ecbc48c6c" - integrity sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw== +"@babel/plugin-transform-named-capturing-groups-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz#78b4d978810b6f3bcf03f9e318f2fc0ed41aecb6" + integrity sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-create-regexp-features-plugin" "^7.10.4" -"@babel/plugin-transform-new-target@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz#60cc2ae66d85c95ab540eb34babb6434d4c70c43" - integrity sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw== +"@babel/plugin-transform-new-target@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz#9097d753cb7b024cb7381a3b2e52e9513a9c6888" + integrity sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-object-super@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz#ebb6a1e7a86ffa96858bd6ac0102d65944261725" - integrity sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ== +"@babel/plugin-transform-object-super@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz#d7146c4d139433e7a6526f888c667e314a093894" + integrity sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" -"@babel/plugin-transform-parameters@^7.8.7", "@babel/plugin-transform-parameters@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.5.tgz#173b265746f5e15b2afe527eeda65b73623a0795" - integrity sha512-0+1FhHnMfj6lIIhVvS4KGQJeuhe1GI//h5uptK4PvLt+BGBxsoUJbd3/IW002yk//6sZPlFgsG1hY6OHLcy6kA== +"@babel/plugin-transform-parameters@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz#59d339d58d0b1950435f4043e74e2510005e2c4a" + integrity sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw== dependencies: - "@babel/helper-get-function-arity" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-property-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz#33194300d8539c1ed28c62ad5087ba3807b98263" - integrity sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg== +"@babel/plugin-transform-property-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz#f6fe54b6590352298785b83edd815d214c42e3c0" + integrity sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-regenerator@^7.8.7": - version "7.8.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz#5e46a0dca2bee1ad8285eb0527e6abc9c37672f8" - integrity sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA== +"@babel/plugin-transform-regenerator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz#2015e59d839074e76838de2159db421966fd8b63" + integrity sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw== dependencies: regenerator-transform "^0.14.2" -"@babel/plugin-transform-reserved-words@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz#9a0635ac4e665d29b162837dd3cc50745dfdf1f5" - integrity sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-shorthand-properties@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz#28545216e023a832d4d3a1185ed492bcfeac08c8" - integrity sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz#9c8ffe8170fdfb88b114ecb920b82fb6e95fe5e8" - integrity sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-sticky-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz#be7a1290f81dae767475452199e1f76d6175b100" - integrity sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-regex" "^7.8.3" - -"@babel/plugin-transform-template-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz#7bfa4732b455ea6a43130adc0ba767ec0e402a80" - integrity sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-typeof-symbol@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz#ede4062315ce0aaf8a657a920858f1a2f35fc412" - integrity sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-unicode-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz#0cef36e3ba73e5c57273effb182f46b91a1ecaad" - integrity sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/preset-env@7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.0.tgz#a5fc42480e950ae8f5d9f8f2bbc03f52722df3a8" - integrity sha512-712DeRXT6dyKAM/FMbQTV/FvRCms2hPCx+3weRjZ8iQVQWZejWWk1wwG6ViWMyqb/ouBbGOl5b6aCk0+j1NmsQ== - dependencies: - "@babel/compat-data" "^7.9.0" - "@babel/helper-compilation-targets" "^7.8.7" - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-proposal-async-generator-functions" "^7.8.3" - "@babel/plugin-proposal-dynamic-import" "^7.8.3" - "@babel/plugin-proposal-json-strings" "^7.8.3" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-proposal-numeric-separator" "^7.8.3" - "@babel/plugin-proposal-object-rest-spread" "^7.9.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" - "@babel/plugin-proposal-optional-chaining" "^7.9.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" +"@babel/plugin-transform-reserved-words@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz#8f2682bcdcef9ed327e1b0861585d7013f8a54dd" + integrity sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-runtime@7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.11.0.tgz#e27f78eb36f19448636e05c33c90fd9ad9b8bccf" + integrity sha512-LFEsP+t3wkYBlis8w6/kmnd6Kb1dxTd+wGJ8MlxTGzQo//ehtqlVL4S9DNUa53+dtPSQobN2CXx4d81FqC58cw== + dependencies: + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + resolve "^1.8.1" + semver "^5.5.1" + +"@babel/plugin-transform-shorthand-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz#9fd25ec5cdd555bb7f473e5e6ee1c971eede4dd6" + integrity sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-spread@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz#fa84d300f5e4f57752fe41a6d1b3c554f13f17cc" + integrity sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" + +"@babel/plugin-transform-sticky-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz#8f3889ee8657581130a29d9cc91d7c73b7c4a28d" + integrity sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-regex" "^7.10.4" + +"@babel/plugin-transform-template-literals@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz#78bc5d626a6642db3312d9d0f001f5e7639fde8c" + integrity sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-typeof-symbol@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz#9509f1a7eec31c4edbffe137c16cc33ff0bc5bfc" + integrity sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-unicode-escapes@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz#feae523391c7651ddac115dae0a9d06857892007" + integrity sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-unicode-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz#e56d71f9282fac6db09c82742055576d5e6d80a8" + integrity sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/preset-env@7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.11.0.tgz#860ee38f2ce17ad60480c2021ba9689393efb796" + integrity sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg== + dependencies: + "@babel/compat-data" "^7.11.0" + "@babel/helper-compilation-targets" "^7.10.4" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-proposal-async-generator-functions" "^7.10.4" + "@babel/plugin-proposal-class-properties" "^7.10.4" + "@babel/plugin-proposal-dynamic-import" "^7.10.4" + "@babel/plugin-proposal-export-namespace-from" "^7.10.4" + "@babel/plugin-proposal-json-strings" "^7.10.4" + "@babel/plugin-proposal-logical-assignment-operators" "^7.11.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.4" + "@babel/plugin-proposal-numeric-separator" "^7.10.4" + "@babel/plugin-proposal-object-rest-spread" "^7.11.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.10.4" + "@babel/plugin-proposal-optional-chaining" "^7.11.0" + "@babel/plugin-proposal-private-methods" "^7.10.4" + "@babel/plugin-proposal-unicode-property-regex" "^7.10.4" "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-class-properties" "^7.10.4" "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - "@babel/plugin-syntax-numeric-separator" "^7.8.0" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" "@babel/plugin-syntax-optional-chaining" "^7.8.0" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - "@babel/plugin-transform-arrow-functions" "^7.8.3" - "@babel/plugin-transform-async-to-generator" "^7.8.3" - "@babel/plugin-transform-block-scoped-functions" "^7.8.3" - "@babel/plugin-transform-block-scoping" "^7.8.3" - "@babel/plugin-transform-classes" "^7.9.0" - "@babel/plugin-transform-computed-properties" "^7.8.3" - "@babel/plugin-transform-destructuring" "^7.8.3" - "@babel/plugin-transform-dotall-regex" "^7.8.3" - "@babel/plugin-transform-duplicate-keys" "^7.8.3" - "@babel/plugin-transform-exponentiation-operator" "^7.8.3" - "@babel/plugin-transform-for-of" "^7.9.0" - "@babel/plugin-transform-function-name" "^7.8.3" - "@babel/plugin-transform-literals" "^7.8.3" - "@babel/plugin-transform-member-expression-literals" "^7.8.3" - "@babel/plugin-transform-modules-amd" "^7.9.0" - "@babel/plugin-transform-modules-commonjs" "^7.9.0" - "@babel/plugin-transform-modules-systemjs" "^7.9.0" - "@babel/plugin-transform-modules-umd" "^7.9.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" - "@babel/plugin-transform-new-target" "^7.8.3" - "@babel/plugin-transform-object-super" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.8.7" - "@babel/plugin-transform-property-literals" "^7.8.3" - "@babel/plugin-transform-regenerator" "^7.8.7" - "@babel/plugin-transform-reserved-words" "^7.8.3" - "@babel/plugin-transform-shorthand-properties" "^7.8.3" - "@babel/plugin-transform-spread" "^7.8.3" - "@babel/plugin-transform-sticky-regex" "^7.8.3" - "@babel/plugin-transform-template-literals" "^7.8.3" - "@babel/plugin-transform-typeof-symbol" "^7.8.4" - "@babel/plugin-transform-unicode-regex" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.10.4" + "@babel/plugin-transform-arrow-functions" "^7.10.4" + "@babel/plugin-transform-async-to-generator" "^7.10.4" + "@babel/plugin-transform-block-scoped-functions" "^7.10.4" + "@babel/plugin-transform-block-scoping" "^7.10.4" + "@babel/plugin-transform-classes" "^7.10.4" + "@babel/plugin-transform-computed-properties" "^7.10.4" + "@babel/plugin-transform-destructuring" "^7.10.4" + "@babel/plugin-transform-dotall-regex" "^7.10.4" + "@babel/plugin-transform-duplicate-keys" "^7.10.4" + "@babel/plugin-transform-exponentiation-operator" "^7.10.4" + "@babel/plugin-transform-for-of" "^7.10.4" + "@babel/plugin-transform-function-name" "^7.10.4" + "@babel/plugin-transform-literals" "^7.10.4" + "@babel/plugin-transform-member-expression-literals" "^7.10.4" + "@babel/plugin-transform-modules-amd" "^7.10.4" + "@babel/plugin-transform-modules-commonjs" "^7.10.4" + "@babel/plugin-transform-modules-systemjs" "^7.10.4" + "@babel/plugin-transform-modules-umd" "^7.10.4" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.10.4" + "@babel/plugin-transform-new-target" "^7.10.4" + "@babel/plugin-transform-object-super" "^7.10.4" + "@babel/plugin-transform-parameters" "^7.10.4" + "@babel/plugin-transform-property-literals" "^7.10.4" + "@babel/plugin-transform-regenerator" "^7.10.4" + "@babel/plugin-transform-reserved-words" "^7.10.4" + "@babel/plugin-transform-shorthand-properties" "^7.10.4" + "@babel/plugin-transform-spread" "^7.11.0" + "@babel/plugin-transform-sticky-regex" "^7.10.4" + "@babel/plugin-transform-template-literals" "^7.10.4" + "@babel/plugin-transform-typeof-symbol" "^7.10.4" + "@babel/plugin-transform-unicode-escapes" "^7.10.4" + "@babel/plugin-transform-unicode-regex" "^7.10.4" "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.9.0" - browserslist "^4.9.1" + "@babel/types" "^7.11.0" + browserslist "^4.12.0" core-js-compat "^3.6.2" invariant "^2.2.2" levenary "^1.1.1" @@ -1193,20 +1351,12 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/runtime-corejs3@^7.7.4": - version "7.7.6" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.7.6.tgz#5b1044ea11b659d288f77190e19c62da959ed9a3" - integrity sha512-NrRUehqG0sMSCaP+0XV/vOvvjNl4BQOWq3Qys1Q2KTEm5tGMo9h0dHnIzeKerj0a7SIB8LP5kYg/T1raE3FoKQ== - dependencies: - core-js-pure "^3.0.0" - regenerator-runtime "^0.13.2" - -"@babel/runtime@^7.7.4": - version "7.7.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.6.tgz#d18c511121aff1b4f2cd1d452f1bac9601dd830f" - integrity sha512-BWAJxpNVa0QlE5gZdWjSxXtemZyZ9RmrmVozxt3NUXeZhVIJ5ANyqmMc0JDrivBZyxUuQvFxlvH4OWWOogGfUw== +"@babel/runtime@7.11.2": + version "7.11.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736" + integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw== dependencies: - regenerator-runtime "^0.13.2" + regenerator-runtime "^0.13.4" "@babel/runtime@^7.8.4": version "7.9.6" @@ -1215,14 +1365,14 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/template@7.8.6", "@babel/template@^7.8.6": - version "7.8.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" - integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== +"@babel/template@7.10.4", "@babel/template@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" + integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/parser" "^7.8.6" - "@babel/types" "^7.8.6" + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/template@^7.10.1": version "7.10.1" @@ -1233,15 +1383,6 @@ "@babel/parser" "^7.10.1" "@babel/types" "^7.10.1" -"@babel/template@^7.4.0", "@babel/template@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b" - integrity sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.7.4" - "@babel/types" "^7.7.4" - "@babel/template@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.3.tgz#e02ad04fe262a657809327f578056ca15fd4d1b8" @@ -1266,20 +1407,20 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/traverse@^7.4.3", "@babel/traverse@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558" - integrity sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.7.4" - "@babel/helper-function-name" "^7.7.4" - "@babel/helper-split-export-declaration" "^7.7.4" - "@babel/parser" "^7.7.4" - "@babel/types" "^7.7.4" +"@babel/traverse@^7.10.4", "@babel/traverse@^7.11.0": + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.5.tgz#be777b93b518eb6d76ee2e1ea1d143daa11e61c3" + integrity sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.5" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/parser" "^7.11.5" + "@babel/types" "^7.11.5" debug "^4.1.0" globals "^11.1.0" - lodash "^4.17.13" + lodash "^4.17.19" "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4": version "7.8.4" @@ -1296,21 +1437,6 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/traverse@^7.9.0", "@babel/traverse@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.6.tgz#5540d7577697bf619cc57b92aa0f1c231a94f442" - integrity sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.9.6" - "@babel/helper-function-name" "^7.9.5" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/parser" "^7.9.6" - "@babel/types" "^7.9.6" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - "@babel/types@^7.10.1", "@babel/types@^7.10.2": version "7.10.2" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.2.tgz#30283be31cad0dbf6fb00bd40641ca0ea675172d" @@ -1320,16 +1446,16 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@babel/types@^7.4.0", "@babel/types@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193" - integrity sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA== +"@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.11.5": + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d" + integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q== dependencies: - esutils "^2.0.2" - lodash "^4.17.13" + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" to-fast-properties "^2.0.0" -"@babel/types@^7.4.4", "@babel/types@^7.8.6", "@babel/types@^7.9.0", "@babel/types@^7.9.5", "@babel/types@^7.9.6": +"@babel/types@^7.4.4": version "7.9.6" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.6.tgz#2c5502b427251e9de1bd2dff95add646d95cc9f7" integrity sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA== @@ -1352,73 +1478,103 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== -"@jsdevtools/coverage-istanbul-loader@3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.3.tgz#102e414b02ae2f0b3c7fd45a705601e1fd4867c5" - integrity sha512-TAdNkeGB5Fe4Og+ZkAr1Kvn9by2sfL44IAHFtxlh1BA1XJ5cLpO9iSNki5opWESv3l3vSHsZ9BNKuqFKbEbFaA== +"@jsdevtools/coverage-istanbul-loader@3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.5.tgz#2a4bc65d0271df8d4435982db4af35d81754ee26" + integrity sha512-EUCPEkaRPvmHjWAAZkWMT7JDzpw7FKB00WTISaiXsbNOd5hCHg77XLA8sLYLFDo1zepYLo2w7GstN8YBqRXZfA== dependencies: convert-source-map "^1.7.0" - istanbul-lib-instrument "^4.0.1" - loader-utils "^1.4.0" + istanbul-lib-instrument "^4.0.3" + loader-utils "^2.0.0" merge-source-map "^1.1.0" - schema-utils "^2.6.4" + schema-utils "^2.7.0" -"@ngtools/webpack@9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-9.1.4.tgz#8866d8461969662d0860d857aafa5a706877f85d" - integrity sha512-CDlQzMnWraxf/dT3G5L+0N0VniWHWdzjLRP8pWBoyV0xlzWS1yL/lj8Mas2jEIuaUxZ8bi29mE7xa8prqewtBQ== +"@ngtools/webpack@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-10.1.3.tgz#f65c591daab7ed0c3372a115c6a90eba701a2ca1" + integrity sha512-wEg3hY0u+HMAIypClOVnpjYaNwBp+yY0pEb1yNc3Id8bBlw76Y+wk+kGplESelkNQKlfwKDaMFk+7EjGkOrmng== dependencies: - "@angular-devkit/core" "9.1.4" - enhanced-resolve "4.1.1" - rxjs "6.5.4" + "@angular-devkit/core" "10.1.3" + enhanced-resolve "4.3.0" webpack-sources "1.4.3" -"@nguniversal/builders@^9.0.2": - version "9.0.2" - resolved "https://registry.yarnpkg.com/@nguniversal/builders/-/builders-9.0.2.tgz#10b2196f1587b41fa1369b5127ef2998ed1d11cf" - integrity sha512-k7TQktIdC/07KlUszgJjtpyuJArHE3fpiCg2wl4xXGdy3+xj9SpgzcgUhVCrcagjIBux7uTLcOqt12Zk4R43Ig== +"@nguniversal/builders@~10.1.0": + version "10.1.0" + resolved "https://registry.yarnpkg.com/@nguniversal/builders/-/builders-10.1.0.tgz#1097bec29254e399117f0d827e73ef8af888f221" + integrity sha512-4GeQ9S7fVMRbj5bwjCE9VVstrYW3MFrqyIwFcbI/l5Oq1kzWFQ3B6hDX1CVEKQYiofgIi1OWDWAhr/ryrQj1yg== dependencies: - "@angular-devkit/architect" "^0.900.6" - "@angular-devkit/core" "^9.0.6" + "@angular-devkit/architect" "^0.1001.0" + "@angular-devkit/core" "^10.1.0" browser-sync "^2.26.7" guess-parser "^0.4.12" http-proxy-middleware "^1.0.0" - rxjs "^6.5.3" + rxjs "^6.5.5" tree-kill "^1.2.1" -"@nguniversal/common@9.0.1": - version "9.0.1" - resolved "https://registry.yarnpkg.com/@nguniversal/common/-/common-9.0.1.tgz#f200003ef5e98d7bf8d54d43b2d64b163d5042da" - integrity sha512-AprW7oREmywDudrBI1auy4lB6AQFKHLeebdY7vAXjviIEzBDm9Zd1Z59SqFtp+H4Pce8R7tQ3zoXY1n7azCigg== +"@nguniversal/common@10.1.0": + version "10.1.0" + resolved "https://registry.yarnpkg.com/@nguniversal/common/-/common-10.1.0.tgz#7104f598b2a6eee078dfc1e0309cb9ea261e7da7" + integrity sha512-AIfLORs+LLHx9d+8kRNDq+GZj/2ToyXgg5Boi2RfgUhV5Rywey082XRlFmPwyVHxltYJzoMPeNWxzV6hrSMCzA== + dependencies: + tslib "^2.0.0" -"@nguniversal/express-engine@~9.0.1": - version "9.0.1" - resolved "https://registry.yarnpkg.com/@nguniversal/express-engine/-/express-engine-9.0.1.tgz#109078bda23093dbdfec7a722c360a4e394931fb" - integrity sha512-uICu/CVrKuRYKUhpn91tRoERRhorDH038zyUsQt3yqsKV5BXyclr+H0lHh94dXyi+W0RKmksvzGNshwc4IWnUA== +"@nguniversal/express-engine@~10.1.0": + version "10.1.0" + resolved "https://registry.yarnpkg.com/@nguniversal/express-engine/-/express-engine-10.1.0.tgz#b1595751eb6acfa02b65e25e9c9ffbe66baab2f5" + integrity sha512-UYQB8662Qnx9Y2TblZmC8QbfAZtiCE6OeLNdwWIz8rVY9jhWi4P5SFb0slvcPMyPL5JAb+FHHOKjsH1NJztsCQ== dependencies: - "@nguniversal/common" "9.0.1" + "@nguniversal/common" "10.1.0" + tslib "^2.0.0" -"@schematics/angular@9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-9.1.4.tgz#01908a9b8c97db204fb1395e202aebd38b789bad" - integrity sha512-7nbiYBRgXc+f0sa5iXTcF6/VMy/Xq0wyKKnDFiLCb2aFYR7EXRHWF2GuwDIg2bvFugLuCBDoNnXeddLE1TXGWg== +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== dependencies: - "@angular-devkit/core" "9.1.4" - "@angular-devkit/schematics" "9.1.4" + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" -"@schematics/update@0.901.4": - version "0.901.4" - resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.901.4.tgz#665214fb6daec3162d428aead5fb4937a4508dd3" - integrity sha512-jCtZY2Fbj502gKN5gdu1brnRy/ssyzTrWm69Ty73V+t8uL7nLr+/hny/VBJ8CiQnKQvxcgVl1xgvI1cXzpysVA== +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + +"@npmcli/move-file@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.0.1.tgz#de103070dac0f48ce49cf6693c23af59c0f70464" + integrity sha512-Uv6h1sT+0DrblvIrolFtbvM1FgWm+/sy4B3pvLp67Zys+thcukzS5ekn7HsZFGpWP4Q3fYJCljbWQE/XivMRLw== + dependencies: + mkdirp "^1.0.4" + +"@schematics/angular@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-10.1.3.tgz#8b39f2d934043c68b55495bc6e44705c6fa7ef8c" + integrity sha512-X3tNnpfF/jkl1KcyCC8PaOYogQlTZ9s7Yuz0va0DAVOptIqorpf8e6+lY0PPLKshaK9TSiFUcQ8SYYnjAVKcdA== + dependencies: + "@angular-devkit/core" "10.1.3" + "@angular-devkit/schematics" "10.1.3" + jsonc-parser "2.3.0" + +"@schematics/update@0.1001.3": + version "0.1001.3" + resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.1001.3.tgz#7b8e2c166948c096cb46d9d7c712b3f9fac044e0" + integrity sha512-ah4YHjEXACmpX0i3cAn5OguH5S430HD+zbxlMu4AC93A8W52ll97vqvUVF8NLZ6RKcOV/8tXmzgzvJDe07i8yQ== dependencies: - "@angular-devkit/core" "9.1.4" - "@angular-devkit/schematics" "9.1.4" + "@angular-devkit/core" "10.1.3" + "@angular-devkit/schematics" "10.1.3" "@yarnpkg/lockfile" "1.1.0" ini "1.3.5" npm-package-arg "^8.0.0" pacote "9.5.12" - rxjs "6.5.4" - semver "7.1.3" + semver "7.3.2" semver-intersect "1.4.0" "@types/angular-animate@1.5.10": @@ -1428,31 +1584,31 @@ dependencies: "@types/angular" "*" -"@types/angular-mocks@1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@types/angular-mocks/-/angular-mocks-1.6.0.tgz#bd32f55b678c239880d2d0d9a3a79b5cad45547e" - integrity sha512-rZRxzmeUJVvNS7uWFEFyK5f3/rXbDWhL7y3StHr5cZFgSN1BEfGEByEr/QKwrbPs5rY+kQiFLBUTcvMrzrpekg== +"@types/angular-mocks@1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@types/angular-mocks/-/angular-mocks-1.7.0.tgz#310d999a3c47c10ecd8eef466b5861df84799429" + integrity sha512-MeT5vxWBx4Ny5/sNZJjpZdv4K2KGwqQYiRQQZctan1TTaNyiVlFRYbcmheolhM4KKbTWmoxTVeuvGzniTDg1kw== dependencies: "@types/angular" "*" -"@types/angular-resource@1.5.14": - version "1.5.14" - resolved "https://registry.yarnpkg.com/@types/angular-resource/-/angular-resource-1.5.14.tgz#902f34e8c98f708ae99493c6d416b39b4a22d9fe" - integrity sha512-dpP5DHIape+lMlLPzfOrkpkgjiDrT2lYcPY2Wrk2FTUEBlOZkR1sM+I8oR1S/ZuKCDzTxOi0UmLg+0MG7zcFyA== +"@types/angular-resource@1.5.16": + version "1.5.16" + resolved "https://registry.yarnpkg.com/@types/angular-resource/-/angular-resource-1.5.16.tgz#e32faef37c9e0557f5042b081746a666118af547" + integrity sha512-EJGp5Qxa+w2AHGW8Y+UUsYTTF+Kh68sFhI9YzXzM7n8pB91VGWynELQ/R3rTVE2xtxyiu+F2WU2mOQC4NUvWrA== dependencies: "@types/angular" "*" -"@types/angular-route@1.3.5": - version "1.3.5" - resolved "https://registry.yarnpkg.com/@types/angular-route/-/angular-route-1.3.5.tgz#78b8e0b069d5efe55ec7072461f4e2f6ae20767b" - integrity sha512-/jvK2s1rhUaOVimYpTEg9cj9IYL+Toq05FlBYDw/hMrZNb2SrkRd2DO3Lus9SZy9URs661gtM/NyQwbBUUWWKw== +"@types/angular-route@1.7.1": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@types/angular-route/-/angular-route-1.7.1.tgz#0f545189ff51afc74afbcdde17b56a277963d51b" + integrity sha512-5N5nfUYTEf5InmrhGU5qtvBOHOq6uvv1olJR5fd6Eq5YFT+cdjrr0nklBaFfulAsF0Cd8y7IQipgaUSwWsATYQ== dependencies: "@types/angular" "*" -"@types/angular@*", "@types/angular@1.6.47": - version "1.6.47" - resolved "https://registry.yarnpkg.com/@types/angular/-/angular-1.6.47.tgz#f7a31279a02c0892ed9aa76aae2da1b17791bacd" - integrity sha512-nHmD3F1eDX77z6n4KBuRIRCtl+AYUDPasS6gpF3+W4gNZsW4krCsDNLrONR4kJBqRf5I2on/FffKwFrBJyX6LA== +"@types/angular@*", "@types/angular@1.7.3": + version "1.7.3" + resolved "https://registry.yarnpkg.com/@types/angular/-/angular-1.7.3.tgz#138c2f2f688e9dcb413c6052d9483d773ce7f627" + integrity sha512-rr40P9yHTlLuY6y+PUfwHeoBWO8uEJTazcs89o83fheyH/b9OZW7p7EsvFMriCPam3p6VSD57zkgn+nAQCvfUw== "@types/body-parser@*": version "1.19.0" @@ -1492,13 +1648,14 @@ "@types/node" "*" "@types/range-parser" "*" -"@types/express@^4.17.0": - version "4.17.3" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.3.tgz#38e4458ce2067873b09a73908df488870c303bd9" - integrity sha512-I8cGRJj3pyOLs/HndoP+25vOqhqWkAZsWMEmq1qXy/b/M3ppufecUwaK2/TVDVxcV61/iSdhykUjQQ2DLSrTdg== +"@types/express@^4.17.8": + version "4.17.8" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.8.tgz#3df4293293317e61c60137d273a2e96cd8d5f27a" + integrity sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ== dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "*" + "@types/qs" "*" "@types/serve-static" "*" "@types/glob@^7.1.1": @@ -1533,10 +1690,10 @@ dependencies: "@types/jasmine" "*" -"@types/jquery@3.3.28": - version "3.3.28" - resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.3.28.tgz#e4e4e1a72a890b9d5fce34019d961265dd1394c4" - integrity sha512-6+0asQBU38H5kdoKvxVGE7fY8JREBgQsxONw0na0noV9D3JLN2+odBPKkTvRcLW20xSNiP8BH0nyl+8PcIHYNw== +"@types/jquery@3.5.1": + version "3.5.1" + resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.1.tgz#cebb057acf5071c40e439f30e840c57a30d406c3" + integrity sha512-Tyctjh56U7eX2b9udu3wG853ASYP0uagChJcQJXLUXEU6C/JiW5qt5dl8ao01VRj1i5pgXPAf8f1mq4+FDLRQg== dependencies: "@types/sizzle" "*" @@ -1549,6 +1706,11 @@ "@types/parse5" "*" "@types/tough-cookie" "*" +"@types/json-schema@^7.0.5": + version "7.0.6" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" + integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== + "@types/mime@*": version "2.0.0" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.0.tgz#5a7306e367c539b9f6543499de8dd519fac37a8b" @@ -1596,6 +1758,11 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== +"@types/qs@*": + version "6.9.5" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.5.tgz#434711bdd49eb5ee69d90c1d67c354a9a8ecb18b" + integrity sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ== + "@types/range-parser@*": version "1.2.3" resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" @@ -1643,156 +1810,155 @@ dependencies: "@types/node" "*" -"@webassemblyjs/ast@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" - integrity sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ== +"@webassemblyjs/ast@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" + integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== dependencies: - "@webassemblyjs/helper-module-context" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/wast-parser" "1.8.5" + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" -"@webassemblyjs/floating-point-hex-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz#1ba926a2923613edce496fd5b02e8ce8a5f49721" - integrity sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ== +"@webassemblyjs/floating-point-hex-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" + integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== -"@webassemblyjs/helper-api-error@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz#c49dad22f645227c5edb610bdb9697f1aab721f7" - integrity sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA== +"@webassemblyjs/helper-api-error@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" + integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== -"@webassemblyjs/helper-buffer@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz#fea93e429863dd5e4338555f42292385a653f204" - integrity sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q== +"@webassemblyjs/helper-buffer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" + integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== -"@webassemblyjs/helper-code-frame@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz#9a740ff48e3faa3022b1dff54423df9aa293c25e" - integrity sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ== +"@webassemblyjs/helper-code-frame@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" + integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== dependencies: - "@webassemblyjs/wast-printer" "1.8.5" + "@webassemblyjs/wast-printer" "1.9.0" -"@webassemblyjs/helper-fsm@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz#ba0b7d3b3f7e4733da6059c9332275d860702452" - integrity sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow== +"@webassemblyjs/helper-fsm@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" + integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== -"@webassemblyjs/helper-module-context@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz#def4b9927b0101dc8cbbd8d1edb5b7b9c82eb245" - integrity sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g== +"@webassemblyjs/helper-module-context@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" + integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== dependencies: - "@webassemblyjs/ast" "1.8.5" - mamacro "^0.0.3" + "@webassemblyjs/ast" "1.9.0" -"@webassemblyjs/helper-wasm-bytecode@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz#537a750eddf5c1e932f3744206551c91c1b93e61" - integrity sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ== +"@webassemblyjs/helper-wasm-bytecode@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" + integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== -"@webassemblyjs/helper-wasm-section@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz#74ca6a6bcbe19e50a3b6b462847e69503e6bfcbf" - integrity sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA== +"@webassemblyjs/helper-wasm-section@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" + integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" -"@webassemblyjs/ieee754@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz#712329dbef240f36bf57bd2f7b8fb9bf4154421e" - integrity sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g== +"@webassemblyjs/ieee754@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" + integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.8.5.tgz#044edeb34ea679f3e04cd4fd9824d5e35767ae10" - integrity sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A== +"@webassemblyjs/leb128@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" + integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.8.5.tgz#a8bf3b5d8ffe986c7c1e373ccbdc2a0915f0cedc" - integrity sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw== +"@webassemblyjs/utf8@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" + integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== -"@webassemblyjs/wasm-edit@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz#962da12aa5acc1c131c81c4232991c82ce56e01a" - integrity sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/helper-wasm-section" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - "@webassemblyjs/wasm-opt" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" - "@webassemblyjs/wast-printer" "1.8.5" - -"@webassemblyjs/wasm-gen@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz#54840766c2c1002eb64ed1abe720aded714f98bc" - integrity sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg== +"@webassemblyjs/wasm-edit@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" + integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/helper-wasm-section" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-opt" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + "@webassemblyjs/wast-printer" "1.9.0" + +"@webassemblyjs/wasm-gen@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" + integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/ieee754" "1.8.5" - "@webassemblyjs/leb128" "1.8.5" - "@webassemblyjs/utf8" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" -"@webassemblyjs/wasm-opt@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz#b24d9f6ba50394af1349f510afa8ffcb8a63d264" - integrity sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q== +"@webassemblyjs/wasm-opt@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" + integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-buffer" "1.8.5" - "@webassemblyjs/wasm-gen" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-buffer" "1.9.0" + "@webassemblyjs/wasm-gen" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" -"@webassemblyjs/wasm-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz#21576f0ec88b91427357b8536383668ef7c66b8d" - integrity sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw== +"@webassemblyjs/wasm-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" + integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-api-error" "1.8.5" - "@webassemblyjs/helper-wasm-bytecode" "1.8.5" - "@webassemblyjs/ieee754" "1.8.5" - "@webassemblyjs/leb128" "1.8.5" - "@webassemblyjs/utf8" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-wasm-bytecode" "1.9.0" + "@webassemblyjs/ieee754" "1.9.0" + "@webassemblyjs/leb128" "1.9.0" + "@webassemblyjs/utf8" "1.9.0" -"@webassemblyjs/wast-parser@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz#e10eecd542d0e7bd394f6827c49f3df6d4eefb8c" - integrity sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg== - dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/floating-point-hex-parser" "1.8.5" - "@webassemblyjs/helper-api-error" "1.8.5" - "@webassemblyjs/helper-code-frame" "1.8.5" - "@webassemblyjs/helper-fsm" "1.8.5" +"@webassemblyjs/wast-parser@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" + integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== + dependencies: + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/floating-point-hex-parser" "1.9.0" + "@webassemblyjs/helper-api-error" "1.9.0" + "@webassemblyjs/helper-code-frame" "1.9.0" + "@webassemblyjs/helper-fsm" "1.9.0" "@xtuc/long" "4.2.2" -"@webassemblyjs/wast-printer@1.8.5": - version "1.8.5" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz#114bbc481fd10ca0e23b3560fa812748b0bae5bc" - integrity sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg== +"@webassemblyjs/wast-printer@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" + integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/wast-parser" "1.8.5" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/wast-parser" "1.9.0" "@xtuc/long" "4.2.2" -"@webcomponents/custom-elements@^1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@webcomponents/custom-elements/-/custom-elements-1.4.1.tgz#9803aaa2286a13a4ba200a7a2ea767871598eb60" - integrity sha512-vNCS1+3sxJOpoIsBjUQiXjGLngakEAGOD5Ale+6ikg6OZG5qI5O39frm3raPhud/IwnF4vec5ags05YBsgzcuA== +"@webcomponents/custom-elements@^1.4.2": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@webcomponents/custom-elements/-/custom-elements-1.4.2.tgz#a6fe80325c2b09e88e988c712144bc667c565499" + integrity sha512-bLw2XH9+2NBwmn7BI6WA2oIo2eOfBpl+GjAqkF/qnkZ8kq3HY5tKYTxtKowWALAferTp3wKD8W6FSn5OyK+rtQ== "@wessberg/ts-evaluator@0.0.25": version "0.0.25" @@ -1886,16 +2052,27 @@ acorn@^6.1.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== -acorn@^6.2.1: - version "6.4.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" - integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== +acorn@^6.4.1: + version "6.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" + integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== acorn@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf" integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg== +adjust-sourcemap-loader@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/adjust-sourcemap-loader/-/adjust-sourcemap-loader-2.0.0.tgz#6471143af75ec02334b219f54bc7970c52fb29a4" + integrity sha512-4hFsTsn58+YjrU9qKzML2JSSDqKvN8mUGQ0nNIrfPi8hmIONT4L3uUaT6MKdMsZ9AjsU6D2xDkZxCkbQPxChrA== + dependencies: + assert "1.4.1" + camelcase "5.0.0" + loader-utils "1.2.3" + object-path "0.11.4" + regex-parser "2.2.10" + adm-zip@^0.4.9: version "0.4.13" resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.13.tgz#597e2f8cc3672151e1307d3e95cddbc75672314a" @@ -1955,20 +2132,15 @@ ajv-keywords@^3.4.1: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== -ajv@6.10.2, ajv@^6.10.2: - version "6.10.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" - integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== - dependencies: - fast-deep-equal "^2.0.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" +ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== -ajv@6.12.0, ajv@^6.5.5: - version "6.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.0.tgz#06d60b96d87b8454a5adaba86e7854da629db4b7" - integrity sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw== +ajv@6.12.4: + version "6.12.4" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234" + integrity sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" @@ -1982,15 +2154,6 @@ ajv@^4.9.1: co "^4.6.0" json-stable-stringify "^1.0.1" -ajv@^5.1.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.3.0.tgz#4414ff74a50879c208ee5fdc826e32c303549eda" - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - ajv@^5.3.0: version "5.5.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" @@ -2009,6 +2172,16 @@ ajv@^6.1.0: json-schema-traverse "^0.3.0" uri-js "^3.0.2" +ajv@^6.10.2: + version "6.10.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" + integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + ajv@^6.12.0: version "6.12.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" @@ -2019,6 +2192,26 @@ ajv@^6.12.0: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^6.12.4: + version "6.12.5" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.5.tgz#19b0e8bae8f476e5ba666300387775fb1a00a4da" + integrity sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^6.5.5: + version "6.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.0.tgz#06d60b96d87b8454a5adaba86e7854da629db4b7" + integrity sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + alphanum-sort@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" @@ -2029,15 +2222,15 @@ angular-in-memory-web-api@~0.11.0: resolved "https://registry.yarnpkg.com/angular-in-memory-web-api/-/angular-in-memory-web-api-0.11.0.tgz#46e4ad896b36d669f36801fc8cafa7db8278d078" integrity sha512-QV1qYHm+Zd+wrvlcPLnAcqqGpOmCN1EUj4rRuYHpek8+QqFFdxBNuPZOJCKvU7I97z5QSKHsdc6PNKlpUQr3UA== -angular-route@1.7.9: - version "1.7.9" - resolved "https://registry.yarnpkg.com/angular-route/-/angular-route-1.7.9.tgz#f9910a2af0ba3ad7a969c5dd369b8360d0d5e4ef" - integrity sha512-vRoj5hzdQtWbODhWJqDzD1iNOEfCKshO6GFBuPVV7RHlPjzIc4R2dHCc7Qiv/8F3LDxJDohc6vSnTDMLHuaqeA== +angular-route@1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/angular-route/-/angular-route-1.8.0.tgz#cb8066c5d34284ffd6a15ac7be1b3d51c5ad7bb2" + integrity sha512-ORvXAdVfCCA6XFwyjSkVQFFGufj0mNGiCvBR93Qsii8+7t/6Ioy6wheUoCj1x4NWUv7hAq3nYYGCVO6QEKb1BQ== -angular@1.7.9: - version "1.7.9" - resolved "https://registry.yarnpkg.com/angular/-/angular-1.7.9.tgz#e52616e8701c17724c3c238cfe4f9446fd570bc4" - integrity sha512-5se7ZpcOtu0MBFlzGv5dsM1quQDoDeUTwZrWjGtTNA7O88cD8TEk5IEKCTDa3uECV9XnvKREVUr7du1ACiWGFQ== +angular@1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/angular/-/angular-1.8.0.tgz#b1ec179887869215cab6dfd0df2e42caa65b1b51" + integrity sha512-VdaMx+Qk0Skla7B5gw77a8hzlcOakwF8mjlW13DpIWIDlfqwAbSSLfd8N/qZnzEmQF4jC4iofInd3gE7vL8ZZg== ansi-colors@4.1.1: version "4.1.1" @@ -2063,10 +2256,6 @@ ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - ansi-regex@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" @@ -2123,16 +2312,10 @@ anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" -app-root-path@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.2.1.tgz#d0df4a682ee408273583d43f6f79e9892624bc9a" - integrity sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA== - -append-transform@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab" - dependencies: - default-require-extensions "^2.0.0" +app-root-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-3.0.0.tgz#210b6f43873227e18a4b810a032283311555d5ad" + integrity sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw== aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" @@ -2164,6 +2347,11 @@ aria-query@^3.0.0: ast-types-flow "0.0.7" commander "^2.11.0" +arity-n@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/arity-n/-/arity-n-1.0.4.tgz#d9e76b11733e08569c0847ae7b39b2860b30b745" + integrity sha1-2edrEXM+CFacCEeuezmyhgswt0U= + arr-diff@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" @@ -2196,6 +2384,11 @@ array-union@^1.0.1: dependencies: array-uniq "^1.0.1" +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" @@ -2216,11 +2409,11 @@ arraybuffer.slice@~0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" -arrify@^1.0.0, arrify@^1.0.1: +arrify@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" -asap@^2.0.0, asap@~2.0.3: +asap@^2.0.0: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" @@ -2244,7 +2437,7 @@ assert-plus@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" -assert@^1.1.1: +assert@1.4.1, assert@^1.1.1: version "1.4.1" resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" dependencies: @@ -2280,7 +2473,7 @@ async@1.5.2, async@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" -async@^2.5.0, async@^2.6.1: +async@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" dependencies: @@ -2306,18 +2499,18 @@ atob@^2.1.1: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -autoprefixer@9.7.4: - version "9.7.4" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.4.tgz#f8bf3e06707d047f0641d87aee8cfb174b2a5378" - integrity sha512-g0Ya30YrMBAEZk60lp+qfX5YQllG+S5W3GYCFvyHTvhOki0AEQJLPEcIuGRsqVwLi8FvXPVtwTGhfr38hVpm0g== +autoprefixer@9.8.6: + version "9.8.6" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f" + integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg== dependencies: - browserslist "^4.8.3" - caniuse-lite "^1.0.30001020" - chalk "^2.4.2" + browserslist "^4.12.0" + caniuse-lite "^1.0.30001109" + colorette "^1.2.1" normalize-range "^0.1.2" num2fraction "^1.2.2" - postcss "^7.0.26" - postcss-value-parser "^4.0.2" + postcss "^7.0.32" + postcss-value-parser "^4.1.0" aws-sign2@~0.6.0: version "0.6.0" @@ -2327,7 +2520,7 @@ aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" -aws4@^1.2.1, aws4@^1.6.0: +aws4@^1.2.1: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" @@ -2343,23 +2536,23 @@ axios@0.19.0: follow-redirects "1.5.10" is-buffer "^2.0.2" -axobject-query@^2.0.2: - version "2.1.1" - resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.1.1.tgz#2a3b1271ec722d48a4cd4b3fcc20c853326a49a7" - integrity sha512-lF98xa/yvy6j3fBHAgQXIYl+J4eZadOSqsPojemUqClzNbBV38wWGpUbQbVEyf4eUF5yF7eHmGgGA2JiHyjeqw== +axobject-query@2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.0.2.tgz#ea187abe5b9002b377f925d8bf7d1c561adf38f9" + integrity sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww== dependencies: - "@babel/runtime" "^7.7.4" - "@babel/runtime-corejs3" "^7.7.4" + ast-types-flow "0.0.7" -babel-loader@8.0.6: - version "8.0.6" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.6.tgz#e33bdb6f362b03f4bb141a0c21ab87c501b70dfb" - integrity sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw== +babel-loader@8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3" + integrity sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw== dependencies: - find-cache-dir "^2.0.0" - loader-utils "^1.0.2" - mkdirp "^0.5.1" + find-cache-dir "^2.1.0" + loader-utils "^1.4.0" + mkdirp "^0.5.3" pify "^4.0.1" + schema-utils "^2.6.5" babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" @@ -2548,18 +2741,6 @@ boom@2.x.x: dependencies: hoek "2.x.x" -boom@4.x.x: - version "4.3.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" - dependencies: - hoek "4.x.x" - -boom@5.x.x: - version "5.2.0" - resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" - dependencies: - hoek "4.x.x" - brace-expansion@^1.1.7: version "1.1.8" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" @@ -2782,7 +2963,7 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@^4.0.0, browserslist@^4.8.3: +browserslist@^4.0.0: version "4.8.7" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.7.tgz#ec8301ff415e6a42c949d0e66b405eb539c532d0" integrity sha512-gFOnZNYBHrEyUML0xr5NJ6edFaaKbTFX9S9kQHlYfCP0Rit/boRIz4G+Avq6/4haEKJXdGGUnoolx+5MWW2BoA== @@ -2791,7 +2972,17 @@ browserslist@^4.0.0, browserslist@^4.8.3: electron-to-chromium "^1.3.349" node-releases "^1.1.49" -browserslist@^4.11.1, browserslist@^4.8.5: +browserslist@^4.12.0: + version "4.14.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.3.tgz#381f9e7f13794b2eb17e1761b4f118e8ae665a53" + integrity sha512-GcZPC5+YqyPO4SFnz48/B0YaCwS47Q9iPChRGi6t7HhflKBcINzFrJvRfC+jp30sRMKxF+d4EHGs27Z0XP1NaQ== + dependencies: + caniuse-lite "^1.0.30001131" + electron-to-chromium "^1.3.570" + escalade "^3.1.0" + node-releases "^1.1.61" + +browserslist@^4.8.5: version "4.12.0" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.12.0.tgz#06c6d5715a1ede6c51fc39ff67fd647f740b656d" integrity sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg== @@ -2888,30 +3079,30 @@ bytes@3.1.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== -cacache@15.0.0: - version "15.0.0" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.0.tgz#133b59edbd2a37ea8ef2d54964c6f247e47e5059" - integrity sha512-L0JpXHhplbJSiDGzyJJnJCTL7er7NzbBgxzVqLswEb4bO91Zbv17OUMuUeu/q0ZwKn3V+1HM4wb9tO4eVE/K8g== +cacache@15.0.5, cacache@^15.0.4, cacache@^15.0.5: + version "15.0.5" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.5.tgz#69162833da29170d6732334643c60e005f5f17d0" + integrity sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A== dependencies: - chownr "^1.1.2" + "@npmcli/move-file" "^1.0.1" + chownr "^2.0.0" fs-minipass "^2.0.0" glob "^7.1.4" infer-owner "^1.0.4" - lru-cache "^5.1.1" + lru-cache "^6.0.0" minipass "^3.1.1" minipass-collect "^1.0.2" minipass-flush "^1.0.5" minipass-pipeline "^1.2.2" mkdirp "^1.0.3" - move-concurrently "^1.0.1" - p-map "^3.0.0" + p-map "^4.0.0" promise-inflight "^1.0.1" - rimraf "^2.7.1" + rimraf "^3.0.2" ssri "^8.0.0" - tar "^6.0.1" + tar "^6.0.2" unique-filename "^1.1.1" -cacache@^12.0.0, cacache@^12.0.2, cacache@^12.0.3: +cacache@^12.0.0, cacache@^12.0.2: version "12.0.3" resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390" integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw== @@ -2932,30 +3123,6 @@ cacache@^12.0.0, cacache@^12.0.2, cacache@^12.0.3: unique-filename "^1.1.1" y18n "^4.0.0" -cacache@^13.0.1: - version "13.0.1" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-13.0.1.tgz#a8000c21697089082f85287a1aec6e382024a71c" - integrity sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w== - dependencies: - chownr "^1.1.2" - figgy-pudding "^3.5.1" - fs-minipass "^2.0.0" - glob "^7.1.4" - graceful-fs "^4.2.2" - infer-owner "^1.0.4" - lru-cache "^5.1.1" - minipass "^3.0.0" - minipass-collect "^1.0.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.2" - mkdirp "^0.5.1" - move-concurrently "^1.0.1" - p-map "^3.0.0" - promise-inflight "^1.0.1" - rimraf "^2.7.1" - ssri "^7.0.0" - unique-filename "^1.1.1" - cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -2993,6 +3160,16 @@ callsites@^2.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= +camelcase@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" + integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA== + +camelcase@5.3.1, camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + camelcase@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" @@ -3001,10 +3178,10 @@ camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" -camelcase@^5.0.0, camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== +camelcase@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e" + integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w== caniuse-api@^3.0.0: version "3.0.0" @@ -3021,16 +3198,21 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001027: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001030.tgz#78076c4c6d67d3e41d6eb9399853fb27fe6e44ee" integrity sha512-QGK0W4Ft/Ac+zTjEiRJfwDNATvS3fodDczBXrH42784kcfqcDKpEPfN08N0HQjrAp8He/Jw8QiSS9QRn7XAbUw== -caniuse-lite@^1.0.30001020, caniuse-lite@^1.0.30001043: - version "1.0.30001051" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001051.tgz#8e944abf9c796bc7ea0bec3c3688a250561fc9ac" - integrity sha512-sw8UUnTlRevawTMZKN7vpfwSjCBVoiMPlYd8oT2VwNylyPCBdMAUmLGUApnYYTtIm5JXsQegUAY7GPHqgfDzjw== - caniuse-lite@^1.0.30001030, caniuse-lite@^1.0.30001032: version "1.0.30001035" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001035.tgz#2bb53b8aa4716b2ed08e088d4dc816a5fe089a1e" integrity sha512-C1ZxgkuA4/bUEdMbU5WrGY4+UhMFFiXrgNAfxiMIqWgFTWfv/xsZCS2xEHT2LMq7xAZfuAnu6mcqyDl0ZR6wLQ== +caniuse-lite@^1.0.30001043: + version "1.0.30001051" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001051.tgz#8e944abf9c796bc7ea0bec3c3688a250561fc9ac" + integrity sha512-sw8UUnTlRevawTMZKN7vpfwSjCBVoiMPlYd8oT2VwNylyPCBdMAUmLGUApnYYTtIm5JXsQegUAY7GPHqgfDzjw== + +caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001131: + version "1.0.30001133" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001133.tgz#ec564c5495311299eb05245e252d589a84acd95e" + integrity sha512-s3XAUFaC/ntDb1O3lcw9K8MPeOW7KO3z9+GzAoBxfz1B0VdacXPMKgFUtG4KIsgmnbexmi013s9miVu4h+qMHw== + canonical-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/canonical-path/-/canonical-path-1.0.0.tgz#fcb470c23958def85081856be7a86e904f180d1d" @@ -3083,6 +3265,14 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^4.0.0, chalk@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -3117,24 +3307,6 @@ chokidar@1.7.0: optionalDependencies: fsevents "~2.1.1" -chokidar@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.3.tgz#dcbd4f6cbb2a55b4799ba8a840ac527e5f4b1176" - dependencies: - anymatch "^2.0.0" - async-each "^1.0.0" - braces "^2.3.0" - glob-parent "^3.1.0" - inherits "^2.0.1" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^2.1.1" - path-is-absolute "^1.0.0" - readdirp "^2.0.0" - upath "^1.0.0" - optionalDependencies: - fsevents "^1.1.2" - chokidar@^2.0.4, chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" @@ -3154,6 +3326,21 @@ chokidar@^2.0.4, chokidar@^2.1.8: optionalDependencies: fsevents "^1.2.7" +chokidar@^3.4.1: + version "3.4.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.2.tgz#38dc8e658dec3809741eb3ef7bb0a47fe424232d" + integrity sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.4.0" + optionalDependencies: + fsevents "~2.1.2" + chownr@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" @@ -3213,14 +3400,15 @@ cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" -cli-spinners@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.2.0.tgz#e8b988d9206c692302d8ee834e7a85c0144d8f77" - integrity sha512-tgU3fKwzYjiLEQgPMD9Jt+JjHVL9kW93FiIMX/l7rivvOD4/LL0Mf7gda3+4U2KJBloybwgj5KEoQgGRioMiKQ== +cli-spinners@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.4.0.tgz#c6256db216b878cfba4720e719cec7cf72685d7f" + integrity sha512-sJAofoarcm76ZGpuooaO0eDy8saEy+YoZBLjC4h8srt4jeBnkYeOgqxgsJQTpyt2LjI5PTfLJHSL+41Yu4fEJA== -cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" +cli-width@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" + integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== cliui@^3.0.3, cliui@^3.2.0: version "3.2.0" @@ -3230,14 +3418,6 @@ cliui@^3.0.3, cliui@^3.2.0: strip-ansi "^3.0.1" wrap-ansi "^2.0.0" -cliui@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.0.0.tgz#743d4650e05f36d1ed2575b59638d87322bfbbcc" - dependencies: - string-width "^2.1.1" - strip-ansi "^4.0.0" - wrap-ansi "^2.0.0" - cliui@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" @@ -3256,24 +3436,11 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" -clone-deep@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" - integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== - dependencies: - is-plain-object "^2.0.4" - kind-of "^6.0.2" - shallow-clone "^3.0.0" - clone@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= -clone@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb" - clone@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" @@ -3295,20 +3462,25 @@ code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" -codelyzer@^5.1.2: - version "5.2.0" - resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-5.2.0.tgz#b0ee573a12779c996090e596c5c1755479d83758" - integrity sha512-izfUfhEOOgAizszPlEDxo71DK/C4wprZw0vkY6UWcOSTQvN1JyfXf9DXwaV7WX+/JC+hH0ShXfdtGLA9Rca7LA== +codelyzer@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-6.0.0.tgz#50c98581cc2890e0e9a9f93878dc317115d836ed" + integrity sha512-edJIQCIcxD9DhVSyBEdJ38AbLikm515Wl91t5RDGNT88uA6uQdTm4phTWfn9JhzAI8kXNUcfYyAE90lJElpGtA== dependencies: - app-root-path "^2.2.1" + "@angular/compiler" "9.0.0" + "@angular/core" "9.0.0" + app-root-path "^3.0.0" aria-query "^3.0.0" - axobject-query "^2.0.2" + axobject-query "2.0.2" css-selector-tokenizer "^0.7.1" cssauron "^1.4.0" damerau-levenshtein "^1.0.4" + rxjs "^6.5.3" semver-dsl "^1.0.1" source-map "^0.5.7" sprintf-js "^1.1.2" + tslib "^1.10.0" + zone.js "~0.10.3" collection-visit@^1.0.0: version "1.0.0" @@ -3362,15 +3534,20 @@ color@^3.0.0: color-convert "^1.9.1" color-string "^1.5.2" -colors@1.1.2, colors@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" +colorette@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" + integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw== -colors@^1.3.3: +colors@1.4.0, colors@^1.3.3: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== +colors@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" + combined-stream@1.0.6, combined-stream@~1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" @@ -3383,7 +3560,7 @@ combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" -commander@^2.11.0, commander@^2.20.0, commander@~2.20.3: +commander@^2.11.0, commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -3400,11 +3577,6 @@ commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" -compare-versions@^3.4.0: - version "3.5.1" - resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.5.1.tgz#26e1f5cf0d48a77eced5046b9f67b6b61075a393" - integrity sha512-9fGPIB7C6AyM18CJJBHt5EnCZDG3oiTJYy0NjfIAGjKpzv0tkxWko7TNQHF5ymqm7IH03tqmeuBxtvD+Izh6mg== - component-bind@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" @@ -3421,6 +3593,13 @@ component-inherit@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" +compose-function@3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/compose-function/-/compose-function-3.0.3.tgz#9ed675f13cc54501d30950a486ff6a7ba3ab185f" + integrity sha1-ntZ18TzFRQHTCVCkhv9qe6OrGF8= + dependencies: + arity-n "^1.0.4" + compressible@~2.0.16: version "2.0.17" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.17.tgz#6e8c108a16ad58384a977f3a482ca20bff2f38c1" @@ -3544,6 +3723,18 @@ content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" +convert-source-map@1.7.0, convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + +convert-source-map@^0.3.3: + version "0.3.5" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-0.3.5.tgz#f1d802950af7dd2631a1febe0596550c86ab3190" + integrity sha1-8dgClQr33SYxof6+BZZVDIarMZA= + convert-source-map@^1.1.1: version "1.5.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5" @@ -3552,13 +3743,6 @@ convert-source-map@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" -convert-source-map@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" - integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== - dependencies: - safe-buffer "~5.1.1" - cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" @@ -3587,23 +3771,22 @@ copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" -copy-webpack-plugin@5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.1.1.tgz#5481a03dea1123d88a988c6ff8b78247214f0b88" - integrity sha512-P15M5ZC8dyCjQHWwd4Ia/dm0SgVvZJMYeykVIVYXbGyqO4dWB5oyPHp9i7wjwo5LhtlhKbiBCdS2NvM07Wlybg== +copy-webpack-plugin@6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-6.0.3.tgz#2b3d2bfc6861b96432a65f0149720adbd902040b" + integrity sha512-q5m6Vz4elsuyVEIUXr7wJdIdePWTubsqVbEMvf1WQnHGv0Q+9yPRu7MtYFPt+GBOXRav9lvIINifTQ1vSCs+eA== dependencies: - cacache "^12.0.3" - find-cache-dir "^2.1.0" - glob-parent "^3.1.0" - globby "^7.1.1" - is-glob "^4.0.1" - loader-utils "^1.2.3" - minimatch "^3.0.4" + cacache "^15.0.4" + fast-glob "^3.2.4" + find-cache-dir "^3.3.1" + glob-parent "^5.1.1" + globby "^11.0.1" + loader-utils "^2.0.0" normalize-path "^3.0.0" - p-limit "^2.2.1" - schema-utils "^1.0.0" - serialize-javascript "^2.1.2" - webpack-log "^2.0.0" + p-limit "^3.0.1" + schema-utils "^2.7.0" + serialize-javascript "^4.0.0" + webpack-sources "^1.4.3" core-js-compat@^3.6.2: version "3.6.5" @@ -3613,11 +3796,6 @@ core-js-compat@^3.6.2: browserslist "^4.8.5" semver "7.0.0" -core-js-pure@^3.0.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.5.0.tgz#f63c7f2b245e7d678e73f87ad28505480554d70e" - integrity sha512-wB0QtKAofWigiISuT1Tej3hKgq932fB//Lf1VoPbiLpTYlHY0nIDhgF+q1na0DAKFHH5wGCirkAknOmDN8ijXA== - core-js@3.6.4: version "3.6.4" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.4.tgz#440a83536b458114b9cb2ac1580ba377dc470647" @@ -3703,12 +3881,6 @@ cryptiles@2.x.x: dependencies: boom "2.x.x" -cryptiles@3.x.x: - version "3.1.2" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" - dependencies: - boom "5.x.x" - crypto-browserify@^3.11.0: version "3.11.1" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.11.1.tgz#948945efc6757a400d6e5e5af47194d10064279f" @@ -3737,24 +3909,23 @@ css-declaration-sorter@^4.0.1: postcss "^7.0.1" timsort "^0.3.0" -css-loader@3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.5.1.tgz#db2b2336f4169edb68e6a829ad4fd36552647b77" - integrity sha512-0G4CbcZzQ9D1Q6ndOfjFuMDo8uLYMu5vc9Abs5ztyHcKvmil6GJrMiNjzzi3tQvUF+mVRuDg7bE6Oc0Prolgig== +css-loader@4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-4.2.2.tgz#b668b3488d566dc22ebcf9425c5f254a05808c89" + integrity sha512-omVGsTkZPVwVRpckeUnLshPp12KsmMSLqYxs12+RzM9jRR5Y+Idn/tBffjXRvOE+qW7if24cuceFJqYR5FmGBg== dependencies: - camelcase "^5.3.1" + camelcase "^6.0.0" cssesc "^3.0.0" icss-utils "^4.1.1" - loader-utils "^1.2.3" - normalize-path "^3.0.0" - postcss "^7.0.27" + loader-utils "^2.0.0" + postcss "^7.0.32" postcss-modules-extract-imports "^2.0.0" - postcss-modules-local-by-default "^3.0.2" + postcss-modules-local-by-default "^3.0.3" postcss-modules-scope "^2.2.0" postcss-modules-values "^3.0.0" - postcss-value-parser "^4.0.3" - schema-utils "^2.6.5" - semver "^6.3.0" + postcss-value-parser "^4.1.0" + schema-utils "^2.7.0" + semver "^7.3.2" css-parse@~2.0.0: version "2.0.0" @@ -3927,6 +4098,14 @@ cyclist@~0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + damerau-levenshtein@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.5.tgz#780cf7144eb2e8dbd1c3bb83ae31100ccc31a414" @@ -4004,7 +4183,7 @@ debug@4, debug@4.1.1, debug@^4.1.0, debug@^4.1.1, debug@~4.1.0: dependencies: ms "^2.1.1" -debug@^3.0.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: +debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -4055,12 +4234,6 @@ default-gateway@^4.2.0: execa "^1.0.0" ip-regex "^2.1.0" -default-require-extensions@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7" - dependencies: - strip-bom "^3.0.0" - defaults@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" @@ -4163,6 +4336,11 @@ dev-ip@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/dev-ip/-/dev-ip-1.0.1.tgz#a76a3ed1855be7a012bb8ac16cb80f3c00dc28f0" +devtools-protocol@0.0.767361: + version "0.0.767361" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.767361.tgz#5977f2558b84f9df36f62501bdddb82f3ae7b66b" + integrity sha512-ziRTdhEVQ9jEwedaUaXZ7kl9w9TF/7A3SXQ0XuqrJB+hMS62POHZUWTbumDN2ehRTfvWqTPc2Jw4gUl/jggmHA== + dezalgo@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" @@ -4188,12 +4366,12 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" -dir-glob@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034" +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== dependencies: - arrify "^1.0.1" - path-type "^3.0.0" + path-type "^4.0.0" dns-equal@^1.0.0: version "1.0.0" @@ -4338,6 +4516,11 @@ electron-to-chromium@^1.3.413: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.428.tgz#9afec8766dbe3cab825817f77e3ed0e63467b71a" integrity sha512-u3+5jEfgLKq/hGO96YfAoOAM1tgFnRDTCD5mLuev44tttcXix+INtVegAkmGzUcfDsnzkPt51XXurXZLLwXt0w== +electron-to-chromium@^1.3.570: + version "1.3.570" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.570.tgz#3f5141cc39b4e3892a276b4889980dabf1d29c7f" + integrity sha512-Y6OCoVQgFQBP5py6A/06+yWxUZHDlNr/gNDGatjH8AZqXl8X0tE4LfjLJsXGz/JmWJz8a6K7bR1k+QzZ+k//fg== + elliptic@^6.0.0: version "6.4.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" @@ -4505,23 +4688,15 @@ engine.io@~3.2.0: engine.io-parser "~2.1.0" ws "~3.3.1" -enhanced-resolve@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz#2937e2b8066cd0fe7ce0990a98f0d71a35189f66" - integrity sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA== +enhanced-resolve@4.3.0, enhanced-resolve@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126" + integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ== dependencies: graceful-fs "^4.1.2" memory-fs "^0.5.0" tapable "^1.0.0" -enhanced-resolve@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f" - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.4.0" - tapable "^1.0.0" - ent@~2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" @@ -4597,6 +4772,24 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +es5-ext@^0.10.35, es5-ext@^0.10.50: + version "0.10.53" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" + integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.3" + next-tick "~1.0.0" + +es6-iterator@2.0.3, es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + es6-promise@^4.0.3: version "4.2.4" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29" @@ -4611,6 +4804,19 @@ es6-promisify@^5.0.0: dependencies: es6-promise "^4.0.3" +es6-symbol@^3.1.1, es6-symbol@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +escalade@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.0.tgz#e8e2d7c7a8b76f6ee64c2181d6b8151441602d4e" + integrity sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig== + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -4720,18 +4926,6 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -execa@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50" - dependencies: - cross-spawn "^6.0.0" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - execa@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" @@ -4818,6 +5012,13 @@ express@^4.15.2, express@^4.17.1: utils-merge "1.0.1" vary "~1.1.2" +ext@^1.1.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244" + integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A== + dependencies: + type "^2.0.0" + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -4831,7 +5032,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@^3.0.0, extend@~3.0.0, extend@~3.0.1: +extend@^3.0.0, extend@~3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" @@ -4895,15 +5096,27 @@ fast-deep-equal@^3.1.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== -fast-json-stable-stringify@2.0.0, fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" +fast-glob@^3.1.1, fast-glob@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" + integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" fast-json-stable-stringify@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" @@ -4914,6 +5127,13 @@ fastparse@^1.1.1: resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.2.tgz#91728c5a5942eced8531283c79441ee4122c35a9" integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ== +fastq@^1.6.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481" + integrity sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q== + dependencies: + reusify "^1.0.4" + faye-websocket@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" @@ -4957,13 +5177,6 @@ filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" -fileset@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0" - dependencies: - glob "^7.0.3" - minimatch "^3.0.3" - fill-range@^2.1.0: version "2.2.3" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" @@ -5038,7 +5251,7 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-cache-dir@3.3.1: +find-cache-dir@3.3.1, find-cache-dir@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== @@ -5047,14 +5260,6 @@ find-cache-dir@3.3.1: make-dir "^3.0.2" pkg-dir "^4.1.0" -find-cache-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.0.0.tgz#4c1faed59f45184530fb9d7fa123a4d04a98472d" - dependencies: - commondir "^1.0.1" - make-dir "^1.0.0" - pkg-dir "^3.0.0" - find-cache-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" @@ -5064,15 +5269,6 @@ find-cache-dir@^2.1.0: make-dir "^2.0.0" pkg-dir "^3.0.0" -find-cache-dir@^3.2.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.0.tgz#4d74ed1fe9ef1731467ca24378e8f8f5c8b6ed11" - integrity sha512-PtXtQb7IrD8O+h6Cq1dbpJH5NzD8+9keN1zZ0YlpDzl1PwXEJEBj6u1Xa92t1Hwluoozd9TNKul5Hi2iqpsWwg== - dependencies: - commondir "^1.0.1" - make-dir "^3.0.2" - pkg-dir "^4.1.0" - find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" @@ -5149,14 +5345,6 @@ form-data@~2.1.1: combined-stream "^1.0.5" mime-types "^2.1.12" -form-data@~2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf" - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - form-data@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" @@ -5262,13 +5450,6 @@ fsevents@^1.0.0: nan "^2.3.0" node-pre-gyp "^0.6.36" -fsevents@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.3.tgz#11f82318f5fe7bb2cd22965a108e9306208216d8" - dependencies: - nan "^2.3.0" - node-pre-gyp "^0.6.39" - fsevents@^1.2.7: version "1.2.9" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" @@ -5341,10 +5522,6 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -5389,6 +5566,13 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" +glob-parent@^5.1.0, glob-parent@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + dependencies: + is-glob "^4.0.1" + glob-parent@~5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" @@ -5408,7 +5592,7 @@ glob@7.1.2, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2: once "^1.3.0" path-is-absolute "^1.0.0" -glob@7.1.6, glob@^7.1.4: +glob@7.1.6, glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -5435,6 +5619,18 @@ globals@^11.1.0: version "11.7.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.7.0.tgz#a583faa43055b1aca771914bf68258e2fc125673" +globby@^11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" + integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + globby@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" @@ -5456,17 +5652,6 @@ globby@^6.1.0: pify "^2.0.0" pinkie-promise "^2.0.0" -globby@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680" - dependencies: - array-union "^1.0.1" - dir-glob "^2.0.0" - glob "^7.1.2" - ignore "^3.3.5" - pify "^3.0.0" - slash "^1.0.0" - graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -5476,11 +5661,6 @@ graceful-fs@^4.1.15: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== -graceful-fs@^4.2.2: - version "4.2.3" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" - integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== - guess-parser@^0.4.12: version "0.4.16" resolved "https://registry.yarnpkg.com/guess-parser/-/guess-parser-0.4.16.tgz#92752dc91a9b1486655a45c7314356af38562173" @@ -5493,17 +5673,6 @@ handle-thing@^2.0.0: resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754" integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ== -handlebars@^4.1.2: - version "4.5.3" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482" - integrity sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA== - dependencies: - neo-async "^2.6.0" - optimist "^0.6.1" - source-map "^0.6.1" - optionalDependencies: - uglify-js "^3.1.4" - har-schema@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" @@ -5519,13 +5688,6 @@ har-validator@~4.2.1: ajv "^4.9.1" har-schema "^1.0.5" -har-validator@~5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" - dependencies: - ajv "^5.1.0" - har-schema "^2.0.0" - har-validator@~5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29" @@ -5654,15 +5816,6 @@ hawk@3.1.3, hawk@~3.1.3: hoek "2.x.x" sntp "1.x.x" -hawk@~6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" - dependencies: - boom "4.x.x" - cryptiles "3.x.x" - hoek "4.x.x" - sntp "2.x.x" - he@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -5685,10 +5838,6 @@ hoek@2.x.x: version "2.16.3" resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" -hoek@4.x.x: - version "4.2.0" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" - hosted-git-info@^2.1.4: version "2.5.0" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" @@ -5735,10 +5884,15 @@ html-encoding-sniffer@^2.0.1: dependencies: whatwg-encoding "^1.0.5" -html-entities@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" - integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8= +html-entities@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.3.1.tgz#fb9a1a4b5b14c5daba82d3e34c6ae4fe701a0e44" + integrity sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA== + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== http-cache-semantics@^3.8.1: version "3.8.1" @@ -5931,6 +6085,13 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.2.tgz#ce13d1875b0c3a674bd6a04b7f76b01b1b6ded01" + integrity sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + icss-utils@^4.0.0, icss-utils@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" @@ -5952,9 +6113,10 @@ ignore-walk@^3.0.1: dependencies: minimatch "^3.0.4" -ignore@^3.3.5: - version "3.3.7" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" +ignore@^5.1.4: + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== image-size@~0.5.0: version "0.5.5" @@ -6052,21 +6214,21 @@ ini@^1.3.4, ini@~1.3.0: version "1.3.4" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" -inquirer@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.1.0.tgz#1298a01859883e17c7264b82870ae1034f92dd29" - integrity sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg== +inquirer@7.3.3: + version "7.3.3" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" + integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== dependencies: ansi-escapes "^4.2.1" - chalk "^3.0.0" + chalk "^4.1.0" cli-cursor "^3.1.0" - cli-width "^2.0.0" + cli-width "^3.0.0" external-editor "^3.0.3" figures "^3.0.0" - lodash "^4.17.15" + lodash "^4.17.19" mute-stream "0.0.8" run-async "^2.4.0" - rxjs "^6.5.3" + rxjs "^6.6.0" string-width "^4.1.0" strip-ansi "^6.0.0" through "^2.3.6" @@ -6096,10 +6258,6 @@ invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" -invert-kv@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" - ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" @@ -6512,25 +6670,6 @@ isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" -istanbul-api@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-2.1.6.tgz#d61702a9d1c66ad89d92e66d401e16b0bda4a35f" - integrity sha512-x0Eicp6KsShG1k1rMgBAi/1GgY7kFGEBwQpw3PXGEmu+rBcBNhqU8g2DgY9mlepAsLPzrzrbqSgCGANnki4POA== - dependencies: - async "^2.6.2" - compare-versions "^3.4.0" - fileset "^2.0.3" - istanbul-lib-coverage "^2.0.5" - istanbul-lib-hook "^2.0.7" - istanbul-lib-instrument "^3.3.0" - istanbul-lib-report "^2.0.8" - istanbul-lib-source-maps "^3.0.6" - istanbul-reports "^2.2.4" - js-yaml "^3.13.1" - make-dir "^2.1.0" - minimatch "^3.0.4" - once "^1.4.0" - istanbul-lib-coverage@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49" @@ -6541,47 +6680,24 @@ istanbul-lib-coverage@^3.0.0: resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== -istanbul-lib-hook@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz#c95695f383d4f8f60df1f04252a9550e15b5b133" - integrity sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA== - dependencies: - append-transform "^1.0.0" - -istanbul-lib-instrument@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630" - integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA== - dependencies: - "@babel/generator" "^7.4.0" - "@babel/parser" "^7.4.3" - "@babel/template" "^7.4.0" - "@babel/traverse" "^7.4.3" - "@babel/types" "^7.4.0" - istanbul-lib-coverage "^2.0.5" - semver "^6.0.0" - -istanbul-lib-instrument@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.1.tgz#61f13ac2c96cfefb076fe7131156cc05907874e6" - integrity sha512-imIchxnodll7pvQBYOqUu88EufLCU56LMeFPZZM/fJZ1irYcYdqroaV+ACK1Ila8ls09iEYArp+nqyC6lW1Vfg== +istanbul-lib-instrument@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== dependencies: "@babel/core" "^7.7.5" - "@babel/parser" "^7.7.5" - "@babel/template" "^7.7.4" - "@babel/traverse" "^7.7.4" "@istanbuljs/schema" "^0.1.2" istanbul-lib-coverage "^3.0.0" semver "^6.3.0" -istanbul-lib-report@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz#5a8113cd746d43c4889eba36ab10e7d50c9b4f33" - integrity sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ== +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== dependencies: - istanbul-lib-coverage "^2.0.5" - make-dir "^2.1.0" - supports-color "^6.1.0" + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" istanbul-lib-source-maps@^3.0.6: version "3.0.6" @@ -6594,17 +6710,18 @@ istanbul-lib-source-maps@^3.0.6: rimraf "^2.6.3" source-map "^0.6.1" -istanbul-reports@^2.2.4: - version "2.2.6" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.6.tgz#7b4f2660d82b29303a8fe6091f8ca4bf058da1af" - integrity sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA== +istanbul-reports@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b" + integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== dependencies: - handlebars "^4.1.2" + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" -jasmine-core@^3.5.0, jasmine-core@~3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.5.0.tgz#132c23e645af96d85c8bca13c8758b18429fc1e4" - integrity sha512-nCeAiw37MIMA9w9IXso7bRaLl+c/ef3wnxsoSAlYrzS+Ot0zTG6nU8G/cIfGkqpkjX2wNaIW9RFG0TwIFnG6bA== +jasmine-core@^3.6.0, jasmine-core@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.6.0.tgz#491f3bb23941799c353ceb7a45b38a950ebc5a20" + integrity sha512-8uQYa7zJN8hq9z+g8z1bqCfdC8eoDAeVnM5sfqs7KHv9/ifoJ500m018fpFc7RDaO6SWCLCXwo/wPSNcdYTgcw== jasmine-core@~2.8.0: version "2.8.0" @@ -6617,11 +6734,12 @@ jasmine-marbles@~0.6.0: dependencies: lodash "^4.5.0" -jasmine-spec-reporter@~4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz#1d632aec0341670ad324f92ba84b4b32b35e9e22" +jasmine-spec-reporter@~5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/jasmine-spec-reporter/-/jasmine-spec-reporter-5.0.2.tgz#b61288ab074ad440dc2477c4d42840b0e74a6b95" + integrity sha512-6gP1LbVgJ+d7PKksQBc2H0oDGNRQI3gKUsWlswKaQ2fif9X5gzhQcgM5+kiJGCQVurOG09jqNhk7payggyp5+g== dependencies: - colors "1.1.2" + colors "1.4.0" jasmine@2.8.0: version "2.8.0" @@ -6635,11 +6753,12 @@ jasminewd2@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/jasminewd2/-/jasminewd2-2.2.0.tgz#e37cf0b17f199cce23bea71b2039395246b4ec4e" -jest-worker@25.1.0, jest-worker@^25.1.0: - version "25.1.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.1.0.tgz#75d038bad6fdf58eba0d2ec1835856c497e3907a" - integrity sha512-ZHhHtlxOWSxCoNOKHGbiLzXnl42ga9CxDr27H36Qn+15pQZd3R/F24jrmjDelw9j/iHUIWMWs08/u2QN50HHOg== +jest-worker@26.3.0, jest-worker@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.3.0.tgz#7c8a97e4f4364b4f05ed8bca8ca0c24de091871f" + integrity sha512-Vmpn2F6IASefL+DVBhPzI2J9/GJUsqzomdeN+P+dK8/jKxbh8R3BtFnx3FIta7wYlPU62cpJMJQo4kuOowcMnw== dependencies: + "@types/node" "*" merge-stream "^2.0.0" supports-color "^7.0.0" @@ -6774,6 +6893,11 @@ json5@^2.1.2: dependencies: minimist "^1.2.5" +jsonc-parser@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.3.0.tgz#7c7fc988ee1486d35734faaaa866fadb00fa91ee" + integrity sha512-b0EBt8SWFNnixVdvoR2ZtEGa9ZqLhbJnOjezn+WP+8kspFm+PFYDN8Z4Bc7pRlDjvuVcADSUkroIuTWWn/YiIA== + jsonfile@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66" @@ -6822,25 +6946,28 @@ karma-chrome-launcher@~3.1.0: dependencies: which "^1.2.1" -karma-coverage-istanbul-reporter@~2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-2.1.1.tgz#37a775fbfbb3cbe98cebf19605c94c6277c3b88a" - integrity sha512-CH8lTi8+kKXGvrhy94+EkEMldLCiUA0xMOiL31vvli9qK0T+qcXJAwWBRVJWnVWxYkTmyWar8lPz63dxX6/z1A== +karma-coverage-istanbul-reporter@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-3.0.3.tgz#f3b5303553aadc8e681d40d360dfdc19bc7e9fe9" + integrity sha512-wE4VFhG/QZv2Y4CdAYWDbMmcAHeS926ZIji4z+FkB2aF/EposRb6DP6G5ncT/wXhqUfAb/d7kZrNKPonbvsATw== dependencies: - istanbul-api "^2.1.6" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^3.0.6" + istanbul-reports "^3.0.2" minimatch "^3.0.4" -karma-jasmine-html-reporter@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.4.2.tgz#16d100fd701271192d27fd28ddc90b710ad36fff" - integrity sha512-7g0gPj8+9JepCNJR9WjDyQ2RkZ375jpdurYQyAYv8PorUCadepl8vrD6LmMqOGcM17cnrynBawQYZHaumgDjBw== +karma-jasmine-html-reporter@^1.5.0: + version "1.5.4" + resolved "https://registry.yarnpkg.com/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.5.4.tgz#669f33d694d88fce1b0ccfda57111de716cb0192" + integrity sha512-PtilRLno5O6wH3lDihRnz0Ba8oSn0YUJqKjjux1peoYGwo0AQqrWRbdWk/RLzcGlb+onTyXAnHl6M+Hu3UxG/Q== -karma-jasmine@~3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/karma-jasmine/-/karma-jasmine-3.0.3.tgz#751ae15d84d16e9148d0af42787fc12f5959f66d" - integrity sha512-80iBR8/hLFY2Uw3S2GG6EndWtMCGMJjrCYNwYROWsJFVTjWrRSsLqcA2ye+U3ygW5sjOQo8f+78L8cGUxjC/+A== +karma-jasmine@~4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/karma-jasmine/-/karma-jasmine-4.0.1.tgz#b99e073b6d99a5196fc4bffc121b89313b0abd82" + integrity sha512-h8XDAhTiZjJKzfkoO1laMH+zfNlra+dEQHUAjpn5JV1zCPtOIVWGQjLBrqhnzQa/hrU2XrZwSyBa6XjEBzfXzw== dependencies: - jasmine-core "^3.5.0" + jasmine-core "^3.6.0" karma-source-map-support@1.4.0: version "1.4.0" @@ -6904,6 +7031,11 @@ kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" +klona@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0" + integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA== + lazy-cache@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264" @@ -6916,36 +7048,29 @@ lcid@^1.0.0: dependencies: invert-kv "^1.0.0" -lcid@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" - dependencies: - invert-kv "^2.0.0" - -less-loader@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-5.0.0.tgz#498dde3a6c6c4f887458ee9ed3f086a12ad1b466" - integrity sha512-bquCU89mO/yWLaUq0Clk7qCsKhsF/TZpJUzETRvJa9KSVEL9SO3ovCvdEHISBhrC81OwC8QSVX7E0bzElZj9cg== +less-loader@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-6.2.0.tgz#8b26f621c155b342eefc24f5bd6e9dc40c42a719" + integrity sha512-Cl5h95/Pz/PWub/tCBgT1oNMFeH1WTD33piG80jn5jr12T4XbxZcjThwNXDQ7AG649WEynuIzO4b0+2Tn9Qolg== dependencies: - clone "^2.1.1" - loader-utils "^1.1.0" - pify "^4.0.1" + clone "^2.1.2" + less "^3.11.3" + loader-utils "^2.0.0" + schema-utils "^2.7.0" -less@3.11.1: - version "3.11.1" - resolved "https://registry.yarnpkg.com/less/-/less-3.11.1.tgz#c6bf08e39e02404fe6b307a3dfffafdc55bd36e2" - integrity sha512-tlWX341RECuTOvoDIvtFqXsKj072hm3+9ymRBe76/mD6O5ZZecnlAOVDlWAleF2+aohFrxNidXhv2773f6kY7g== +less@^3.11.3: + version "3.12.2" + resolved "https://registry.yarnpkg.com/less/-/less-3.12.2.tgz#157e6dd32a68869df8859314ad38e70211af3ab4" + integrity sha512-+1V2PCMFkL+OIj2/HrtrvZw0BC0sYLMICJfbQjuj/K8CEnlrFX6R5cKKgzzttsZDHyxQNL1jqMREjKN3ja/E3Q== dependencies: - clone "^2.1.2" tslib "^1.10.0" optionalDependencies: errno "^0.1.1" graceful-fs "^4.1.2" image-size "~0.5.0" + make-dir "^2.1.0" mime "^1.4.1" - mkdirp "^0.5.0" - promise "^7.1.1" - request "^2.83.0" + native-request "^1.0.5" source-map "~0.6.0" leven@^3.1.0: @@ -6968,10 +7093,10 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -license-webpack-plugin@2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/license-webpack-plugin/-/license-webpack-plugin-2.1.4.tgz#c5529a4bb87cc9b4489b486d054ba7cae43a554e" - integrity sha512-1Xq72fmPbTg5KofXs+yI5L4QqPFjQ6mZxoeI6D7gfiEDOtaEIk6PGrdLaej90bpDqKNHNxlQ/MW4tMAL6xMPJQ== +license-webpack-plugin@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/license-webpack-plugin/-/license-webpack-plugin-2.3.0.tgz#c00f70d5725ba0408de208acb9e66612cc2eceda" + integrity sha512-JK/DXrtN6UeYQSgkg5q1+pgJ8aiKPL9tnz9Wzw+Ikkf+8mJxG56x6t8O+OH/tAeF/5NREnelTEMyFtbJNkjH4w== dependencies: "@types/webpack-sources" "^0.1.5" webpack-sources "^1.2.0" @@ -7011,6 +7136,15 @@ loader-runner@^2.4.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== +loader-utils@1.2.3, loader-utils@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" + integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== + dependencies: + big.js "^5.2.2" + emojis-list "^2.0.0" + json5 "^1.0.1" + loader-utils@2.0.0, loader-utils@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" @@ -7028,15 +7162,6 @@ loader-utils@^1.0.2, loader-utils@^1.1.0: emojis-list "^2.0.0" json5 "^0.5.0" -loader-utils@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" - integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== - dependencies: - big.js "^5.2.2" - emojis-list "^2.0.0" - json5 "^1.0.1" - loader-utils@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" @@ -7132,12 +7257,17 @@ lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -log-symbols@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" - integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== +lodash@^4.17.19: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + +log-symbols@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" + integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== dependencies: - chalk "^2.4.2" + chalk "^4.0.0" log4js@^4.0.0: version "4.1.1" @@ -7150,10 +7280,10 @@ log4js@^4.0.0: rfdc "^1.1.2" streamroller "^1.0.4" -loglevel@^1.6.6: - version "1.6.8" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.8.tgz#8a25fb75d092230ecd4457270d80b54e28011171" - integrity sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA== +loglevel@^1.6.8: + version "1.7.0" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.0.tgz#728166855a740d59d38db01cf46f042caa041bb0" + integrity sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ== loose-envify@^1.0.0: version "1.3.1" @@ -7168,12 +7298,12 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" -magic-string@0.25.4: - version "0.25.4" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.4.tgz#325b8a0a79fc423db109b77fd5a19183b7ba5143" - integrity sha512-oycWO9nEVAP2RVPbIoDoA4Y7LFIJ3xRYov93gAyJhZkET1tNuB0u7uWkZS2LpBWTJUWnmau/To8ECWRC+jKNfw== +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== dependencies: - sourcemap-codec "^1.4.4" + yallist "^4.0.0" magic-string@0.25.7: version "0.25.7" @@ -7195,12 +7325,6 @@ magic-string@^0.25.1: dependencies: sourcemap-codec "^1.4.4" -make-dir@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.1.0.tgz#19b4369fe48c116f53c2af95ad102c0e39e85d51" - dependencies: - pify "^3.0.0" - make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -7209,6 +7333,13 @@ make-dir@^2.0.0, make-dir@^2.1.0: pify "^4.0.1" semver "^5.6.0" +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + make-dir@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.0.2.tgz#04a1acbf22221e1d6ef43559f43e05a90dbb4392" @@ -7237,17 +7368,6 @@ make-fetch-happen@^5.0.0: socks-proxy-agent "^4.0.0" ssri "^6.0.0" -mamacro@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4" - integrity sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA== - -map-age-cleaner@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.2.tgz#098fb15538fd3dbe461f12745b0ca8568d4e3f74" - dependencies: - p-defer "^1.0.0" - map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" @@ -7274,15 +7394,7 @@ media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" -mem@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-4.0.0.tgz#6437690d9471678f6cc83659c00cbafcd6b0cdaf" - dependencies: - map-age-cleaner "^0.1.1" - mimic-fn "^1.0.0" - p-is-promise "^1.1.0" - -memory-fs@^0.4.0, memory-fs@^0.4.1: +memory-fs@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" dependencies: @@ -7313,6 +7425,11 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -7453,19 +7570,15 @@ mime@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/mime/-/mime-2.3.1.tgz#b1621c54d63b97c47d3cfe7f7215f7d64517c369" -mimic-fn@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" - mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mini-css-extract-plugin@0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz#47f2cf07aa165ab35733b1fc97d4c46c0564339e" - integrity sha512-lp3GeY7ygcgAmVIcRPBVhIkf8Us7FZjA+ILpal44qLdSu11wmjKQ3d9k15lfD7pO4esu9eUIAW7qiYIBppv40A== +mini-css-extract-plugin@0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.10.0.tgz#a0e6bfcad22a9c73f6c882a3c7557a98e2d3d27d" + integrity sha512-QgKgJBjaJhxVPwrLNqqwNS0AGkuQQ31Hp4xGXEK/P7wehEg6qmNtReHKai3zRXqY60wGVWLYcOMJK2b98aGc3A== dependencies: loader-utils "^1.1.0" normalize-url "1.9.1" @@ -7480,7 +7593,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" -minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -7568,10 +7681,10 @@ minizlib@^1.2.1: dependencies: minipass "^2.9.0" -minizlib@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.0.tgz#fd52c645301ef09a63a2c209697c294c6ce02cf3" - integrity sha512-EzTZN/fjSvifSX0SlqUERCN39o6T40AMarPbv0MrarSFtIITCBh7bi+dU8nxGFHuqs9jdIAeoYoKuQAAASsPPA== +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== dependencies: minipass "^3.0.0" yallist "^4.0.0" @@ -7596,6 +7709,11 @@ mitt@^1.1.3: resolved "https://registry.yarnpkg.com/mitt/-/mitt-1.2.0.tgz#cb24e6569c806e31bd4e3995787fe38a04fdf90d" integrity sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw== +mitt@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mitt/-/mitt-2.1.0.tgz#f740577c23176c6205b121b2973514eade1b2230" + integrity sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg== + mixin-deep@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.0.tgz#47a8732ba97799457c8c1eca28f95132d7e8150a" @@ -7612,20 +7730,20 @@ mkdirp@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" -mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1, mkdirp@~0.5.x: +mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: minimist "0.0.8" -mkdirp@^0.5.3: +mkdirp@^0.5.3, mkdirp@^0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== dependencies: minimist "^1.2.5" -mkdirp@^1.0.3: +mkdirp@^1.0.3, mkdirp@^1.0.4, mkdirp@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -7728,6 +7846,11 @@ nanomatch@^1.2.9: snapdragon "^0.8.1" to-regex "^3.0.1" +native-request@^1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/native-request/-/native-request-1.0.7.tgz#ff742dc555b4c8f2f1c14b548639ba174e573856" + integrity sha512-9nRjinI9bmz+S7dgNtf4A70+/vPhnd+2krGpy4SUlADuOuSa24IDkNaZ+R/QT1wQ6S8jBdi6wE7fLekFZNfUpQ== + needle@^2.2.1: version "2.2.4" resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" @@ -7749,11 +7872,21 @@ neo-async@^2.5.0: version "2.5.1" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.1.tgz#acb909e327b1e87ec9ef15f41b8a269512ad41ee" -neo-async@^2.6.0, neo-async@^2.6.1: +neo-async@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +next-tick@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= + nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" @@ -7832,22 +7965,6 @@ node-pre-gyp@^0.6.36: tar "^2.2.1" tar-pack "^3.4.0" -node-pre-gyp@^0.6.39: - version "0.6.39" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649" - dependencies: - detect-libc "^1.0.2" - hawk "3.1.3" - mkdirp "^0.5.1" - nopt "^4.0.1" - npmlog "^4.0.2" - rc "^1.1.7" - request "2.81.0" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^2.2.1" - tar-pack "^3.4.0" - node-releases@^1.1.49: version "1.1.50" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.50.tgz#803c40d2c45db172d0410e4efec83aa8c6ad0592" @@ -7867,6 +7984,11 @@ node-releases@^1.1.53: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.54.tgz#0a6b3916a7ddfd9656983fcde82cf38d1dbe1a6f" integrity sha512-tLzytKpgwKQr37yw9CEODjNM9lnmsNxzlv575GzOZ16AgMvPcJis/DgrJX4UEV1KIYoXk6XoVfY6YaMOPJESAQ== +node-releases@^1.1.61: + version "1.1.61" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.61.tgz#707b0fca9ce4e11783612ba4a2fcba09047af16e" + integrity sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g== + nopt@3.0.x: version "3.0.6" resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" @@ -7989,10 +8111,10 @@ npm-packlist@^1.1.6: ignore-walk "^3.0.1" npm-bundled "^1.0.1" -npm-pick-manifest@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-6.0.0.tgz#bfde7abe95f2670aed1629a3c18245ccb3cc2eb8" - integrity sha512-PdJpXMvjqt4nftNEDpCgjBUF8yI3Q3MyuAmVB9nemnnCg32F4BPL/JFBfdj8DubgHCYUFQhtLWmBPvdsFtjWMg== +npm-pick-manifest@6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-6.1.0.tgz#2befed87b0fce956790f62d32afb56d7539c022a" + integrity sha512-ygs4k6f54ZxJXrzT0x34NybRlLeZ4+6nECAIbr2i0foTnijtS1TJiyzpqtuUAJOps/hO0tNDr8fRV5g+BtRlTw== dependencies: npm-install-checks "^4.0.0" npm-package-arg "^8.0.0" @@ -8055,7 +8177,7 @@ nwsapi@^2.2.0: resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== -oauth-sign@~0.8.1, oauth-sign@~0.8.2: +oauth-sign@~0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" @@ -8093,7 +8215,7 @@ object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object-path@^0.11.4: +object-path@0.11.4, object-path@^0.11.4: version "0.11.4" resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.11.4.tgz#370ae752fbf37de3ea70a861c23bba8915691949" integrity sha1-NwrnUvvzfePqcKhhwju6iRVpGUk= @@ -8194,10 +8316,10 @@ open@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/open/-/open-0.0.5.tgz#42c3e18ec95466b6bf0dc42f3a2945c3f0cad8fc" -open@7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/open/-/open-7.0.3.tgz#db551a1af9c7ab4c7af664139930826138531c48" - integrity sha512-sP2ru2v0P290WFfv49Ap8MF6PkzGNnGlAwHweB4WR4mr5d2d0woiCluUeJ218w7/+PmoBy9JmYgD5A4mLcWOFA== +open@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/open/-/open-7.2.0.tgz#212959bd7b0ce2e8e3676adc76e3cf2f0a2498b4" + integrity sha512-4HeyhxCvBTI5uBePsAdi55C5fmqnWZ2e2MlmvWi5KW5tdH5rxoiv/aMtbeVxKZc3eWkT1GymMnLG8XC4Rq4TDQ== dependencies: is-docker "^2.0.0" is-wsl "^2.1.1" @@ -8232,7 +8354,7 @@ opn@^5.5.0: dependencies: is-wsl "^1.1.0" -optimist@^0.6.1, optimist@~0.6.0, optimist@~0.6.1: +optimist@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= @@ -8256,16 +8378,16 @@ options@>=0.0.5: version "0.0.6" resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" -ora@4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/ora/-/ora-4.0.3.tgz#752a1b7b4be4825546a7a3d59256fa523b6b6d05" - integrity sha512-fnDebVFyz309A73cqCipVL1fBZewq4vwgSHfxh43vVy31mbyoQ8sCH3Oeaog/owYOs/lLlGVPCISQonTneg6Pg== +ora@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.0.0.tgz#4f0b34f2994877b49b452a707245ab1e9f6afccb" + integrity sha512-s26qdWqke2kjN/wC4dy+IQPBIMWBJlSU/0JZhk30ZDBLelW25rv66yutUWARMigpGPzcXHb+Nac5pNhN/WsARw== dependencies: - chalk "^3.0.0" + chalk "^4.1.0" cli-cursor "^3.1.0" - cli-spinners "^2.2.0" + cli-spinners "^2.4.0" is-interactive "^1.0.0" - log-symbols "^3.0.0" + log-symbols "^4.0.0" mute-stream "0.0.8" strip-ansi "^6.0.0" wcwidth "^1.0.1" @@ -8292,14 +8414,6 @@ os-locale@^1.4.0: dependencies: lcid "^1.0.0" -os-locale@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.0.1.tgz#3b014fbf01d87f60a1e5348d80fe870dc82c4620" - dependencies: - execa "^0.10.0" - lcid "^2.0.0" - mem "^4.0.0" - os-tmpdir@^1.0.0, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -8318,18 +8432,10 @@ osenv@^0.1.5: os-homedir "^1.0.0" os-tmpdir "^1.0.0" -p-defer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" - p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" -p-is-promise@^1.1.0: - version "1.1.0" - resolved "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" - p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" @@ -8343,17 +8449,17 @@ p-limit@^2.0.0: dependencies: p-try "^2.0.0" -p-limit@^2.2.0, p-limit@^2.2.1: +p-limit@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== dependencies: p-try "^2.0.0" -p-limit@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e" - integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ== +p-limit@^3.0.1, p-limit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.2.tgz#1664e010af3cadc681baafd3e2a437be7b0fb5fe" + integrity sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg== dependencies: p-try "^2.0.0" @@ -8382,10 +8488,10 @@ p-map@^2.0.0: resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== -p-map@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" - integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== dependencies: aggregate-error "^3.0.0" @@ -8490,15 +8596,23 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" -parse5@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" +parse5-htmlparser2-tree-adapter@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" + integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== + dependencies: + parse5 "^6.0.1" parse5@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== +parse5@6.0.1, parse5@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + parsejson@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/parsejson/-/parsejson-0.0.3.tgz#ab7e3759f209ece99437973f7d0f1f64ae0e64ab" @@ -8588,11 +8702,10 @@ path-type@^1.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" -path-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - dependencies: - pify "^3.0.0" +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== pbkdf2@^3.0.3: version "3.0.14" @@ -8622,6 +8735,11 @@ picomatch@^2.0.4, picomatch@^2.0.5: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5" integrity sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA== +picomatch@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== + pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -8651,7 +8769,7 @@ pkg-dir@^3.0.0: dependencies: find-up "^3.0.0" -pkg-dir@^4.1.0: +pkg-dir@^4.1.0, pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== @@ -8665,6 +8783,13 @@ pkg-up@^2.0.0: dependencies: find-up "^2.1.0" +pnp-webpack-plugin@1.6.4: + version "1.6.4" + resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149" + integrity sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg== + dependencies: + ts-pnp "^1.1.6" + portfinder@^1.0.20: version "1.0.20" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.20.tgz#bea68632e54b2e13ab7b0c4775e9b41bf270e44a" @@ -8674,14 +8799,14 @@ portfinder@^1.0.20: debug "^2.2.0" mkdirp "0.5.x" -portfinder@^1.0.25: - version "1.0.25" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca" - integrity sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg== +portfinder@^1.0.26: + version "1.0.28" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" + integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== dependencies: async "^2.6.2" debug "^3.1.1" - mkdirp "^0.5.1" + mkdirp "^0.5.5" portscanner@2.1.1: version "2.1.1" @@ -8845,15 +8970,15 @@ postcss-modules-extract-imports@^2.0.0: dependencies: postcss "^7.0.5" -postcss-modules-local-by-default@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz#e8a6561be914aaf3c052876377524ca90dbb7915" - integrity sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ== +postcss-modules-local-by-default@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0" + integrity sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw== dependencies: icss-utils "^4.1.1" - postcss "^7.0.16" + postcss "^7.0.32" postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.0.0" + postcss-value-parser "^4.1.0" postcss-modules-scope@^2.2.0: version "2.2.0" @@ -9027,20 +9152,29 @@ postcss-value-parser@^3.2.3: version "3.3.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" -postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.3: - version "4.1.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" - integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== - postcss-value-parser@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz#482282c09a42706d1fc9a069b73f44ec08391dc9" integrity sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ== -postcss@7.0.27, postcss@^7.0.27: - version "7.0.27" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.27.tgz#cc67cdc6b0daa375105b7c424a85567345fc54d9" - integrity sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ== +postcss-value-parser@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" + integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== + +postcss@7.0.21: + version "7.0.21" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.21.tgz#06bb07824c19c2021c5d056d5b10c35b989f7e17" + integrity sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + +postcss@7.0.32: + version "7.0.32" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" + integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== dependencies: chalk "^2.4.2" source-map "^0.6.1" @@ -9054,7 +9188,7 @@ postcss@^7.0.0, postcss@^7.0.1: source-map "^0.6.1" supports-color "^5.5.0" -postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.26, postcss@^7.0.5, postcss@^7.0.6: +postcss@^7.0.14, postcss@^7.0.5, postcss@^7.0.6: version "7.0.29" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.29.tgz#d3a903872bd52280b83bce38cdc83ce55c06129e" integrity sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw== @@ -9063,6 +9197,24 @@ postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.26, postcss@^7.0.5, postcss@^7.0. source-map "^0.6.1" supports-color "^6.1.0" +postcss@^7.0.27: + version "7.0.27" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.27.tgz#cc67cdc6b0daa375105b7c424a85567345fc54d9" + integrity sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + +postcss@^7.0.32: + version "7.0.34" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.34.tgz#f2baf57c36010df7de4009940f21532c16d65c20" + integrity sha512-H/7V2VeNScX9KE83GDrDZNiGT1m2H+UTnlinIzhjlLX9hfMUn1mHNnGeX81a1c8JSBdBvqk7c2ZOG6ZPn5itGw== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -9113,12 +9265,6 @@ promise-retry@^1.1.1: err-code "^1.0.0" retry "^0.10.0" -promise@^7.1.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" - dependencies: - asap "~2.0.3" - protoduck@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/protoduck/-/protoduck-5.0.1.tgz#03c3659ca18007b69a50fd82a7ebcc516261151f" @@ -9126,10 +9272,10 @@ protoduck@^5.0.1: dependencies: genfun "^5.0.0" -protractor@~5.4.3: - version "5.4.3" - resolved "https://registry.yarnpkg.com/protractor/-/protractor-5.4.3.tgz#35f050741e404a45868618ea648745d89af31683" - integrity sha512-7pMAolv8Ah1yJIqaorDTzACtn3gk7BamVKPTeO5lqIGOrfosjPgXFx/z1dqSI+m5EeZc2GMJHPr5DYlodujDNA== +protractor@~7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/protractor/-/protractor-7.0.0.tgz#c3e263608bd72e2c2dc802b11a772711a4792d03" + integrity sha512-UqkFjivi4GcvUQYzqGYNe0mLzfn5jiLmO8w9nMhQoJRLhy2grJonpga2IWhI6yJO30LibWXJJtA4MOIZD2GgZw== dependencies: "@types/q" "^0.0.32" "@types/selenium-webdriver" "^3.0.0" @@ -9139,13 +9285,13 @@ protractor@~5.4.3: glob "^7.0.3" jasmine "2.8.0" jasminewd2 "^2.1.0" - optimist "~0.6.0" q "1.4.1" saucelabs "^1.5.0" selenium-webdriver "3.6.0" source-map-support "~0.4.0" webdriver-js-extender "2.1.0" - webdriver-manager "^12.0.6" + webdriver-manager "^12.1.7" + yargs "^15.3.1" proxy-addr@~2.0.5: version "2.0.5" @@ -9227,15 +9373,18 @@ punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -puppeteer@3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-3.3.0.tgz#95839af9fdc0aa4de7e5ee073a4c0adeb9e2d3d7" - integrity sha512-23zNqRltZ1PPoK28uRefWJ/zKb5Jhnzbbwbpcna2o5+QMn17F0khq5s1bdH3vPlyj+J36pubccR8wiNA/VE0Vw== +puppeteer@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-5.1.0.tgz#e7bae2caa6e3a13a622755e4c27689d9812c38ca" + integrity sha512-IZBFG8XcA+oHxYo5rEpJI/HQignUis2XPijPoFpNxla2O+WufonGsUsSqrhRXgBKOME5zNfhRdUY2LvxAiKlhw== dependencies: debug "^4.1.0" + devtools-protocol "0.0.767361" extract-zip "^2.0.0" https-proxy-agent "^4.0.0" mime "^2.0.3" + mitt "^2.0.1" + pkg-dir "^4.2.0" progress "^2.0.1" proxy-from-env "^1.0.0" rimraf "^3.0.2" @@ -9269,7 +9418,7 @@ qs@6.2.3: resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.3.tgz#1cfcb25c10a9b2b483053ff39f5dfc9233908cfe" integrity sha1-HPyyXBCpsrSDBT/zn138kjOQjP4= -qs@6.5.1, "qs@>= 0.4.0", qs@~6.5.1: +qs@6.5.1, "qs@>= 0.4.0": version "6.5.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" @@ -9326,6 +9475,13 @@ randombytes@^2.0.0, randombytes@^2.0.1: dependencies: safe-buffer "^5.1.0" +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + range-parser@^1.2.0, range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" @@ -9364,13 +9520,13 @@ raw-body@^2.3.2: iconv-lite "0.4.24" unpipe "1.0.0" -raw-loader@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-4.0.0.tgz#d639c40fb9d72b5c7f8abc1fb2ddb25b29d3d540" - integrity sha512-iINUOYvl1cGEmfoaLjnZXt4bKfT2LJnZZib5N/LLyAphC+Dd11vNP9CNVb38j+SAJpFI1uo8j9frmih53ASy7Q== +raw-loader@4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-4.0.1.tgz#14e1f726a359b68437e183d5a5b7d33a3eba6933" + integrity sha512-baolhQBSi3iNh1cglJjA0mYzga+wePk7vdEX//1dTFd+v4TsQlQE0jitJSNF1OIP82rdYulH7otaVmdlDaJ64A== dependencies: - loader-utils "^1.2.3" - schema-utils "^2.5.0" + loader-utils "^2.0.0" + schema-utils "^2.6.5" rc@^1.1.7: version "1.2.2" @@ -9530,6 +9686,13 @@ readdirp@~3.2.0: dependencies: picomatch "^2.0.4" +readdirp@~3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada" + integrity sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ== + dependencies: + picomatch "^2.2.1" + reflect-metadata@^0.1.2: version "0.1.10" resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.10.tgz#b4f83704416acad89988c9b15635d47e03b9344a" @@ -9553,16 +9716,16 @@ regenerate@^1.2.1, regenerate@^1.4.0: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== -regenerator-runtime@0.13.5, regenerator-runtime@^0.13.4: +regenerator-runtime@0.13.7: + version "0.13.7" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== + +regenerator-runtime@^0.13.4: version "0.13.5" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== -regenerator-runtime@^0.13.2: - version "0.13.3" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" - integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw== - regenerator-transform@^0.14.2: version "0.14.4" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.4.tgz#5266857896518d1616a78a0479337a30ea974cc7" @@ -9590,6 +9753,11 @@ regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +regex-parser@2.2.10: + version "2.2.10" + resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.10.tgz#9e66a8f73d89a107616e63b39d4deddfee912b37" + integrity sha512-8t6074A68gHfU8Neftl0Le6KTDwfGAj7IyjPIMSfikI2wJUTHDMaIq42bUsfVnj8mhx0R+45rdUXHGpN164avA== + regexpu-core@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b" @@ -9709,34 +9877,7 @@ request@2.81.0: tunnel-agent "^0.6.0" uuid "^3.0.0" -request@^2.83.0: - version "2.85.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.85.0.tgz#5a03615a47c61420b3eb99b7dba204f83603e1fa" - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.6.0" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.1" - forever-agent "~0.6.1" - form-data "~2.3.1" - har-validator "~5.0.3" - hawk "~6.0.2" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.17" - oauth-sign "~0.8.2" - performance-now "^2.1.0" - qs "~6.5.1" - safe-buffer "^5.1.1" - stringstream "~0.0.5" - tough-cookie "~2.3.3" - tunnel-agent "^0.6.0" - uuid "^3.1.0" - -request@^2.87.0, request@^2.88.0: +request@^2.87.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== @@ -9819,6 +9960,22 @@ resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" +resolve-url-loader@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-3.1.1.tgz#28931895fa1eab9be0647d3b2958c100ae3c0bf0" + integrity sha512-K1N5xUjj7v0l2j/3Sgs5b8CjrrgtC70SmdCuZiJ8tSyb5J+uk3FoeZ4b7yTnH6j7ngI+Bc5bldHJIa8hYdu2gQ== + dependencies: + adjust-sourcemap-loader "2.0.0" + camelcase "5.3.1" + compose-function "3.0.3" + convert-source-map "1.7.0" + es6-iterator "2.0.3" + loader-utils "1.2.3" + postcss "7.0.21" + rework "1.0.1" + rework-visit "1.0.0" + source-map "0.6.1" + resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" @@ -9842,6 +9999,13 @@ resolve@^1.3.2: dependencies: path-parse "^1.0.5" +resolve@^1.8.1: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + resp-modifier@6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/resp-modifier/-/resp-modifier-6.0.2.tgz#b124de5c4fbafcba541f48ffa73970f4aa456b4f" @@ -9870,6 +10034,24 @@ retry@^0.12.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rework-visit@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rework-visit/-/rework-visit-1.0.0.tgz#9945b2803f219e2f7aca00adb8bc9f640f842c9a" + integrity sha1-mUWygD8hni96ygCtuLyfZA+ELJo= + +rework@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rework/-/rework-1.0.1.tgz#30806a841342b54510aa4110850cd48534144aa7" + integrity sha1-MIBqhBNCtUUQqkEQhQzUhTQUSqc= + dependencies: + convert-source-map "^0.3.3" + css "^2.0.0" + rfdc@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.2.tgz#e6e72d74f5dc39de8f538f65e00c36c18018e349" @@ -9904,13 +10086,6 @@ rimraf@^2.6.3: dependencies: glob "^7.1.3" -rimraf@^2.7.1: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - rimraf@~2.2.6: version "2.2.8" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.2.8.tgz#e439be2aaee327321952730f99a8929e4fc50582" @@ -9967,10 +10142,10 @@ rollup-pluginutils@^2.8.2: dependencies: estree-walker "^0.6.1" -rollup@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.1.0.tgz#552e248e397a06b9c6db878c0564ca4ee06729c9" - integrity sha512-gfE1455AEazVVTJoeQtcOq/U6GSxwoj4XPSWVsuWmgIxj7sBQNLDOSA82PbdMe+cP8ql8fR1jogPFe8Wg8g4SQ== +rollup@2.26.5: + version "2.26.5" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.26.5.tgz#5562ec36fcba3eed65cfd630bd78e037ad0e0307" + integrity sha512-rCyFG3ZtQdnn9YwfuAVH0l/Om34BdO5lwCA0W6Hq+bNB21dVEBbCRxhaHOmu1G7OBFDWytbzAC104u7rxHwGjA== optionalDependencies: fsevents "~2.1.2" @@ -9988,6 +10163,11 @@ run-async@^2.4.0: resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" @@ -9998,17 +10178,10 @@ rx@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" -rxjs@6.5.3, rxjs@^6.5.2: - version "6.5.3" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" - integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA== - dependencies: - tslib "^1.9.0" - -rxjs@6.5.4, rxjs@^6.5.3, rxjs@~6.5.4: - version "6.5.4" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" - integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q== +rxjs@6.6.2: + version "6.6.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.2.tgz#8096a7ac03f2cc4fe5860ef6e572810d9e01c0d2" + integrity sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg== dependencies: tslib "^1.9.0" @@ -10019,6 +10192,20 @@ rxjs@^5.5.6: dependencies: symbol-observable "1.0.1" +rxjs@^6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" + integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA== + dependencies: + tslib "^1.9.0" + +rxjs@^6.5.3, rxjs@^6.5.5, rxjs@^6.6.0, rxjs@~6.6.0: + version "6.6.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552" + integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== + dependencies: + tslib "^1.9.0" + safe-buffer@5.1.2, safe-buffer@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -10039,25 +10226,25 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.1.2: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" -sass-loader@8.0.2: - version "8.0.2" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-8.0.2.tgz#debecd8c3ce243c76454f2e8290482150380090d" - integrity sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ== +sass-loader@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-10.0.1.tgz#10c0364d8034f22fee25ddcc9eded20f99bbe3b4" + integrity sha512-b2PSldKVTS3JcFPHSrEXh3BeAfR7XknGiGCAO5aHruR3Pf3kqLP3Gb2ypXLglRrAzgZkloNxLZ7GXEGDX0hBUQ== dependencies: - clone-deep "^4.0.1" - loader-utils "^1.2.3" - neo-async "^2.6.1" - schema-utils "^2.6.1" - semver "^6.3.0" + klona "^2.0.3" + loader-utils "^2.0.0" + neo-async "^2.6.2" + schema-utils "^2.7.0" + semver "^7.3.2" -sass@1.26.3: - version "1.26.3" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.26.3.tgz#412df54486143b76b5a65cdf7569e86f44659f46" - integrity sha512-5NMHI1+YFYw4sN3yfKjpLuV9B5l7MqQ6FlkTcC4FT+oHbBRUZoSjHrrt/mE0nFXJyY2kQtU9ou9HxvFVjLFuuw== +sass@1.26.10: + version "1.26.10" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.26.10.tgz#851d126021cdc93decbf201d1eca2a20ee434760" + integrity sha512-bzN0uvmzfsTvjz0qwccN1sPm2HxxpNI/Xa+7PlUEMS+nQvbyuEK7Y0qFqxlPHhiNHb1Ze8WQJtU31olMObkAMw== dependencies: chokidar ">=2.0.0 <4.0.0" @@ -10086,7 +10273,7 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -schema-utils@^2.5.0, schema-utils@^2.6.5: +schema-utils@^2.6.5: version "2.6.6" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.6.tgz#299fe6bd4a3365dc23d99fd446caff8f1d6c330c" integrity sha512-wHutF/WPSbIi9x6ctjGGk2Hvl0VOz5l3EKEuKbjPlB30mKZUzb9A5k9yEXRX3pwyqVLPvpfZZEllaFq/M718hA== @@ -10094,13 +10281,14 @@ schema-utils@^2.5.0, schema-utils@^2.6.5: ajv "^6.12.0" ajv-keywords "^3.4.1" -schema-utils@^2.6.1, schema-utils@^2.6.4: - version "2.6.4" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.4.tgz#a27efbf6e4e78689d91872ee3ccfa57d7bdd0f53" - integrity sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ== +schema-utils@^2.6.6, schema-utils@^2.7.0: + version "2.7.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" + integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== dependencies: - ajv "^6.10.2" - ajv-keywords "^3.4.1" + "@types/json-schema" "^7.0.5" + ajv "^6.12.4" + ajv-keywords "^3.5.2" secure-compare@3.0.1: version "3.0.1" @@ -10149,10 +10337,10 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.1.3.tgz#e4345ce73071c53f336445cfc19efb1c311df2a6" - integrity sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA== +semver@7.3.2, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== semver@^5.0.0, semver@^5.5.0: version "5.5.0" @@ -10163,6 +10351,11 @@ semver@^5.4.1, semver@^5.6.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== +semver@^5.5.1: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + semver@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.0.0.tgz#05e359ee571e5ad7ed641a6eec1e547ba52dea65" @@ -10173,11 +10366,6 @@ semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.0.0, semver@^7.1.1: - version "7.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" - integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== - send@0.15.2: version "0.15.2" resolved "https://registry.yarnpkg.com/send/-/send-0.15.2.tgz#f91fab4403bcf87e716f70ceb5db2f578bdc17d6" @@ -10239,6 +10427,13 @@ serialize-javascript@^2.1.2: resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== +serialize-javascript@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" + integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== + dependencies: + randombytes "^2.1.0" + serve-index@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.8.0.tgz#7c5d96c13fb131101f93c1c5774f8516a1e78d3b" @@ -10353,13 +10548,6 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" -shallow-clone@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" - integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== - dependencies: - kind-of "^6.0.2" - shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -10385,6 +10573,11 @@ slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + smart-buffer@4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.2.tgz#5207858c3815cc69110703c6b94e46c15634395d" @@ -10423,12 +10616,6 @@ sntp@1.x.x: dependencies: hoek "2.x.x" -sntp@2.x.x: - version "2.1.0" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" - dependencies: - hoek "4.x.x" - socket.io-adapter@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-0.5.0.tgz#cb6d4bb8bec81e1078b99677f9ced0046066bb8b" @@ -10556,12 +10743,14 @@ sockjs-client@1.4.0: json3 "^3.3.2" url-parse "^1.4.3" -sockjs@0.3.19: - version "0.3.19" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.19.tgz#d976bbe800af7bd20ae08598d582393508993c0d" +sockjs@0.3.20: + version "0.3.20" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.20.tgz#b26a283ec562ef8b2687b44033a4eeceac75d855" + integrity sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA== dependencies: faye-websocket "^0.10.0" - uuid "^3.0.1" + uuid "^3.4.0" + websocket-driver "0.6.5" socks-proxy-agent@^4.0.0: version "4.0.1" @@ -10603,12 +10792,16 @@ source-map-explorer@^1.3.2: temp "^0.8.3" underscore "^1.8.3" -source-map-loader@0.2.4: - version "0.2.4" - resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-0.2.4.tgz#c18b0dc6e23bf66f6792437557c569a11e072271" +source-map-loader@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-1.0.2.tgz#b0a6582b2eaa387ede1ecf8061ae0b93c23f9eb0" + integrity sha512-oX8d6ndRjN+tVyjj6PlXSyFPhDdVAPsZA30nD3/II8g4uOv8fCz0DMn5sy8KtVbDfKQxOpGwGJnK3xIW3tauDw== dependencies: - async "^2.5.0" - loader-utils "^1.1.0" + data-urls "^2.0.0" + iconv-lite "^0.6.2" + loader-utils "^2.0.0" + schema-utils "^2.7.0" + source-map "^0.6.1" source-map-resolve@^0.5.0: version "0.5.1" @@ -10631,6 +10824,14 @@ source-map-resolve@^0.5.2: source-map-url "^0.4.0" urix "^0.1.0" +source-map-support@0.5.19: + version "0.5.19" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-support@^0.5.5, source-map-support@^0.5.6: version "0.5.9" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" @@ -10656,6 +10857,10 @@ source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" +source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + source-map@0.7.3, source-map@^0.7.3: version "0.7.3" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" @@ -10664,10 +10869,6 @@ source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.6, source-map@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - sourcemap-codec@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.1.tgz#c8fd92d91889e902a07aee392bdd2c5863958ba2" @@ -10712,10 +10913,10 @@ spdy-transport@^3.0.0: readable-stream "^3.0.6" wbuf "^1.7.3" -spdy@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.1.tgz#6f12ed1c5db7ea4f24ebb8b89ba58c87c08257f2" - integrity sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA== +spdy@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b" + integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA== dependencies: debug "^4.1.0" handle-thing "^2.0.0" @@ -10723,10 +10924,10 @@ spdy@^4.0.1: select-hose "^2.0.0" spdy-transport "^3.0.0" -speed-measure-webpack-plugin@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.3.1.tgz#69840a5cdc08b4638697dac7db037f595d7f36a0" - integrity sha512-qVIkJvbtS9j/UeZumbdfz0vg+QfG/zxonAjzefZrqzkr7xOncLVXkeGbTpzd1gjCBM4PmVNkWlkeTVhgskAGSQ== +speed-measure-webpack-plugin@1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.3.3.tgz#6ff894fc83e8a6310dde3af863a0329cd79da4f5" + integrity sha512-2ljD4Ch/rz2zG3HsLsnPfp23osuPBS0qPuz9sGpkNXTN1Ic4M+W9xB8l8rS8ob2cO4b1L+WTJw/0AJwWYVgcxQ== dependencies: chalk "^2.0.1" @@ -10765,14 +10966,6 @@ ssri@^6.0.0, ssri@^6.0.1: dependencies: figgy-pudding "^3.5.1" -ssri@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-7.1.0.tgz#92c241bf6de82365b5c7fb4bd76e975522e1294d" - integrity sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g== - dependencies: - figgy-pudding "^3.5.1" - minipass "^3.1.1" - ssri@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.0.tgz#79ca74e21f8ceaeddfcb4b90143c458b8d988808" @@ -10870,13 +11063,6 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^2.0.0, string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" @@ -10958,7 +11144,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -stringstream@~0.0.4, stringstream@~0.0.5: +stringstream@~0.0.4: version "0.0.5" resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" @@ -10968,12 +11154,6 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1: dependencies: ansi-regex "^2.0.0" -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - dependencies: - ansi-regex "^3.0.0" - strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" @@ -10994,10 +11174,6 @@ strip-bom@^2.0.0: dependencies: is-utf8 "^0.2.0" -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" @@ -11006,13 +11182,13 @@ strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" -style-loader@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.1.3.tgz#9e826e69c683c4d9bf9db924f85e9abb30d5e200" - integrity sha512-rlkH7X/22yuwFYK357fMN/BxYOorfnfq0eD7+vqlemSK4wEcejFF1dg4zxP0euBW8NrYx2WZzZ8PPFevr7D+Kw== +style-loader@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.2.1.tgz#c5cbbfbf1170d076cfdd86e0109c5bba114baa1a" + integrity sha512-ByHSTQvHLkWE9Ir5+lGbVOXhxX10fbprhLvdg96wedFZb4NDekDPxVKv5Fwmio+QcMlkkNfuK+5W1peQ5CUhZg== dependencies: - loader-utils "^1.2.3" - schema-utils "^2.6.4" + loader-utils "^2.0.0" + schema-utils "^2.6.6" stylehacks@^4.0.0: version "4.0.3" @@ -11031,18 +11207,18 @@ stylus-loader@3.0.2: lodash.clonedeep "^4.5.0" when "~3.6.x" -stylus@0.54.7: - version "0.54.7" - resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.54.7.tgz#c6ce4793965ee538bcebe50f31537bfc04d88cd2" - integrity sha512-Yw3WMTzVwevT6ZTrLCYNHAFmanMxdylelL3hkWNgPMeTCpMwpV3nXjpOHuBXtFv7aiO2xRuQS6OoAdgkNcSNug== +stylus@0.54.8: + version "0.54.8" + resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.54.8.tgz#3da3e65966bc567a7b044bfe0eece653e099d147" + integrity sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg== dependencies: css-parse "~2.0.0" debug "~3.1.0" - glob "^7.1.3" - mkdirp "~0.5.x" + glob "^7.1.6" + mkdirp "~1.0.4" safer-buffer "^2.1.2" sax "~1.2.4" - semver "^6.0.0" + semver "^6.3.0" source-map "^0.7.3" supports-color@^2.0.0: @@ -11196,15 +11372,15 @@ tar@^4.4.10: safe-buffer "^5.1.2" yallist "^3.0.3" -tar@^6.0.1: - version "6.0.2" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.2.tgz#5df17813468a6264ff14f766886c622b84ae2f39" - integrity sha512-Glo3jkRtPcvpDlAs/0+hozav78yoXKFr+c4wgw62NNMO3oo4AaJdCo21Uu7lcwr55h39W2XD1LMERc64wtbItg== +tar@^6.0.2: + version "6.0.5" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.5.tgz#bde815086e10b39f1dcd298e89d596e1535e200f" + integrity sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg== dependencies: chownr "^2.0.0" fs-minipass "^2.0.0" minipass "^3.0.0" - minizlib "^2.1.0" + minizlib "^2.1.1" mkdirp "^1.0.3" yallist "^4.0.0" @@ -11215,19 +11391,19 @@ temp@^0.8.3: os-tmpdir "^1.0.0" rimraf "~2.2.6" -terser-webpack-plugin@2.3.5: - version "2.3.5" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.5.tgz#5ad971acce5c517440ba873ea4f09687de2f4a81" - integrity sha512-WlWksUoq+E4+JlJ+h+U+QUzXpcsMSSNXkDy9lBVkSqDn1w23Gg29L/ary9GeJVYCGiNJJX7LnVc4bwL1N3/g1w== - dependencies: - cacache "^13.0.1" - find-cache-dir "^3.2.0" - jest-worker "^25.1.0" - p-limit "^2.2.2" - schema-utils "^2.6.4" - serialize-javascript "^2.1.2" +terser-webpack-plugin@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-4.1.0.tgz#6e9d6ae4e1a900d88ddce8da6a47507ea61f44bc" + integrity sha512-0ZWDPIP8BtEDZdChbufcXUigOYk6dOX/P/X0hWxqDDcVAQLb8Yy/0FAaemSfax3PAA67+DJR778oz8qVbmy4hA== + dependencies: + cacache "^15.0.5" + find-cache-dir "^3.3.1" + jest-worker "^26.3.0" + p-limit "^3.0.2" + schema-utils "^2.6.6" + serialize-javascript "^4.0.0" source-map "^0.6.1" - terser "^4.4.3" + terser "^5.0.0" webpack-sources "^1.4.3" terser-webpack-plugin@^1.4.3: @@ -11245,10 +11421,10 @@ terser-webpack-plugin@^1.4.3: webpack-sources "^1.4.0" worker-farm "^1.7.0" -terser@4.6.10: - version "4.6.10" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.10.tgz#90f5bd069ff456ddbc9503b18e52f9c493d3b7c2" - integrity sha512-qbF/3UOo11Hggsbsqm2hPa6+L4w7bkr+09FNseEe8xrcVD3APGLFqE+Oz1ZKAxjYnFsj80rLOfgAtJ0LNJjtTA== +terser@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.3.0.tgz#c481f4afecdcc182d5e2bdd2ff2dc61555161e81" + integrity sha512-XTT3D3AwxC54KywJijmY2mxZ8nJiEjBHVYzq8l9OaYuRFWeQNBwvipuzzYEP4e+/AVcd1hqG/CqgsdIRyT45Fg== dependencies: commander "^2.20.0" source-map "~0.6.1" @@ -11263,19 +11439,19 @@ terser@^4.1.2: source-map "~0.6.1" source-map-support "~0.5.12" -terser@^4.4.3: - version "4.6.4" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.4.tgz#40a0b37afbe5b57e494536815efa68326840fc00" - integrity sha512-5fqgBPLgVHZ/fVvqRhhUp9YUiGXhFJ9ZkrZWD9vQtFBR4QIGTnbsb+/kKqSqfgp3WnBwGWAFnedGTtmX1YTn0w== +terser@^4.6.2: + version "4.6.13" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.13.tgz#e879a7364a5e0db52ba4891ecde007422c56a916" + integrity sha512-wMvqukYgVpQlymbnNbabVZbtM6PN63AzqexpwJL8tbh/mRT9LE5o+ruVduAGL7D6Fpjl+Q+06U5I9Ul82odAhw== dependencies: commander "^2.20.0" source-map "~0.6.1" source-map-support "~0.5.12" -terser@^4.6.2: - version "4.6.13" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.13.tgz#e879a7364a5e0db52ba4891ecde007422c56a916" - integrity sha512-wMvqukYgVpQlymbnNbabVZbtM6PN63AzqexpwJL8tbh/mRT9LE5o+ruVduAGL7D6Fpjl+Q+06U5I9Ul82odAhw== +terser@^5.0.0: + version "5.3.2" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.3.2.tgz#f4bea90eb92945b2a028ceef79181b9bb586e7af" + integrity sha512-H67sydwBz5jCUA32ZRL319ULu+Su1cAoZnnc+lXnenGRYWyLE3Scgkt8mNoAsMx0h5kdo758zdoS0LG9rYZXDQ== dependencies: commander "^2.20.0" source-map "~0.6.1" @@ -11398,7 +11574,7 @@ tough-cookie@^3.0.1: psl "^1.1.28" punycode "^2.1.1" -tough-cookie@~2.3.0, tough-cookie@~2.3.3: +tough-cookie@~2.3.0: version "2.3.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561" dependencies: @@ -11434,16 +11610,26 @@ ts-node@~8.3.0: source-map-support "^0.5.6" yn "^3.0.0" -tslib@1.11.1, tslib@^1.11.1: - version "1.11.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" - integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== +ts-pnp@^1.1.6: + version "1.2.0" + resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" + integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== + +tslib@2.0.1, tslib@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e" + integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ== tslib@^1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== +tslib@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" + integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== + tslib@^1.8.1: version "1.9.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" @@ -11519,19 +11705,29 @@ type-is@~1.6.17, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/type/-/type-2.1.0.tgz#9bdc22c648cf8cf86dd23d32336a41cfb6475e3f" + integrity sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA== + typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -typescript@3.6.5: - version "3.6.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.5.tgz#dae20114a7b4ff4bd642db9c8c699f2953e8bbdb" - integrity sha512-BEjlc0Z06ORZKbtcxGrIvvwYs5hAnuo6TKdNFL55frVDlB+na3z5bsLhFaIxmT+dPWgBIjMo6aNnTOgHHmHgiQ== +typescript@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.2.tgz#7ea7c88777c723c681e33bf7988be5d008d05ac2" + integrity sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ== -typescript@~3.8.3: - version "3.8.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061" - integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w== +typescript@~4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.3.tgz#153bbd468ef07725c1df9c77e8b453f8d36abba5" + integrity sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg== ua-parser-js@0.7.12: version "0.7.12" @@ -11547,14 +11743,6 @@ ua-parser-js@0.7.21: resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.21.tgz#853cf9ce93f642f67174273cc34565ae6f308777" integrity sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ== -uglify-js@^3.1.4: - version "3.7.3" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.3.tgz#f918fce9182f466d5140f24bb0ff35c2d32dcc6a" - integrity sha512-7tINm46/3puUA4hCkKYo4Xdts+JDaVC9ZPRcG8Xw9R4nhO/gZgUM3TENq8IF4Vatk8qCig4MzP/c8G4u2BkVQg== - dependencies: - commander "~2.20.3" - source-map "~0.6.1" - uid-number@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" @@ -11650,13 +11838,13 @@ unique-slug@^2.0.0: dependencies: imurmurhash "^0.1.4" -universal-analytics@0.4.20: - version "0.4.20" - resolved "https://registry.yarnpkg.com/universal-analytics/-/universal-analytics-0.4.20.tgz#d6b64e5312bf74f7c368e3024a922135dbf24b03" - integrity sha512-gE91dtMvNkjO+kWsPstHRtSwHXz0l2axqptGYp5ceg4MsuurloM0PU3pdOfpb5zBXUvyjT4PwhWK2m39uczZuw== +universal-analytics@0.4.23: + version "0.4.23" + resolved "https://registry.yarnpkg.com/universal-analytics/-/universal-analytics-0.4.23.tgz#d915e676850c25c4156762471bdd7cf2eaaca8ac" + integrity sha512-lgMIH7XBI6OgYn1woDEmxhGdj8yDefMKg7GkWdeATAlQZFrMrNyxSkpDzY57iY0/6fdlzTbBV03OawvvzG+q7A== dependencies: - debug "^3.0.0" - request "^2.88.0" + debug "^4.1.1" + request "^2.88.2" uuid "^3.0.0" universalify@^0.1.0: @@ -11679,10 +11867,6 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" -upath@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" - upath@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068" @@ -11774,23 +11958,24 @@ utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" -uuid@7.0.2: - version "7.0.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.2.tgz#7ff5c203467e91f5e0d85cfcbaaf7d2ebbca9be6" - integrity sha512-vy9V/+pKG+5ZTYKf+VcphF5Oc6EFiu3W8Nv3P3zIh0EqVI80ZxOzuPfe9EHjkFNvf8+xuTHVeei4Drydlx4zjw== +uuid@8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.0.tgz#ab738085ca22dc9a8c92725e459b1d507df5d6ea" + integrity sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ== -uuid@^3.0.0, uuid@^3.1.0: +uuid@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" -uuid@^3.0.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" - uuid@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" +uuid@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + validate-npm-package-license@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" @@ -11844,14 +12029,23 @@ w3c-xmlserializer@^2.0.0: dependencies: xml-name-validator "^3.0.0" -watchpack@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" - integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== +watchpack-chokidar2@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0" + integrity sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA== + dependencies: + chokidar "^2.1.8" + +watchpack@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.4.tgz#6e9da53b3c80bb2d6508188f5b200410866cd30b" + integrity sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg== dependencies: - chokidar "^2.0.2" graceful-fs "^4.1.2" neo-async "^2.5.0" + optionalDependencies: + chokidar "^3.4.1" + watchpack-chokidar2 "^2.0.0" wbuf@^1.1.0: version "1.7.2" @@ -11880,7 +12074,7 @@ webdriver-js-extender@2.1.0: "@types/selenium-webdriver" "^3.0.0" selenium-webdriver "^3.0.1" -webdriver-manager@^12.0.6: +webdriver-manager@^12.1.7: version "12.1.7" resolved "https://registry.yarnpkg.com/webdriver-manager/-/webdriver-manager-12.1.7.tgz#ed4eaee8f906b33c146e869b55e850553a1b1162" integrity sha512-XINj6b8CYuUYC93SG3xPkxlyUc3IJbD6Vvo75CVGuG9uzsefDzWQrhz0Lq8vbPxtb4d63CZdYophF8k8Or/YiA== @@ -11913,10 +12107,10 @@ webpack-dev-middleware@3.7.2, webpack-dev-middleware@^3.7.2: range-parser "^1.2.1" webpack-log "^2.0.0" -webpack-dev-server@3.10.3: - version "3.10.3" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.10.3.tgz#f35945036813e57ef582c2420ef7b470e14d3af0" - integrity sha512-e4nWev8YzEVNdOMcNzNeCN947sWJNd43E5XvsJzbAL08kGc2frm1tQ32hTJslRS+H65LCb/AaUCYU7fjHCpDeQ== +webpack-dev-server@3.11.0: + version "3.11.0" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz#8f154a3bce1bcfd1cc618ef4e703278855e7ff8c" + integrity sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg== dependencies: ansi-html "0.0.7" bonjour "^3.5.0" @@ -11926,31 +12120,31 @@ webpack-dev-server@3.10.3: debug "^4.1.1" del "^4.1.1" express "^4.17.1" - html-entities "^1.2.1" + html-entities "^1.3.1" http-proxy-middleware "0.19.1" import-local "^2.0.0" internal-ip "^4.3.0" ip "^1.1.5" is-absolute-url "^3.0.3" killable "^1.0.1" - loglevel "^1.6.6" + loglevel "^1.6.8" opn "^5.5.0" p-retry "^3.0.1" - portfinder "^1.0.25" + portfinder "^1.0.26" schema-utils "^1.0.0" selfsigned "^1.10.7" semver "^6.3.0" serve-index "^1.9.1" - sockjs "0.3.19" + sockjs "0.3.20" sockjs-client "1.4.0" - spdy "^4.0.1" + spdy "^4.0.2" strip-ansi "^3.0.1" supports-color "^6.1.0" url "^0.11.0" webpack-dev-middleware "^3.7.2" webpack-log "^2.0.0" ws "^6.2.1" - yargs "12.0.5" + yargs "^13.3.2" webpack-log@^2.0.0: version "2.0.0" @@ -11996,42 +12190,49 @@ webpack-sources@^1.3.0: source-list-map "^2.0.0" source-map "~0.6.1" -webpack-subresource-integrity@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/webpack-subresource-integrity/-/webpack-subresource-integrity-1.4.0.tgz#44963a64c9a214ad729158e7f46d52c2525cc88a" - integrity sha512-GB1kB/LwAWC3CxwcedGhMkxGpNZxSheCe1q+KJP1bakuieAdX/rGHEcf5zsEzhKXpqsGqokgsDoD9dIkr61VDQ== +webpack-subresource-integrity@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/webpack-subresource-integrity/-/webpack-subresource-integrity-1.4.1.tgz#e8bf918b444277df46a66cd84542cbcdc5a6272d" + integrity sha512-XMLFInbGbB1HV7K4vHWANzc1CN0t/c4bBvnlvGxGwV45yE/S/feAXIm8dJsCkzqWtSKnmaEgTp/meyeThxG4Iw== dependencies: webpack-sources "^1.3.0" -webpack@4.42.0: - version "4.42.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.42.0.tgz#b901635dd6179391d90740a63c93f76f39883eb8" - integrity sha512-EzJRHvwQyBiYrYqhyjW9AqM90dE4+s1/XtCfn7uWg6cS72zH+2VPFAlsnW0+W0cDi0XRjNKUMoJtpSi50+Ph6w== +webpack@4.44.1: + version "4.44.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.1.tgz#17e69fff9f321b8f117d1fda714edfc0b939cc21" + integrity sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ== dependencies: - "@webassemblyjs/ast" "1.8.5" - "@webassemblyjs/helper-module-context" "1.8.5" - "@webassemblyjs/wasm-edit" "1.8.5" - "@webassemblyjs/wasm-parser" "1.8.5" - acorn "^6.2.1" + "@webassemblyjs/ast" "1.9.0" + "@webassemblyjs/helper-module-context" "1.9.0" + "@webassemblyjs/wasm-edit" "1.9.0" + "@webassemblyjs/wasm-parser" "1.9.0" + acorn "^6.4.1" ajv "^6.10.2" ajv-keywords "^3.4.1" chrome-trace-event "^1.0.2" - enhanced-resolve "^4.1.0" + enhanced-resolve "^4.3.0" eslint-scope "^4.0.3" json-parse-better-errors "^1.0.2" loader-runner "^2.4.0" loader-utils "^1.2.3" memory-fs "^0.4.1" micromatch "^3.1.10" - mkdirp "^0.5.1" + mkdirp "^0.5.3" neo-async "^2.6.1" node-libs-browser "^2.2.1" schema-utils "^1.0.0" tapable "^1.1.3" terser-webpack-plugin "^1.4.3" - watchpack "^1.6.0" + watchpack "^1.7.4" webpack-sources "^1.4.1" +websocket-driver@0.6.5: + version "0.6.5" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.6.5.tgz#5cb2556ceb85f4373c6d8238aa691c8454e13a36" + integrity sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY= + dependencies: + websocket-extensions ">=0.1.1" + websocket-driver@>=0.5.1: version "0.7.0" resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.0.tgz#0caf9d2d755d93aee049d4bdd0d3fe2cca2a24eb" @@ -12132,10 +12333,10 @@ worker-farm@^1.7.0: dependencies: errno "~0.1.7" -worker-plugin@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/worker-plugin/-/worker-plugin-4.0.2.tgz#0456dd7af1c0de64591326fd8a08c5d9f2b5b27a" - integrity sha512-V+1zSZMOOKk+uBzKyNIODLQLsx59zSIOaI75J1EMS0iR1qy+KQR3y/pQ3T0vIhvPfDFapGRMsoMvQNEL3okqSA== +worker-plugin@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/worker-plugin/-/worker-plugin-5.0.0.tgz#113b5fe1f4a5d6a957cecd29915bedafd70bb537" + integrity sha512-AXMUstURCxDD6yGam2r4E34aJg6kW85IiaeX72hi+I1cxyaMUtrvVY6sbfpGKAj5e7f68Acl62BjQF5aOOx2IQ== dependencies: loader-utils "^1.1.0" @@ -12253,7 +12454,7 @@ y18n@^3.2.0, y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" -"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: +y18n@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" @@ -12271,14 +12472,6 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yargs-parser@^11.1.1: - version "11.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" - integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - yargs-parser@^13.1.1: version "13.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" @@ -12287,6 +12480,14 @@ yargs-parser@^13.1.1: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^18.1.0, yargs-parser@^18.1.1: version "18.1.3" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" @@ -12301,24 +12502,6 @@ yargs-parser@^4.1.0, yargs-parser@^4.2.0: dependencies: camelcase "^3.0.0" -yargs@12.0.5: - version "12.0.5" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" - integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== - dependencies: - cliui "^4.0.0" - decamelize "^1.2.0" - find-up "^3.0.0" - get-caller-file "^1.0.1" - os-locale "^3.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1 || ^4.0.0" - yargs-parser "^11.1.1" - yargs@15.3.0: version "15.3.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.0.tgz#403af6edc75b3ae04bf66c94202228ba119f0976" @@ -12401,6 +12584,22 @@ yargs@^13.3.0: y18n "^4.0.0" yargs-parser "^13.1.1" +yargs@^13.3.2: + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.2" + yargs@^15.3.1: version "15.3.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b" diff --git a/aio/tools/stackblitz-builder/README.md b/aio/tools/stackblitz-builder/README.md index d5f0b763238a5..bd2673e573a97 100644 --- a/aio/tools/stackblitz-builder/README.md +++ b/aio/tools/stackblitz-builder/README.md @@ -1,6 +1,6 @@ # Overview -[Stackblitz](https://stackblitz.com/) is an online tool for creating, collaborating and sharing ideas. +[Stackblitz](https://stackblitz.com/) is an online tool for creating, collaborating and sharing ideas. In AIO we use it to share one or more runnable versions of our examples. Stackblitz can be used both on a separate page and in an embedded form. @@ -8,24 +8,25 @@ Stackblitz can be used both on a separate page and in an embedded form. ## Stackblitz generation -Both forms are created within `builder.js`. How is a stackblitz created? What is the process from a -directory with files to a link with a stackblitz. +Both forms are created within `builder.js`. +How is a stackblitz created? +What is the process from a directory with files to a link with a stackblitz. -An "executable" stackblitz is an HTML file with a `
      ` that makes a post to stackblitz on submit. It -contains an `` element for each file we need in the stackblitz. +An "executable" stackblitz is an HTML file with a `` that makes a post to stackblitz on submit. +It contains an `` element for each file we need in the stackblitz. -The form will be submitted on load, so you can either double click the HTML file or open it with an -anchor tag to open the stackblitz. +The form will be submitted on load, so you can either double click the HTML file or open it with an anchor tag to open the stackblitz. So the `builder.js` job is to get all the needed files from an example and build this HTML file for you. ## Customizing the generation per example basis -How does this tool know what is an example and what is not? It will look for all folders containing a -`stackblitz.json` file. If found, all files within the folder and subfolders will be used in the stackblitz, with -a few generic exceptions that you can find at `builder.js`. +How does this tool know what is an example and what is not? +It will look for all folders containing a `stackblitz.json` file. +If found, all files within the folder and subfolders will be used in the stackblitz, with a few generic exceptions that you can find at `builder.js`. -You can use the `stackblitz.json` to customize the stackblitz generation. For example: +You can use the `stackblitz.json` to customize the stackblitz generation. +For example: ```json { @@ -39,21 +40,21 @@ You can use the `stackblitz.json` to customize the stackblitz generation. For ex } ``` -Here you can specify a description for the stackblitz, some tags and also a files array where you -can specify extra files to add or to ignore. +Here you can specify a description for the stackblitz, some tags and also a files array where you can specify extra files to add or to ignore. ## Executing the stackblitz generation `generateStackblitz.js` will create a stackblitz for each `stackblitz.json` it finds. -Where? At `src/generated/live-examples/`. +Where? +At `src/generated/live-examples/`. Then the `` embedded component will look at this folder to get the stackblitz it needs for the example. ## Appendix: Why not generating stackblitz at runtime? -At AngularJS, all the plunker examples were generated at runtime. The downside was that all the example code had to be -deployed as well and would no longer be useful after the plunker was generated. +At AngularJS, all the plunker examples were generated at runtime. +The downside was that all the example code had to be deployed as well and would no longer be useful after the plunker was generated. This `StackblitzBuilder` tool takes a few seconds to run, and the end result is only 3mb~. diff --git a/aio/tools/transforms/README.md b/aio/tools/transforms/README.md index cbda103a3d9ca..b3547bdf8373d 100644 --- a/aio/tools/transforms/README.md +++ b/aio/tools/transforms/README.md @@ -1,36 +1,27 @@ # Overview -All the content that is rendered by the AIO application, and some of its configuration files, are -generated from source files by [Dgeni](https://github.com/angular/dgeni). Dgeni is a general purpose -documentation generation tool. +All the content that is rendered by the AIO application, and some of its configuration files, are generated from source files by [Dgeni](https://github.com/angular/dgeni). +Dgeni is a general purpose documentation generation tool. -Markdown files in `/aio/content`, code comments in the core Angular source files and example files -are processed and transformed into files that are consumed by the AIO application. +Markdown files in `/aio/content`, code comments in the core Angular source files and example files are processed and transformed into files that are consumed by the AIO application. -Dgeni is configured by "packages", which contain services and processors. Some of these packages are -installed as `node_modules` from the [dgeni-packages](https://github.com/angular/dgeni-packages) and -some are specific to the AIO project. +Dgeni is configured by "packages", which contain services and processors. +Some of these packages are installed as `node_modules` from the [dgeni-packages](https://github.com/angular/dgeni-packages) and some are specific to the AIO project. The project specific packages are stored in this folder (`aio/tools/transforms`). -If you are an author and want to know how to generate the documentation, the steps are outlined in -the top level [README.md](../../README.md#guide-to-authoring). +If you are an author and want to know how to generate the documentation, the steps are outlined in the top level [README.md](../../README.md#guide-to-authoring). ## Root packages -To run Dgeni, you must specify a root package, which acts as the entry point to the documentation -generation. -This root package, in turn requires a number of other packages, some are defined locally in the -`tools/transforms` folder, such as `tools/transforms/cheatsheet-package` and -`tools/transforms/content-package`, etc. And some are brought in from the `dgeni-packages` node -modules, such as `jsdoc` and `nunjucks`. +To run Dgeni, you must specify a root package, which acts as the entry point to the documentation generation. +This root package, in turn requires a number of other packages, some are defined locally in the `tools/transforms` folder, such as `tools/transforms/cheatsheet-package` and `tools/transforms/content-package`, etc. +And some are brought in from the `dgeni-packages` node modules, such as `jsdoc` and `nunjucks`. -* The primary root package is defined in `tools/transforms/angular.io-package/index.js`. This package -is used to run a full generation of all the documentation. -* There are also root packages defined in `tools/transforms/authors-package/*-package.js`. These -packages are used by the documentation authors when writing docs, since it allows them to run partial -doc generation, which is not complete but is faster for quickly seeing changes to the document that -you are working on. +* The primary root package is defined in `tools/transforms/angular.io-package/index.js`. + This package is used to run a full generation of all the documentation. +* There are also root packages defined in `tools/transforms/authors-package/*-package.js`. + These packages are used by the documentation authors when writing docs, since it allows them to run partial doc generation, which is not complete but is faster for quickly seeing changes to the document that you are working on. ## Other packages @@ -46,5 +37,5 @@ you are working on. ## Templates -All the templates for the angular.io dgeni transformations are stoted in the `tools/transforms/templates` -folder. See the [README](./templates/README.md). \ No newline at end of file +All the templates for the angular.io dgeni transformations are stoted in the `tools/transforms/templates` folder. +See the [README](./templates/README.md). diff --git a/aio/tools/transforms/angular-base-package/processors/createSitemap.js b/aio/tools/transforms/angular-base-package/processors/createSitemap.js index e6d320b450dc8..b937ebb83e41e 100644 --- a/aio/tools/transforms/angular-base-package/processors/createSitemap.js +++ b/aio/tools/transforms/angular-base-package/processors/createSitemap.js @@ -5,6 +5,7 @@ module.exports = function createSitemap() { 'contributors-json', 'navigation-json', 'resources-json', + 'events-json' ], ignoredPaths: [ 'file-not-found', diff --git a/aio/tools/transforms/angular-base-package/processors/createSitemap.spec.js b/aio/tools/transforms/angular-base-package/processors/createSitemap.spec.js index 9802f3bcf54b6..f8935c831da5b 100644 --- a/aio/tools/transforms/angular-base-package/processors/createSitemap.spec.js +++ b/aio/tools/transforms/angular-base-package/processors/createSitemap.spec.js @@ -47,7 +47,7 @@ describe('createSitemap processor', () => { expect(docs.pop().urls).toEqual(['abc', 'fgh']); }); - it('ignoring blacklisted doc types', () => { + it('ignoring excluded doc types', () => { const docs = [ { path: 'abc', outputPath: 'abc', docType: 'good' }, { path: 'cde', outputPath: 'cde', docType: 'bad' }, @@ -58,7 +58,7 @@ describe('createSitemap processor', () => { expect(docs.pop().urls).toEqual(['abc', 'fgh']); }); - it('ignoring blacklisted paths', () => { + it('ignoring excluded paths', () => { const docs = [ { path: 'abc', outputPath: 'abc' }, { path: 'cde', outputPath: 'cde' }, diff --git a/aio/tools/transforms/angular-content-package/index.js b/aio/tools/transforms/angular-content-package/index.js index 65f4de1c38475..47d7432ae6da4 100644 --- a/aio/tools/transforms/angular-content-package/index.js +++ b/aio/tools/transforms/angular-content-package/index.js @@ -82,6 +82,11 @@ module.exports = new Package('angular-content', [basePackage, contentPackage]) include: CONTENTS_PATH + '/marketing/resources.json', fileReader: 'jsonFileReader' }, + { + basePath: CONTENTS_PATH, + include: CONTENTS_PATH + '/marketing/events.json', + fileReader: 'jsonFileReader' + }, ]); collectExamples.exampleFolders.push('examples'); @@ -110,7 +115,8 @@ module.exports = new Package('angular-content', [basePackage, contentPackage]) {docTypes: ['navigation-json'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'}, {docTypes: ['contributors-json'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'}, {docTypes: ['announcements-json'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'}, - {docTypes: ['resources-json'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'} + {docTypes: ['resources-json'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'}, + {docTypes: ['events-json'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'} ]); }) diff --git a/aio/tools/transforms/authors-package/api-package.js b/aio/tools/transforms/authors-package/api-package.js index 77698753c0415..d8d34a2412dd1 100644 --- a/aio/tools/transforms/authors-package/api-package.js +++ b/aio/tools/transforms/authors-package/api-package.js @@ -20,8 +20,6 @@ const packageMap = { 'platform-browser': ['platform-browser/index.ts', 'platform-browser/animations/index.ts', 'platform-browser/testing/index.ts'], 'platform-browser-dynamic': ['platform-browser-dynamic/index.ts', 'platform-browser-dynamic/testing/index.ts'], 'platform-server': ['platform-server/index.ts', 'platform-server/testing/index.ts'], - 'platform-webworker': ['platform-webworker/index.ts'], - 'platform-webworker-dynamic': ['platform-webworker-dynamic/index.ts'], router: ['router/index.ts', 'router/testing/index.ts', 'router/upgrade/index.ts'], 'service-worker': ['service-worker/index.ts'], upgrade: ['upgrade/index.ts', 'upgrade/static/index.ts', 'upgrade/static/testing/index.ts'] diff --git a/aio/tools/transforms/templates/api/decorator.template.html b/aio/tools/transforms/templates/api/decorator.template.html index 4212a37166886..7c24766dd6dc7 100644 --- a/aio/tools/transforms/templates/api/decorator.template.html +++ b/aio/tools/transforms/templates/api/decorator.template.html @@ -12,12 +12,16 @@

      Options

      {% for option in doc.members %} - + + + + + @@ -46,4 +51,4 @@

      {$ option.name $}

      - -
      + +
      @@ -26,8 +30,9 @@

      {$ option.name $}

      - - {$ option.name $}: {$ option.type | escape $} + + {$ option.name $}{%- if option.isOptional %}?{% endif -%}: {$ option.type | escape $}
      {% endfor %} -{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/aio/tools/transforms/templates/api/includes/decorator-overview.html b/aio/tools/transforms/templates/api/includes/decorator-overview.html index 657a4933d1ec8..20d20db6c4524 100644 --- a/aio/tools/transforms/templates/api/includes/decorator-overview.html +++ b/aio/tools/transforms/templates/api/includes/decorator-overview.html @@ -10,7 +10,7 @@ - {$ option.name $} + {$ option.name $}{%- if option.isOptional %}?{% endif -%} {$ option.shortDescription | marked $} diff --git a/aio/tools/transforms/templates/api/lib/memberHelpers.html b/aio/tools/transforms/templates/api/lib/memberHelpers.html index 3b7c05515066c..49dc46c02a65e 100644 --- a/aio/tools/transforms/templates/api/lib/memberHelpers.html +++ b/aio/tools/transforms/templates/api/lib/memberHelpers.html @@ -3,7 +3,7 @@ {%- macro renderHeritage(exportDoc) -%} {%- if exportDoc.extendsClauses.length %} extends {% for clause in exportDoc.extendsClauses -%} - {$ clause.text $}{% if not loop.last %}, {% endif -%} + {% if clause.doc.path %}{$ clause.text $}{% else %}{$ clause.text $}{% endif %}{% if not loop.last %}, {% endif -%} {% endfor %}{% endif %} {%- if exportDoc.implementsClauses.length %} implements {% for clause in exportDoc.implementsClauses -%} {$ clause.text $}{% if not loop.last %}, {% endif -%} @@ -132,11 +132,11 @@

      {$ method.overloads.length $} overloads...

      - + Show All Hide All expand_more - +
      diff --git a/aio/tsconfig.json b/aio/tsconfig.json index ce114541d0a69..c4edb3ba2e9d8 100644 --- a/aio/tsconfig.json +++ b/aio/tsconfig.json @@ -1,25 +1,28 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ { "compileOnSave": false, "compilerOptions": { "baseUrl": "src", "outDir": "./out-tsc", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "noUnusedLocals": true, + "noUnusedParameters": true, "sourceMap": true, "declaration": false, - "module": "esnext", - "moduleResolution": "node", + "downlevelIteration": true, "experimentalDecorators": true, + "moduleResolution": "node", "importHelpers": true, "target": "es2015", + "module": "es2020", "lib": [ "es2018", "dom" ], "skipLibCheck": true, - "strict": true, - "noFallthroughCasesInSwitch": true, - "noImplicitReturns": true, - "noUnusedLocals": true, - "noUnusedParameters": true, // disabled because this is on by default in tsc 2.7 breaking our codebase - we need to refactor "strictPropertyInitialization": false }, @@ -35,6 +38,7 @@ "angularCompilerOptions": { "disableTypeScriptVersionCheck": true, "strictInjectionParameters": true, + "strictInputAccessModifiers": true, "strictTemplates": true } } diff --git a/aio/tslint.json b/aio/tslint.json index 4f7ccaf9ed0e8..044f74da1be82 100644 --- a/aio/tslint.json +++ b/aio/tslint.json @@ -11,32 +11,16 @@ ] }, "array-type": false, - "arrow-parens": false, "arrow-return-shorthand": true, "ban": [ true, {"name": "fdescribe", "message": "Don't keep jasmine focus methods."}, {"name": "fit", "message": "Don't keep jasmine focus methods."} ], - "component-class-suffix": true, - "component-selector": [ - true, - "element", - "aio", - "kebab-case" - ], - "contextual-lifecycle": true, "curly": true, "deprecation": { - "severity": "warn" + "severity": "warning" }, - "directive-class-suffix": true, - "directive-selector": [ - true, - "attribute", - "aio", - "camelCase" - ], "eofline": true, "import-blacklist": [ true, @@ -48,13 +32,11 @@ "spaces" ] }, - "interface-name": false, "max-classes-per-file": false, "max-line-length": [ true, 140 ], - "member-access": false, "member-ordering": [ true, { @@ -66,8 +48,8 @@ ] } ], - "no-conflicting-lifecycle": true, - "no-consecutive-blank-lines": false, + // TODO(gkalpak): Fix the code and enable this to align with CLI. (Failures: 114) + // "no-any": true, "no-console": [ true, "debug", @@ -77,24 +59,20 @@ "trace" ], "no-empty": false, - "no-host-metadata-property": true, "no-inferrable-types": [ true, "ignore-params" ], - "no-input-rename": true, - "no-inputs-metadata-property": true, - "no-output-native": true, - "no-output-on-prefix": true, - "no-output-rename": true, - "no-outputs-metadata-property": true, - "no-string-literal": false, + // TODO(gkalpak): Fix the code and enable this to align with CLI. (Failures: 59) + // "no-non-null-assertion": true, + "no-redundant-jsdoc": true, + // TODO(gkalpak): Fix the code and remove this to align with CLI. "no-switch-case-fall-through": true, "no-var-requires": false, - "object-literal-key-quotes": false, - "object-literal-sort-keys": false, - "only-arrow-functions": false, - "ordered-imports": false, + "object-literal-key-quotes": [ + true, + "as-needed" + ], "quotemark": [ true, "single" @@ -113,9 +91,11 @@ "named": "never" } }, - "template-banana-in-box": true, - "template-no-negated-async": true, - "trailing-comma": false, + // TODO(gkalpak): Fix the code and enable this to align with CLI. (Failures: 243) + // "typedef": [ + // true, + // "call-signature" + // ], "typedef-whitespace": { "options": [ { @@ -134,35 +114,61 @@ } ] }, - "use-lifecycle-interface": true, - "use-pipe-transform-interface": true, - "variable-name": [ - true, - "allow-leading-underscore", - "allow-pascal-case", - "ban-keywords", - "check-format", - "require-const-for-all-caps" - ], + "variable-name": { + "options": [ + "ban-keywords", + "check-format", + "allow-leading-underscore", + "allow-pascal-case", + "require-const-for-all-caps" + ] + }, + "whitespace": { + "options": [ + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type", + "check-typecast" + ] + }, + "component-class-suffix": true, + "contextual-lifecycle": true, + "directive-class-suffix": true, + "no-conflicting-lifecycle": true, + "no-host-metadata-property": true, + "no-input-rename": true, + "no-inputs-metadata-property": true, + "no-output-native": true, + "no-output-on-prefix": true, + "no-output-rename": true, + "no-outputs-metadata-property": true, "template-accessibility-alt-text": true, "template-accessibility-elements-content": true, "template-accessibility-label-for": true, "template-accessibility-tabindex-no-positive": true, "template-accessibility-table-scope": true, "template-accessibility-valid-aria": true, + "template-banana-in-box": true, "template-click-events-have-key-events": true, "template-mouse-events-have-key-events": true, "template-no-autofocus": true, "template-no-distracting-elements": true, - "whitespace": { - "options": [ - "check-branch", - "check-decl", - "check-operator", - "check-separator", - "check-type", - "check-typecast" - ] - } + "template-no-negated-async": true, + "use-lifecycle-interface": true, + "use-pipe-transform-interface": true, + "directive-selector": [ + true, + "attribute", + "aio", + "camelCase" + ], + "component-selector": [ + true, + "element", + "aio", + "kebab-case" + ] } } diff --git a/aio/yarn.lock b/aio/yarn.lock index 22211e6a0a4e4..8419c9e157cd9 100644 --- a/aio/yarn.lock +++ b/aio/yarn.lock @@ -2,177 +2,178 @@ # yarn lockfile v1 -"@angular-devkit/architect@0.1000.1": - version "0.1000.1" - resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1000.1.tgz#6ca8529d888b3f5fc1f28863bb744855b67b811e" - integrity sha512-GpoJ+p38feerxwfpJgrjwv/2c47qIX+TMdfKVqbswxLnzK21hXjd0zn6UfovAFwLeL1hRu2O00NDsmQn01gdoA== - dependencies: - "@angular-devkit/core" "10.0.1" - rxjs "6.5.5" - -"@angular-devkit/build-angular@0.1000.1": - version "0.1000.1" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.1000.1.tgz#8073c8826763b6e0d2e5f2dcb21d55be11ce6937" - integrity sha512-rRYtHzy27BM3XjPVqlpQOs+RXAgtiT1Qr6EiLiMcb8Twg4aWHzKF+IITLQL9CSYkpOnY40vHjWZuEVu0qIhEPQ== - dependencies: - "@angular-devkit/architect" "0.1000.1" - "@angular-devkit/build-optimizer" "0.1000.1" - "@angular-devkit/build-webpack" "0.1000.1" - "@angular-devkit/core" "10.0.1" - "@babel/core" "7.9.6" - "@babel/generator" "7.9.6" - "@babel/plugin-transform-runtime" "7.9.6" - "@babel/preset-env" "7.9.6" - "@babel/runtime" "7.9.6" - "@babel/template" "7.8.6" - "@jsdevtools/coverage-istanbul-loader" "3.0.3" - "@ngtools/webpack" "10.0.1" - ajv "6.12.2" - autoprefixer "9.8.0" +"@angular-devkit/architect@0.1001.3": + version "0.1001.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/architect/-/architect-0.1001.3.tgz#168aa424be9d0dad90d1a03129c3999fbf76a1cc" + integrity sha512-WS5IAN6I73jKapiHKYz3U05Kka4eVRmwCk++GWM2uGChluiZsI87eK8vxMS3KWDIqTnAOuMpDt3XWxlASv1nlQ== + dependencies: + "@angular-devkit/core" "10.1.3" + rxjs "6.6.2" + +"@angular-devkit/build-angular@0.1001.3": + version "0.1001.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-angular/-/build-angular-0.1001.3.tgz#8085bcb26394c5dc47ecc4b9d9c7a47dfe9e1df4" + integrity sha512-TQhNNfBeWLLOcXitmBTl2l95/9/2OcVVGyI5bxbpcCn8f9ioRVa2DvIxQLR92aoGkTrp7Vgd12xu07DSuuQwvg== + dependencies: + "@angular-devkit/architect" "0.1001.3" + "@angular-devkit/build-optimizer" "0.1001.3" + "@angular-devkit/build-webpack" "0.1001.3" + "@angular-devkit/core" "10.1.3" + "@babel/core" "7.11.1" + "@babel/generator" "7.11.0" + "@babel/plugin-transform-runtime" "7.11.0" + "@babel/preset-env" "7.11.0" + "@babel/runtime" "7.11.2" + "@babel/template" "7.10.4" + "@jsdevtools/coverage-istanbul-loader" "3.0.5" + "@ngtools/webpack" "10.1.3" + autoprefixer "9.8.6" babel-loader "8.1.0" browserslist "^4.9.1" - cacache "15.0.3" + cacache "15.0.5" caniuse-lite "^1.0.30001032" circular-dependency-plugin "5.2.0" copy-webpack-plugin "6.0.3" core-js "3.6.4" - css-loader "3.5.3" + css-loader "4.2.2" cssnano "4.1.10" file-loader "6.0.0" find-cache-dir "3.3.1" glob "7.1.6" - jest-worker "26.0.0" + jest-worker "26.3.0" karma-source-map-support "1.4.0" - less-loader "6.1.0" - license-webpack-plugin "2.2.0" + less-loader "6.2.0" + license-webpack-plugin "2.3.0" loader-utils "2.0.0" - mini-css-extract-plugin "0.9.0" + mini-css-extract-plugin "0.10.0" minimatch "3.0.4" - open "7.0.4" - parse5 "4.0.0" + open "7.2.0" + parse5 "6.0.1" + parse5-htmlparser2-tree-adapter "6.0.1" pnp-webpack-plugin "1.6.4" - postcss "7.0.31" + postcss "7.0.32" postcss-import "12.0.1" postcss-loader "3.0.0" raw-loader "4.0.1" - regenerator-runtime "0.13.5" + regenerator-runtime "0.13.7" resolve-url-loader "3.1.1" rimraf "3.0.2" - rollup "2.10.9" - rxjs "6.5.5" - sass "1.26.5" - sass-loader "8.0.2" + rollup "2.26.5" + rxjs "6.6.2" + sass "1.26.10" + sass-loader "10.0.1" semver "7.3.2" source-map "0.7.3" - source-map-loader "1.0.0" + source-map-loader "1.0.2" source-map-support "0.5.19" speed-measure-webpack-plugin "1.3.3" style-loader "1.2.1" - stylus "0.54.7" + stylus "0.54.8" stylus-loader "3.0.2" - terser "4.7.0" - terser-webpack-plugin "3.0.1" + terser "5.3.0" + terser-webpack-plugin "4.1.0" tree-kill "1.2.2" - webpack "4.43.0" + webpack "4.44.1" webpack-dev-middleware "3.7.2" webpack-dev-server "3.11.0" webpack-merge "4.2.2" webpack-sources "1.4.3" webpack-subresource-integrity "1.4.1" - worker-plugin "4.0.3" + worker-plugin "5.0.0" -"@angular-devkit/build-optimizer@0.1000.1": - version "0.1000.1" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.1000.1.tgz#2cb46c7b8fc4361d06244d50545b23e91e866c15" - integrity sha512-Q60lxyetBcMKUiNMc1vGUExuJMashHB9CF8HVenX80R9ihaA/GHAUrD2PbKBpLVoC4T291uUhfcA8MB1fJNRfw== +"@angular-devkit/build-optimizer@0.1001.3": + version "0.1001.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-optimizer/-/build-optimizer-0.1001.3.tgz#11e6ea59ab0d6f6c0724c9453c82a2f15653534d" + integrity sha512-tQy4ADOVDL0hJcykpZzqfInQV6ft499E3g+D0jcZL/imSsxH4EaaBA2HCc0JTeAFjmkI32OhD9T8G/swqqBcVw== dependencies: loader-utils "2.0.0" source-map "0.7.3" - tslib "2.0.0" + tslib "2.0.1" + typescript "4.0.2" webpack-sources "1.4.3" -"@angular-devkit/build-webpack@0.1000.1": - version "0.1000.1" - resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1000.1.tgz#c0e8208dfa52ca1743955c6ae96fb1d7685103e1" - integrity sha512-m+abxD38LYdHw+w53Rmc4MbuwDP7rfevAZ/1QR2WFYj0BI5QsTYGlpmieI2TXiwiwvTILn9UzYZAA16nKvmUwA== +"@angular-devkit/build-webpack@0.1001.3": + version "0.1001.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/build-webpack/-/build-webpack-0.1001.3.tgz#889aaa2dde7daacb88969d9ede5ba2df94250df3" + integrity sha512-XpAEWRWIdh/bk2UHkP7iIjEiVwkQkAWoZPNYMJzg3iN/iAAdUDPiNBTXhFZEZjFEWT0RXl4iKW2hr5LFvpe6lw== dependencies: - "@angular-devkit/architect" "0.1000.1" - "@angular-devkit/core" "10.0.1" - rxjs "6.5.5" + "@angular-devkit/architect" "0.1001.3" + "@angular-devkit/core" "10.1.3" + rxjs "6.6.2" -"@angular-devkit/core@10.0.1": - version "10.0.1" - resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-10.0.1.tgz#acc1c6a088507e7340964c8cbf85e91781e86686" - integrity sha512-AXsxN00zbixi/9HyzzsDGm6rtMferxKfhG8WPJfp/0TLeJrmiLs5wdNjk8LhfTZABSTYx/QxRgOI6OnBoXePgg== +"@angular-devkit/core@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/core/-/core-10.1.3.tgz#48776a87253b40f6005b14413e089a1fee6b7227" + integrity sha512-Ub31/eqFtSuQy3V+B74Jt0jAUw8fs8sbd0ZL2UHYUJyrwm20iIRam+mOD3Sj8HFrDGLR8m56KsxJ12KvC1oxtQ== dependencies: - ajv "6.12.2" + ajv "6.12.4" fast-json-stable-stringify "2.1.0" magic-string "0.25.7" - rxjs "6.5.5" + rxjs "6.6.2" source-map "0.7.3" -"@angular-devkit/schematics@10.0.1": - version "10.0.1" - resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-10.0.1.tgz#2631043e7459c5d1228ffeba18eb63aa1e45f40e" - integrity sha512-lG70f4KsZews/z1npzJC7ccJgz3RXyLetyg+wa5uGWV+Silpr7XX+3U65DjPwG/+921woifeqRMbOhK+zCCaVA== +"@angular-devkit/schematics@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular-devkit/schematics/-/schematics-10.1.3.tgz#49ccf51a1a8e71625b5ec1a0d24adfc24c31c903" + integrity sha512-5+E2bBBsphuz1KfloC5yA+hXSEbxMokkp5UEp+X9VC7zUGTXV8sxuvcbBo+JVutaoNHezJGu2JUx/LqNrKd58w== dependencies: - "@angular-devkit/core" "10.0.1" - ora "4.0.4" - rxjs "6.5.5" + "@angular-devkit/core" "10.1.3" + ora "5.0.0" + rxjs "6.6.2" -"@angular/animations@10.0.2": - version "10.0.2" - resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-10.0.2.tgz#4af6983800c7e6fbb402f7183fc547ae480cb534" - integrity sha512-3fMR574KnaeAon7ZlwYCB2qkUoZ255Y2KwU6Z/ki37U66QZc8XMqf/d4oUiTZgLsJG4a5Whse0IX8Jz5/HAvQQ== +"@angular/animations@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-10.1.3.tgz#2047dae5fc1bf0f5173a410f0103fb003113d1b9" + integrity sha512-qIdxP28iF6qaoGBB3C6VvHt22nR3FMK5kh+no+jYmmy6z5cBVhwS/Vb6nkx+XRqivKBVHxWNZQ4ae6xmTg/k7A== dependencies: tslib "^2.0.0" -"@angular/cdk@10.0.1": - version "10.0.1" - resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-10.0.1.tgz#8e10317cd6fee4d9f8a3794998629496fb60e68b" - integrity sha512-tEgaTDQplptbOf4cHHdVScH0h5QNvkWDhabAWpWaT4/dVXEsp+p2E9Pzkemesi/gNmUIetVjGaicX5VqsijZSQ== +"@angular/cdk@10.2.2": + version "10.2.2" + resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-10.2.2.tgz#429816d2f8d15d1da99b85ee6810d54bf46e3d05" + integrity sha512-DVMnj7QY1prZblRjYfDeyEH79p1TDI0JGgg2D2BAWwzMoPKCgVCqy1uRuvi+WNhYoDR3QJJJ8tXLKucUoShuIw== dependencies: tslib "^2.0.0" optionalDependencies: parse5 "^5.0.0" -"@angular/cli@10.0.1": - version "10.0.1" - resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-10.0.1.tgz#23fd9e6495a89d7fe1bc756fdfb5af9c71bcaf26" - integrity sha512-6Ht3022UcaWTBDnQKgcvTHbOP4ITjzn1DcZWKN0+zKk4PNqOwWtOEF2CBokOG79gTQVdrp2p5YQo5uX6UG7KMQ== - dependencies: - "@angular-devkit/architect" "0.1000.1" - "@angular-devkit/core" "10.0.1" - "@angular-devkit/schematics" "10.0.1" - "@schematics/angular" "10.0.1" - "@schematics/update" "0.1000.1" +"@angular/cli@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-10.1.3.tgz#188f99583814e97727787869065d228c1b1f4407" + integrity sha512-wj+ZcTLRzM94asLUZRO5U96CLEsnWosa3Iqub+1AH1/C8Wv2w/2njUKDM7ifQeebYzjPb5EcN4EIAGcHAGyeWw== + dependencies: + "@angular-devkit/architect" "0.1001.3" + "@angular-devkit/core" "10.1.3" + "@angular-devkit/schematics" "10.1.3" + "@schematics/angular" "10.1.3" + "@schematics/update" "0.1001.3" "@yarnpkg/lockfile" "1.1.0" ansi-colors "4.1.1" debug "4.1.1" ini "1.3.5" - inquirer "7.1.0" + inquirer "7.3.3" npm-package-arg "8.0.1" npm-pick-manifest "6.1.0" - open "7.0.4" + open "7.2.0" pacote "9.5.12" read-package-tree "5.3.1" rimraf "3.0.2" semver "7.3.2" symbol-observable "1.2.0" - universal-analytics "0.4.20" - uuid "8.1.0" + universal-analytics "0.4.23" + uuid "8.3.0" -"@angular/common@10.0.2": - version "10.0.2" - resolved "https://registry.yarnpkg.com/@angular/common/-/common-10.0.2.tgz#8d5422b3a3e1bc405606476b90b0caffc9c9155a" - integrity sha512-zpNB2XD6jinXZjfihoO5Q1Yg7urfpZTt/fitdmwFHCcQ/1qZ9T2BVh8+VqVRkh6Pjxmtvu0uPnJ1a/aZ5f9r9A== +"@angular/common@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/common/-/common-10.1.3.tgz#43b63609e3ef321d8b6835a5cd339587bf0aecbe" + integrity sha512-+9UsK+ZTCLO3MvTYlDTbjJGAZxtK9WftHWxbT3NTAJ8tisDfb+MwXB0xNw7qLOysMe3u04zShT0YXYZo5aJBrw== dependencies: tslib "^2.0.0" -"@angular/compiler-cli@10.0.2": - version "10.0.2" - resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-10.0.2.tgz#8f178a03989e0018890c52807df9e3e03faaf47a" - integrity sha512-LGX86k1hOyaw5aPCjFfoLuPhVLKMENOdCBeNBzZB+H2CUGHfv8OWFB1EzjZO1N07VGR7JoMx9ZWSP7ornhuS4Q== +"@angular/compiler-cli@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-10.1.3.tgz#e3b7dc11a362ec9fe70060e3730547a7e57cb69a" + integrity sha512-31XZ6jv4Vjsaa0kF+gzeHMyQiMILpaaZa+j1f5IqeS+HBl1ThxLTCpAhR1TVfZ/2EZV6uAM8o8FTYrhscy9qTA== dependencies: canonical-path "1.0.0" chokidar "^3.0.0" @@ -188,38 +189,34 @@ tslib "^2.0.0" yargs "15.3.0" -"@angular/compiler@10.0.2": - version "10.0.2" - resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-10.0.2.tgz#1056af84ad76763f03228aa3a60b63a5cd775944" - integrity sha512-TNE5ESDlRCVneb/K62HOEgLpxuZZTlw8RcmOy5vt3SngEVc576OE/aYsEA6MCwTlqj16GLSS3jGm9HBJcBKUVw== +"@angular/compiler@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-10.1.3.tgz#84c2da8c37d02a7b7337ae34c173ce1d90d57d9a" + integrity sha512-rfiXkf6BPFWHLU0rg+c5BgTdrxVJcyOQipKw3iI2W00RsU3VCFTXKYpm10DamhRrNOf8rJcboqMbdi34awy6xA== dependencies: tslib "^2.0.0" -"@angular/compiler@~8.2.14": - version "8.2.14" - resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-8.2.14.tgz#46db7a9d1c17f236126518ff26480c160d5a6183" - integrity sha512-ABZO4E7eeFA1QyJ2trDezxeQM5ZFa1dXw1Mpl/+1vuXDKNjJgNyWYwKp/NwRkLmrsuV0yv4UDCDe4kJOGbPKnw== - dependencies: - tslib "^1.9.0" +"@angular/compiler@9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-9.0.0.tgz#87e0bef4c369b6cadae07e3a4295778fc93799d5" + integrity sha512-ctjwuntPfZZT2mNj2NDIVu51t9cvbhl/16epc5xEwyzyDt76pX9UgwvY+MbXrf/C/FWwdtmNtfP698BKI+9leQ== -"@angular/core@10.0.2": - version "10.0.2" - resolved "https://registry.yarnpkg.com/@angular/core/-/core-10.0.2.tgz#d2d2c2dd4a9e80dcccc63c274f13ab7397ee5a3b" - integrity sha512-r4M1D2NOdkmmFyvYLHRYSIBKTGNXQarZHDZcm5oEq2eTsRVe2u9MYIeOpHKeVQCQK7XKQVB13IZQP3XpUvljFg== +"@angular/core@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-10.1.3.tgz#7dbc38eb73a1d526d9c2aca3025c42e38c4acdc3" + integrity sha512-2rnNa8bSH1JoQRzUWXXvPGgxtNA6mSiIqDZs1tHdQZxJI15NbyAJhw6lglgBFahE/nOcUx+11ZhxaPJWSsbEOg== dependencies: tslib "^2.0.0" -"@angular/core@~8.2.14": - version "8.2.14" - resolved "https://registry.yarnpkg.com/@angular/core/-/core-8.2.14.tgz#35566f5b19480369229477e7e0e0fde740bd5204" - integrity sha512-zeePkigi+hPh3rN7yoNENG/YUBUsIvUXdxx+AZq+QPaFeKEA2FBSrKn36ojHFrdJUjKzl0lPMEiGC2b6a6bo6g== - dependencies: - tslib "^1.9.0" +"@angular/core@9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-9.0.0.tgz#227dc53e1ac81824f998c6e76000b7efc522641e" + integrity sha512-6Pxgsrf0qF9iFFqmIcWmjJGkkCaCm6V5QNnxMy2KloO3SDq6QuMVRbN9RtC8Urmo25LP+eZ6ZgYqFYpdD8Hd9w== -"@angular/elements@10.0.2": - version "10.0.2" - resolved "https://registry.yarnpkg.com/@angular/elements/-/elements-10.0.2.tgz#42464da37306ada1a5c9c8db00e0395b5a6939f0" - integrity sha512-ZYOuDojWJCCiRoZYXPtGhVVPT1y75V/wktzaMKLcNY/MxnJYW984i/Ynv7gdeqC8kvf0v1s0FkF7t1xndUwbCA== +"@angular/elements@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/elements/-/elements-10.1.3.tgz#a1b63a55f9f0f6bf150a7511a4fb20639869a767" + integrity sha512-eKgXIQlt1aRQc7QyoEZI0D0qsPn2banQuhJmLxKqjELNO8WJZt8VNEAvFMa3a2LO+OaVr6rv0YZhYYki5hkLiQ== dependencies: tslib "^2.0.0" @@ -230,50 +227,45 @@ dependencies: tslib "^2.0.0" -"@angular/forms@10.0.2": - version "10.0.2" - resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-10.0.2.tgz#fa443f73156640664a9e018aaeb42f85d6d20fcb" - integrity sha512-qnfApb5Q58SFdl8za8i6ijvP0UfVGxxTtIVnf8czVU5Jz5/KYDbPeChVw/aPl3hfXq8jt0Q6Yl99aAm/BNyhpQ== +"@angular/forms@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-10.1.3.tgz#c48a9c79bc50b21017685037ad628ff0bc8d5e61" + integrity sha512-ntLnIZnEo+9ziajnjQPYvVR5m0gRfQBbXx5dug4EuUI5SzE2WzcTEZTnltgw4cLqOy/fOt8cXMiW0YeRBHsjKA== dependencies: tslib "^2.0.0" -"@angular/language-service@10.0.2": - version "10.0.2" - resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-10.0.2.tgz#31f22020be96ab2cf77283e0627f8a6fffedfe36" - integrity sha512-kEMJ3DkprpoGJvEjvH/PZrBKtgCbLtFYtrXHRDy2+92vgCT0Xz6TwzZ2qlwlQSijffOgsV5LwdjI4oxpgVKReQ== - -"@angular/material@10.0.1": - version "10.0.1" - resolved "https://registry.yarnpkg.com/@angular/material/-/material-10.0.1.tgz#f59988499d20ee4ab93292d7e9a9d16ce24839f0" - integrity sha512-4xGIupOiPbyYG/tTbVhgjATRZSRf+Xj2FGkX3csSlIOvhrFtN1B9gTlcbOjzWHPpWTFChZALzMXA/841KA9QqA== +"@angular/material@10.2.2": + version "10.2.2" + resolved "https://registry.yarnpkg.com/@angular/material/-/material-10.2.2.tgz#224864e3c280ee2e8f0ccf28574c65d788799782" + integrity sha512-xRt8FsjY/MdC/dMBhitCXmOfXo4uhzLZ+kBqkKwY8gBsJ7FjhJIPbe/kRPBuzvVkVphrEfi/pMeDOge8v5ETbA== dependencies: tslib "^2.0.0" -"@angular/platform-browser-dynamic@10.0.2": - version "10.0.2" - resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-10.0.2.tgz#b752e2110e5a4316087ce7922227b453e423c144" - integrity sha512-R1rt1/Ynm0DHgzMBcduCPoDg2y3MrYZVgT+N0DLobr2nCaVD74vGsJBVCRv7/m1sdCxyhPlOvq8Bm5sRauw2fw== +"@angular/platform-browser-dynamic@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-10.1.3.tgz#e90f9329f2ccbfe817680f16a00686440653ee06" + integrity sha512-JGVz0XxiZuF1FGJ2zUk1/TogIlBFgFCUgNbSyULIfE/UXcuuvvLlzF+ls26tHK06lFHRAVHFjjDpyA270UzRTQ== dependencies: tslib "^2.0.0" -"@angular/platform-browser@10.0.2": - version "10.0.2" - resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-10.0.2.tgz#518db3bdff9692cc4ec0c871f3305218da66aebd" - integrity sha512-FLS3fYSuWvrDc7PiVCvs4joWZZxDe9+alJi90Sub1oBS/EnxmZpkS0Gr7zQv4MjAvVhNCVoTzL3CaV/SIoZqaw== +"@angular/platform-browser@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-10.1.3.tgz#f6a5c5098e878b964cfddc296fb63eb147710211" + integrity sha512-Y5/M9NEmQceda96a9ntmxidfgJTf23DmEvGw0SJ1TAn2X9EjlM4s7H8KNH9R/tDPK9QcuvzX9FTZsxQ9b6kCFQ== dependencies: tslib "^2.0.0" -"@angular/router@10.0.2": - version "10.0.2" - resolved "https://registry.yarnpkg.com/@angular/router/-/router-10.0.2.tgz#6514540f4f3179d8be3fd23b1f4a0dd02801a314" - integrity sha512-IcA3W+r5T0NC8TM4J9F0VOxG0wr7nJOSef6Qek6utZd6ByLlXxOhBrPIC5Ou+QNZeg9OuI2FBt6coea9jgmNOA== +"@angular/router@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/router/-/router-10.1.3.tgz#42b4c173bba8441a3e1eb6f1ca60e3b2a4eb3e86" + integrity sha512-CAd6u1y+NjB8edtuC2j2OpS6xFO+s90bg4kyu7zr9i0wIQX8xI+neFzkTeoYWJ0PNfi05cCGelyQnLZPZFsyvw== dependencies: tslib "^2.0.0" -"@angular/service-worker@10.0.2": - version "10.0.2" - resolved "https://registry.yarnpkg.com/@angular/service-worker/-/service-worker-10.0.2.tgz#1414f4b7721a45c97c9a3efc6b7516453643d55d" - integrity sha512-PXbh5k7yba+X18o2nNqST92Mcsq+5CXDaYIwUcUkYhx1omAMHhYF9W+FFJSY/EhW2yx5x4aRoh9ZmOqldsQB9A== +"@angular/service-worker@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@angular/service-worker/-/service-worker-10.1.3.tgz#f5e8aa4663d6aae059c338cf796ae49ccd827c14" + integrity sha512-Zs8W+CCPxGGQFpF8BahF/ngwAnUOeFZIICfEdZaYnwwxFNWuJcwBRTc8DARyR58Ggc3wncZYd6KbHs+oa1n6Lg== dependencies: tslib "^2.0.0" @@ -284,40 +276,40 @@ dependencies: "@babel/highlight" "^7.8.3" -"@babel/code-frame@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.1.tgz#d5481c5095daa1c57e16e54c6f9198443afb49ff" - integrity sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw== +"@babel/code-frame@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" + integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== dependencies: - "@babel/highlight" "^7.10.1" + "@babel/highlight" "^7.10.4" -"@babel/compat-data@^7.10.1", "@babel/compat-data@^7.9.6": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.10.1.tgz#b1085ffe72cd17bf2c0ee790fc09f9626011b2db" - integrity sha512-CHvCj7So7iCkGKPRFUfryXIkU2gSBw7VSZFYLsqVhrS47269VK2Hfi9S/YcublPMW8k1u2bQBlbDruoQEm4fgw== +"@babel/compat-data@^7.10.4", "@babel/compat-data@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.11.0.tgz#e9f73efe09af1355b723a7f39b11bad637d7c99c" + integrity sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ== dependencies: browserslist "^4.12.0" invariant "^2.2.4" semver "^5.5.0" -"@babel/core@7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.9.6.tgz#d9aa1f580abf3b2286ef40b6904d390904c63376" - integrity sha512-nD3deLvbsApbHAHttzIssYqgb883yU/d9roe4RZymBCDaZryMJDbptVpEpeQuRh4BJ+SYI8le9YGxKvFEvl1Wg== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.9.6" - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helpers" "^7.9.6" - "@babel/parser" "^7.9.6" - "@babel/template" "^7.8.6" - "@babel/traverse" "^7.9.6" - "@babel/types" "^7.9.6" +"@babel/core@7.11.1": + version "7.11.1" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.1.tgz#2c55b604e73a40dc21b0e52650b11c65cf276643" + integrity sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.0" + "@babel/helper-module-transforms" "^7.11.0" + "@babel/helpers" "^7.10.4" + "@babel/parser" "^7.11.1" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.11.0" + "@babel/types" "^7.11.0" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.1" json5 "^2.1.2" - lodash "^4.17.13" + lodash "^4.17.19" resolve "^1.3.2" semver "^5.4.1" source-map "^0.5.0" @@ -343,24 +335,22 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@7.9.6", "@babel/generator@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.9.6.tgz#5408c82ac5de98cda0d77d8124e99fa1f2170a43" - integrity sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ== +"@babel/generator@7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.0.tgz#4b90c78d8c12825024568cbe83ee6c9af193585c" + integrity sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ== dependencies: - "@babel/types" "^7.9.6" + "@babel/types" "^7.11.0" jsesc "^2.5.1" - lodash "^4.17.13" source-map "^0.5.0" -"@babel/generator@^7.10.1": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.10.2.tgz#0fa5b5b2389db8bfdfcc3492b551ee20f5dd69a9" - integrity sha512-AxfBNHNu99DTMvlUPlt1h2+Hn7knPpH5ayJ8OqDWSeLld+Fi2AYBTC/IejWDM9Edcii4UzZRCsbUt0WlSDsDsA== +"@babel/generator@^7.11.0", "@babel/generator@^7.11.5": + version "7.11.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.6.tgz#b868900f81b163b4d464ea24545c61cbac4dc620" + integrity sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA== dependencies: - "@babel/types" "^7.10.2" + "@babel/types" "^7.11.5" jsesc "^2.5.1" - lodash "^4.17.13" source-map "^0.5.0" "@babel/generator@^7.4.0", "@babel/generator@^7.8.4": @@ -373,22 +363,12 @@ lodash "^4.17.13" source-map "^0.5.0" -"@babel/generator@^7.8.6": - version "7.8.8" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.8.tgz#cdcd58caab730834cee9eeadb729e833b625da3e" - integrity sha512-HKyUVu69cZoclptr8t8U5b6sx6zoWjh8jiUhnuj3MpZuKT2dJ8zPTuiy31luq32swhI0SpwItCIlU8XW7BZeJg== +"@babel/helper-annotate-as-pure@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3" + integrity sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA== dependencies: - "@babel/types" "^7.8.7" - jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" - -"@babel/helper-annotate-as-pure@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.1.tgz#f6d08acc6f70bbd59b436262553fb2e259a1a268" - integrity sha512-ewp3rvJEwLaHgyWGe4wQssC2vjks3E80WiUe2BpMb0KhreTjMROCbxXcEovTrbeGVdQct5VjQfrv9EgC+xMzCw== - dependencies: - "@babel/types" "^7.10.1" + "@babel/types" "^7.10.4" "@babel/helper-annotate-as-pure@^7.8.3": version "7.8.3" @@ -397,25 +377,46 @@ dependencies: "@babel/types" "^7.8.3" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz#c84097a427a061ac56a1c30ebf54b7b22d241503" - integrity sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" + integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg== dependencies: - "@babel/helper-explode-assignable-expression" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/helper-explode-assignable-expression" "^7.10.4" + "@babel/types" "^7.10.4" -"@babel/helper-compilation-targets@^7.9.6": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.2.tgz#a17d9723b6e2c750299d2a14d4637c76936d8285" - integrity sha512-hYgOhF4To2UTB4LTaZepN/4Pl9LD4gfbJx8A34mqoluT8TLbof1mhUlYuNWTEebONa8+UlCC4X0TEXu7AOUyGA== +"@babel/helper-compilation-targets@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz#804ae8e3f04376607cc791b9d47d540276332bd2" + integrity sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ== dependencies: - "@babel/compat-data" "^7.10.1" + "@babel/compat-data" "^7.10.4" browserslist "^4.12.0" invariant "^2.2.4" levenary "^1.1.1" semver "^5.5.0" +"@babel/helper-create-class-features-plugin@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d" + integrity sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.10.5" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" + +"@babel/helper-create-regexp-features-plugin@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8" + integrity sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-regex" "^7.10.4" + regexpu-core "^4.7.0" + "@babel/helper-create-regexp-features-plugin@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.3.tgz#c774268c95ec07ee92476a3862b75cc2839beb79" @@ -433,31 +434,30 @@ "@babel/helper-regex" "^7.8.3" regexpu-core "^4.7.0" -"@babel/helper-define-map@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.1.tgz#5e69ee8308648470dd7900d159c044c10285221d" - integrity sha512-+5odWpX+OnvkD0Zmq7panrMuAGQBu6aPUgvMzuMGo4R+jUOvealEj2hiqI6WhxgKrTpFoFj0+VdsuA8KDxHBDg== +"@babel/helper-define-map@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" + integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ== dependencies: - "@babel/helper-function-name" "^7.10.1" - "@babel/types" "^7.10.1" - lodash "^4.17.13" + "@babel/helper-function-name" "^7.10.4" + "@babel/types" "^7.10.5" + lodash "^4.17.19" -"@babel/helper-explode-assignable-expression@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz#a728dc5b4e89e30fc2dfc7d04fa28a930653f982" - integrity sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw== +"@babel/helper-explode-assignable-expression@^7.10.4": + version "7.11.4" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz#2d8e3470252cc17aba917ede7803d4a7a276a41b" + integrity sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ== dependencies: - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/types" "^7.10.4" -"@babel/helper-function-name@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz#92bd63829bfc9215aca9d9defa85f56b539454f4" - integrity sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ== +"@babel/helper-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" + integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== dependencies: - "@babel/helper-get-function-arity" "^7.10.1" - "@babel/template" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helper-function-name@^7.8.3": version "7.8.3" @@ -468,21 +468,12 @@ "@babel/template" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/helper-function-name@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz#2b53820d35275120e1874a82e5aabe1376920a5c" - integrity sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw== - dependencies: - "@babel/helper-get-function-arity" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/types" "^7.9.5" - -"@babel/helper-get-function-arity@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz#7303390a81ba7cb59613895a192b93850e373f7d" - integrity sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw== +"@babel/helper-get-function-arity@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" + integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== dependencies: - "@babel/types" "^7.10.1" + "@babel/types" "^7.10.4" "@babel/helper-get-function-arity@^7.8.3": version "7.8.3" @@ -491,90 +482,63 @@ dependencies: "@babel/types" "^7.8.3" -"@babel/helper-hoist-variables@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.1.tgz#7e77c82e5dcae1ebf123174c385aaadbf787d077" - integrity sha512-vLm5srkU8rI6X3+aQ1rQJyfjvCBLXP8cAGeuw04zeAM2ItKb1e7pmVmLyHb4sDaAYnLL13RHOZPLEtcGZ5xvjg== +"@babel/helper-hoist-variables@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" + integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA== dependencies: - "@babel/types" "^7.10.1" + "@babel/types" "^7.10.4" -"@babel/helper-member-expression-to-functions@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz#432967fd7e12a4afef66c4687d4ca22bc0456f15" - integrity sha512-u7XLXeM2n50gb6PWJ9hoO5oO7JFPaZtrh35t8RqKLT1jFKj9IWeD1zrcrYp1q1qiZTdEarfDWfTIP8nGsu0h5g== +"@babel/helper-member-expression-to-functions@^7.10.4", "@babel/helper-member-expression-to-functions@^7.10.5": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df" + integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q== dependencies: - "@babel/types" "^7.10.1" + "@babel/types" "^7.11.0" -"@babel/helper-member-expression-to-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" - integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA== +"@babel/helper-module-imports@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" + integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw== dependencies: - "@babel/types" "^7.8.3" + "@babel/types" "^7.10.4" -"@babel/helper-module-imports@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz#dd331bd45bccc566ce77004e9d05fe17add13876" - integrity sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg== +"@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.10.5", "@babel/helper-module-transforms@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359" + integrity sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg== dependencies: - "@babel/types" "^7.10.1" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/template" "^7.10.4" + "@babel/types" "^7.11.0" + lodash "^4.17.19" -"@babel/helper-module-imports@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498" - integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg== +"@babel/helper-optimise-call-expression@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" + integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== dependencies: - "@babel/types" "^7.8.3" - -"@babel/helper-module-transforms@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz#24e2f08ee6832c60b157bb0936c86bef7210c622" - integrity sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg== - dependencies: - "@babel/helper-module-imports" "^7.10.1" - "@babel/helper-replace-supers" "^7.10.1" - "@babel/helper-simple-access" "^7.10.1" - "@babel/helper-split-export-declaration" "^7.10.1" - "@babel/template" "^7.10.1" - "@babel/types" "^7.10.1" - lodash "^4.17.13" - -"@babel/helper-module-transforms@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz#43b34dfe15961918707d247327431388e9fe96e5" - integrity sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA== - dependencies: - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.6" - "@babel/helper-simple-access" "^7.8.3" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/template" "^7.8.6" - "@babel/types" "^7.9.0" - lodash "^4.17.13" - -"@babel/helper-optimise-call-expression@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz#b4a1f2561870ce1247ceddb02a3860fa96d72543" - integrity sha512-a0DjNS1prnBsoKx83dP2falChcs7p3i8VMzdrSbfLhuQra/2ENC4sbri34dz/rWmDADsmF1q5GbfaXydh0Jbjg== - dependencies: - "@babel/types" "^7.10.1" - -"@babel/helper-optimise-call-expression@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9" - integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ== - dependencies: - "@babel/types" "^7.8.3" + "@babel/types" "^7.10.4" "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== -"@babel/helper-plugin-utils@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.1.tgz#ec5a5cf0eec925b66c60580328b122c01230a127" - integrity sha512-fvoGeXt0bJc7VMWZGCAEBEMo/HAjW2mP8apF5eXK0wSqwLAVHAISCWRoLMBMUs2kqeaG77jltVqu4Hn8Egl3nA== +"@babel/helper-plugin-utils@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" + integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== + +"@babel/helper-regex@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.5.tgz#32dfbb79899073c415557053a19bd055aae50ae0" + integrity sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg== + dependencies: + lodash "^4.17.19" "@babel/helper-regex@^7.8.3": version "7.8.3" @@ -583,69 +547,47 @@ dependencies: lodash "^4.17.13" -"@babel/helper-remap-async-to-generator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz#273c600d8b9bf5006142c1e35887d555c12edd86" - integrity sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-wrap-function" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" - -"@babel/helper-replace-supers@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz#ec6859d20c5d8087f6a2dc4e014db7228975f13d" - integrity sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A== +"@babel/helper-remap-async-to-generator@^7.10.4": + version "7.11.4" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz#4474ea9f7438f18575e30b0cac784045b402a12d" + integrity sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA== dependencies: - "@babel/helper-member-expression-to-functions" "^7.10.1" - "@babel/helper-optimise-call-expression" "^7.10.1" - "@babel/traverse" "^7.10.1" - "@babel/types" "^7.10.1" - -"@babel/helper-replace-supers@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz#91192d25f6abbcd41da8a989d4492574fb1530bc" - integrity sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.8.3" - "@babel/helper-optimise-call-expression" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-wrap-function" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" -"@babel/helper-replace-supers@^7.8.6": - version "7.8.6" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz#5ada744fd5ad73203bf1d67459a27dcba67effc8" - integrity sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA== +"@babel/helper-replace-supers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" + integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A== dependencies: - "@babel/helper-member-expression-to-functions" "^7.8.3" - "@babel/helper-optimise-call-expression" "^7.8.3" - "@babel/traverse" "^7.8.6" - "@babel/types" "^7.8.6" + "@babel/helper-member-expression-to-functions" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" -"@babel/helper-simple-access@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz#08fb7e22ace9eb8326f7e3920a1c2052f13d851e" - integrity sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw== +"@babel/helper-simple-access@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz#0f5ccda2945277a2a7a2d3a821e15395edcf3461" + integrity sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw== dependencies: - "@babel/template" "^7.10.1" - "@babel/types" "^7.10.1" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" -"@babel/helper-simple-access@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz#7f8109928b4dab4654076986af575231deb639ae" - integrity sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw== +"@babel/helper-skip-transparent-expression-wrappers@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz#eec162f112c2f58d3af0af125e3bb57665146729" + integrity sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q== dependencies: - "@babel/template" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/types" "^7.11.0" -"@babel/helper-split-export-declaration@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz#c6f4be1cbc15e3a868e4c64a17d5d31d754da35f" - integrity sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g== +"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" + integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== dependencies: - "@babel/types" "^7.10.1" + "@babel/types" "^7.11.0" "@babel/helper-split-export-declaration@^7.8.3": version "7.8.3" @@ -654,25 +596,34 @@ dependencies: "@babel/types" "^7.8.3" -"@babel/helper-validator-identifier@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz#5770b0c1a826c4f53f5ede5e153163e0318e94b5" - integrity sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw== +"@babel/helper-validator-identifier@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" + integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== "@babel/helper-validator-identifier@^7.9.5": version "7.9.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80" integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g== -"@babel/helper-wrap-function@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610" - integrity sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ== +"@babel/helper-wrap-function@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" + integrity sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug== dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/template" "^7.8.3" - "@babel/traverse" "^7.8.3" - "@babel/types" "^7.8.3" + "@babel/helper-function-name" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helpers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044" + integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA== + dependencies: + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" "@babel/helpers@^7.8.4": version "7.8.4" @@ -683,21 +634,12 @@ "@babel/traverse" "^7.8.4" "@babel/types" "^7.8.3" -"@babel/helpers@^7.9.6": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.1.tgz#a6827b7cb975c9d9cef5fd61d919f60d8844a973" - integrity sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw== - dependencies: - "@babel/template" "^7.10.1" - "@babel/traverse" "^7.10.1" - "@babel/types" "^7.10.1" - -"@babel/highlight@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.1.tgz#841d098ba613ba1a427a2b383d79e35552c38ae0" - integrity sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg== +"@babel/highlight@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== dependencies: - "@babel/helper-validator-identifier" "^7.10.1" + "@babel/helper-validator-identifier" "^7.10.4" chalk "^2.0.0" js-tokens "^4.0.0" @@ -710,93 +652,124 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/parser@^7.10.1": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.10.2.tgz#871807f10442b92ff97e4783b9b54f6a0ca812d0" - integrity sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ== +"@babel/parser@^7.10.4", "@babel/parser@^7.11.1", "@babel/parser@^7.11.5": + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037" + integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q== -"@babel/parser@^7.4.3", "@babel/parser@^7.7.5", "@babel/parser@^7.8.3", "@babel/parser@^7.8.4": +"@babel/parser@^7.4.3", "@babel/parser@^7.8.3", "@babel/parser@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.4.tgz#d1dbe64691d60358a974295fa53da074dd2ce8e8" integrity sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw== -"@babel/parser@^7.8.6": - version "7.8.8" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.8.tgz#4c3b7ce36db37e0629be1f0d50a571d2f86f6cd4" - integrity sha512-mO5GWzBPsPf6865iIbzNE0AvkKF3NE+2S3eRUpE+FE07BOAkXh6G+GW/Pj01hhXjve1WScbaIO4UlY1JKeqCcA== - -"@babel/parser@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.6.tgz#3b1bbb30dabe600cd72db58720998376ff653bc7" - integrity sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q== - -"@babel/plugin-proposal-async-generator-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f" - integrity sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw== +"@babel/plugin-proposal-async-generator-functions@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz#3491cabf2f7c179ab820606cec27fed15e0e8558" + integrity sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-remap-async-to-generator" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.10.4" "@babel/plugin-syntax-async-generators" "^7.8.0" -"@babel/plugin-proposal-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz#38c4fe555744826e97e2ae930b0fb4cc07e66054" - integrity sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w== +"@babel/plugin-proposal-class-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz#a33bf632da390a59c7a8c570045d1115cd778807" + integrity sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-proposal-dynamic-import@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz#ba57a26cb98b37741e9d5bca1b8b0ddf8291f17e" + integrity sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-dynamic-import" "^7.8.0" -"@babel/plugin-proposal-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz#da5216b238a98b58a1e05d6852104b10f9a70d6b" - integrity sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q== +"@babel/plugin-proposal-export-namespace-from@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz#570d883b91031637b3e2958eea3c438e62c05f54" + integrity sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-proposal-json-strings@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz#593e59c63528160233bd321b1aebe0820c2341db" + integrity sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.0" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" - integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw== +"@babel/plugin-proposal-logical-assignment-operators@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz#9f80e482c03083c87125dee10026b58527ea20c8" + integrity sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz#02a7e961fc32e6d5b2db0649e01bf80ddee7e04a" + integrity sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@babel/plugin-proposal-numeric-separator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz#5d6769409699ec9b3b68684cd8116cedff93bad8" - integrity sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ== +"@babel/plugin-proposal-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz#ce1590ff0a65ad12970a609d78855e9a4c1aef06" + integrity sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-proposal-object-rest-spread@^7.9.6": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.10.1.tgz#cba44908ac9f142650b4a65b8aa06bf3478d5fb6" - integrity sha512-Z+Qri55KiQkHh7Fc4BW6o+QBuTagbOp9txE+4U1i79u9oWlf2npkiDx+Rf3iK3lbcHBuNy9UOkwuR5wOMH3LIQ== +"@babel/plugin-proposal-object-rest-spread@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz#bd81f95a1f746760ea43b6c2d3d62b11790ad0af" + integrity sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.10.1" + "@babel/plugin-transform-parameters" "^7.10.4" -"@babel/plugin-proposal-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz#9dee96ab1650eed88646ae9734ca167ac4a9c5c9" - integrity sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw== +"@babel/plugin-proposal-optional-catch-binding@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz#31c938309d24a78a49d68fdabffaa863758554dd" + integrity sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz#31db16b154c39d6b8a645292472b98394c292a58" - integrity sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w== +"@babel/plugin-proposal-optional-chaining@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz#de5866d0646f6afdaab8a566382fe3a221755076" + integrity sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-unicode-property-regex@^7.4.4", "@babel/plugin-proposal-unicode-property-regex@^7.8.3": +"@babel/plugin-proposal-private-methods@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz#b160d972b8fdba5c7d111a145fc8c421fc2a6909" + integrity sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-proposal-unicode-property-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz#4483cda53041ce3413b7fe2f00022665ddfaa75d" + integrity sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.8.8" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz#ee3a95e90cdc04fe8cd92ec3279fa017d68a0d1d" integrity sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A== @@ -811,6 +784,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-class-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz#6644e6a0baa55a61f9e3231f6c9eeb6ee46c124c" + integrity sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-dynamic-import@^7.8.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" @@ -818,6 +798,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-json-strings@^7.8.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" @@ -825,6 +812,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" @@ -832,12 +826,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.8.0", "@babel/plugin-syntax-numeric-separator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz#0e3fb63e09bea1b11e96467271c8308007e7c41f" - integrity sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw== +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread@^7.8.0": version "7.8.3" @@ -860,73 +854,80 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz#3acdece695e6b13aaf57fc291d1a800950c71391" - integrity sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g== +"@babel/plugin-syntax-top-level-await@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz#4bbeb8917b54fcf768364e0a81f560e33a3ef57d" + integrity sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-arrow-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz#82776c2ed0cd9e1a49956daeb896024c9473b8b6" - integrity sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg== +"@babel/plugin-transform-arrow-functions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd" + integrity sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-async-to-generator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz#4308fad0d9409d71eafb9b1a6ee35f9d64b64086" - integrity sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ== +"@babel/plugin-transform-async-to-generator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz#41a5017e49eb6f3cda9392a51eef29405b245a37" + integrity sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ== dependencies: - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-remap-async-to-generator" "^7.8.3" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.10.4" -"@babel/plugin-transform-block-scoped-functions@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz#437eec5b799b5852072084b3ae5ef66e8349e8a3" - integrity sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg== +"@babel/plugin-transform-block-scoped-functions@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz#1afa595744f75e43a91af73b0d998ecfe4ebc2e8" + integrity sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-block-scoping@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz#97d35dab66857a437c166358b91d09050c868f3a" - integrity sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w== +"@babel/plugin-transform-block-scoping@^7.10.4": + version "7.11.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz#5b7efe98852bef8d652c0b28144cd93a9e4b5215" + integrity sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - lodash "^4.17.13" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-classes@^7.9.5": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.1.tgz#6e11dd6c4dfae70f540480a4702477ed766d733f" - integrity sha512-P9V0YIh+ln/B3RStPoXpEQ/CoAxQIhRSUn7aXqQ+FZJ2u8+oCtjIXR3+X0vsSD8zv+mb56K7wZW1XiDTDGiDRQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.1" - "@babel/helper-define-map" "^7.10.1" - "@babel/helper-function-name" "^7.10.1" - "@babel/helper-optimise-call-expression" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/helper-replace-supers" "^7.10.1" - "@babel/helper-split-export-declaration" "^7.10.1" +"@babel/plugin-transform-classes@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz#405136af2b3e218bc4a1926228bc917ab1a0adc7" + integrity sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-define-map" "^7.10.4" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.10.4" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz#96d0d28b7f7ce4eb5b120bb2e0e943343c86f81b" - integrity sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA== +"@babel/plugin-transform-computed-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz#9ded83a816e82ded28d52d4b4ecbdd810cdfc0eb" + integrity sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-destructuring@^7.9.5": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.1.tgz#abd58e51337815ca3a22a336b85f62b998e71907" - integrity sha512-V/nUc4yGWG71OhaTH705pU8ZSdM6c1KmmLP8ys59oOYbT7RpMYAR3MsVOt6OHL0WzG7BlTU076va9fjJyYzJMA== +"@babel/plugin-transform-destructuring@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz#70ddd2b3d1bea83d01509e9bb25ddb3a74fc85e5" + integrity sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA== dependencies: - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-dotall-regex@^7.4.4", "@babel/plugin-transform-dotall-regex@^7.8.3": +"@babel/plugin-transform-dotall-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz#469c2062105c1eb6a040eaf4fac4b488078395ee" + integrity sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-dotall-regex@^7.4.4": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" integrity sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw== @@ -934,262 +935,270 @@ "@babel/helper-create-regexp-features-plugin" "^7.8.3" "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-transform-duplicate-keys@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz#8d12df309aa537f272899c565ea1768e286e21f1" - integrity sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ== +"@babel/plugin-transform-duplicate-keys@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz#697e50c9fee14380fe843d1f306b295617431e47" + integrity sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-exponentiation-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz#581a6d7f56970e06bf51560cd64f5e947b70d7b7" - integrity sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ== +"@babel/plugin-transform-exponentiation-operator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz#5ae338c57f8cf4001bdb35607ae66b92d665af2e" + integrity sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-for-of@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz#0f260e27d3e29cd1bb3128da5e76c761aa6c108e" - integrity sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ== +"@babel/plugin-transform-for-of@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz#c08892e8819d3a5db29031b115af511dbbfebae9" + integrity sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-function-name@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz#279373cb27322aaad67c2683e776dfc47196ed8b" - integrity sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ== +"@babel/plugin-transform-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz#6a467880e0fc9638514ba369111811ddbe2644b7" + integrity sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg== dependencies: - "@babel/helper-function-name" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz#aef239823d91994ec7b68e55193525d76dbd5dc1" - integrity sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A== +"@babel/plugin-transform-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz#9f42ba0841100a135f22712d0e391c462f571f3c" + integrity sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-member-expression-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz#963fed4b620ac7cbf6029c755424029fa3a40410" - integrity sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA== +"@babel/plugin-transform-member-expression-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz#b1ec44fcf195afcb8db2c62cd8e551c881baf8b7" + integrity sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-modules-amd@^7.9.6": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.1.tgz#65950e8e05797ebd2fe532b96e19fc5482a1d52a" - integrity sha512-31+hnWSFRI4/ACFr1qkboBbrTxoBIzj7qA69qlq8HY8p7+YCzkCT6/TvQ1a4B0z27VeWtAeJd6pr5G04dc1iHw== +"@babel/plugin-transform-modules-amd@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz#1b9cddaf05d9e88b3aad339cb3e445c4f020a9b1" + integrity sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw== dependencies: - "@babel/helper-module-transforms" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-module-transforms" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.9.6": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.1.tgz#d5ff4b4413ed97ffded99961056e1fb980fb9301" - integrity sha512-AQG4fc3KOah0vdITwt7Gi6hD9BtQP/8bhem7OjbaMoRNCH5Djx42O2vYMfau7QnAzQCa+RJnhJBmFFMGpQEzrg== +"@babel/plugin-transform-modules-commonjs@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz#66667c3eeda1ebf7896d41f1f16b17105a2fbca0" + integrity sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w== dependencies: - "@babel/helper-module-transforms" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" - "@babel/helper-simple-access" "^7.10.1" + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-systemjs@^7.9.6": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.1.tgz#9962e4b0ac6aaf2e20431ada3d8ec72082cbffb6" - integrity sha512-ewNKcj1TQZDL3YnO85qh9zo1YF1CHgmSTlRQgHqe63oTrMI85cthKtZjAiZSsSNjPQ5NCaYo5QkbYqEw1ZBgZA== +"@babel/plugin-transform-modules-systemjs@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz#6270099c854066681bae9e05f87e1b9cadbe8c85" + integrity sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw== dependencies: - "@babel/helper-hoist-variables" "^7.10.1" - "@babel/helper-module-transforms" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-hoist-variables" "^7.10.4" + "@babel/helper-module-transforms" "^7.10.5" + "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-umd@^7.9.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz#e909acae276fec280f9b821a5f38e1f08b480697" - integrity sha512-uTWkXkIVtg/JGRSIABdBoMsoIeoHQHPTL0Y2E7xf5Oj7sLqwVsNXOkNk0VJc7vF0IMBsPeikHxFjGe+qmwPtTQ== - dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz#a2a72bffa202ac0e2d0506afd0939c5ecbc48c6c" - integrity sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw== +"@babel/plugin-transform-modules-umd@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz#9a8481fe81b824654b3a0b65da3df89f3d21839e" + integrity sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-module-transforms" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-new-target@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz#60cc2ae66d85c95ab540eb34babb6434d4c70c43" - integrity sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw== +"@babel/plugin-transform-named-capturing-groups-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz#78b4d978810b6f3bcf03f9e318f2fc0ed41aecb6" + integrity sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-create-regexp-features-plugin" "^7.10.4" -"@babel/plugin-transform-object-super@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz#ebb6a1e7a86ffa96858bd6ac0102d65944261725" - integrity sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ== +"@babel/plugin-transform-new-target@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz#9097d753cb7b024cb7381a3b2e52e9513a9c6888" + integrity sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-parameters@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.1.tgz#b25938a3c5fae0354144a720b07b32766f683ddd" - integrity sha512-tJ1T0n6g4dXMsL45YsSzzSDZCxiHXAQp/qHrucOq5gEHncTA3xDxnd5+sZcoQp+N1ZbieAaB8r/VUCG0gqseOg== +"@babel/plugin-transform-object-super@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz#d7146c4d139433e7a6526f888c667e314a093894" + integrity sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ== dependencies: - "@babel/helper-get-function-arity" "^7.10.1" - "@babel/helper-plugin-utils" "^7.10.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" -"@babel/plugin-transform-parameters@^7.9.5": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.5.tgz#173b265746f5e15b2afe527eeda65b73623a0795" - integrity sha512-0+1FhHnMfj6lIIhVvS4KGQJeuhe1GI//h5uptK4PvLt+BGBxsoUJbd3/IW002yk//6sZPlFgsG1hY6OHLcy6kA== +"@babel/plugin-transform-parameters@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz#59d339d58d0b1950435f4043e74e2510005e2c4a" + integrity sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw== dependencies: - "@babel/helper-get-function-arity" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-property-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz#33194300d8539c1ed28c62ad5087ba3807b98263" - integrity sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg== +"@babel/plugin-transform-property-literals@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz#f6fe54b6590352298785b83edd815d214c42e3c0" + integrity sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-regenerator@^7.8.7": - version "7.8.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz#5e46a0dca2bee1ad8285eb0527e6abc9c37672f8" - integrity sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA== +"@babel/plugin-transform-regenerator@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz#2015e59d839074e76838de2159db421966fd8b63" + integrity sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw== dependencies: regenerator-transform "^0.14.2" -"@babel/plugin-transform-reserved-words@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz#9a0635ac4e665d29b162837dd3cc50745dfdf1f5" - integrity sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A== +"@babel/plugin-transform-reserved-words@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz#8f2682bcdcef9ed327e1b0861585d7013f8a54dd" + integrity sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ== dependencies: - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-runtime@7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.9.6.tgz#3ba804438ad0d880a17bca5eaa0cdf1edeedb2fd" - integrity sha512-qcmiECD0mYOjOIt8YHNsAP1SxPooC/rDmfmiSK9BNY72EitdSc7l44WTEklaWuFtbOEBjNhWWyph/kOImbNJ4w== +"@babel/plugin-transform-runtime@7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.11.0.tgz#e27f78eb36f19448636e05c33c90fd9ad9b8bccf" + integrity sha512-LFEsP+t3wkYBlis8w6/kmnd6Kb1dxTd+wGJ8MlxTGzQo//ehtqlVL4S9DNUa53+dtPSQobN2CXx4d81FqC58cw== dependencies: - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" resolve "^1.8.1" semver "^5.5.1" -"@babel/plugin-transform-shorthand-properties@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz#28545216e023a832d4d3a1185ed492bcfeac08c8" - integrity sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz#9c8ffe8170fdfb88b114ecb920b82fb6e95fe5e8" - integrity sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-sticky-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz#be7a1290f81dae767475452199e1f76d6175b100" - integrity sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-regex" "^7.8.3" - -"@babel/plugin-transform-template-literals@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz#7bfa4732b455ea6a43130adc0ba767ec0e402a80" - integrity sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-typeof-symbol@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz#ede4062315ce0aaf8a657a920858f1a2f35fc412" - integrity sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-transform-unicode-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz#0cef36e3ba73e5c57273effb182f46b91a1ecaad" - integrity sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/preset-env@7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.9.6.tgz#df063b276c6455ec6fcfc6e53aacc38da9b0aea6" - integrity sha512-0gQJ9RTzO0heXOhzftog+a/WyOuqMrAIugVYxMYf83gh1CQaQDjMtsOpqOwXyDL/5JcWsrCm8l4ju8QC97O7EQ== - dependencies: - "@babel/compat-data" "^7.9.6" - "@babel/helper-compilation-targets" "^7.9.6" - "@babel/helper-module-imports" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-proposal-async-generator-functions" "^7.8.3" - "@babel/plugin-proposal-dynamic-import" "^7.8.3" - "@babel/plugin-proposal-json-strings" "^7.8.3" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-proposal-numeric-separator" "^7.8.3" - "@babel/plugin-proposal-object-rest-spread" "^7.9.6" - "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" - "@babel/plugin-proposal-optional-chaining" "^7.9.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" +"@babel/plugin-transform-shorthand-properties@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz#9fd25ec5cdd555bb7f473e5e6ee1c971eede4dd6" + integrity sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-spread@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz#fa84d300f5e4f57752fe41a6d1b3c554f13f17cc" + integrity sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" + +"@babel/plugin-transform-sticky-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz#8f3889ee8657581130a29d9cc91d7c73b7c4a28d" + integrity sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-regex" "^7.10.4" + +"@babel/plugin-transform-template-literals@^7.10.4": + version "7.10.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz#78bc5d626a6642db3312d9d0f001f5e7639fde8c" + integrity sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-typeof-symbol@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz#9509f1a7eec31c4edbffe137c16cc33ff0bc5bfc" + integrity sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-unicode-escapes@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz#feae523391c7651ddac115dae0a9d06857892007" + integrity sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-unicode-regex@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz#e56d71f9282fac6db09c82742055576d5e6d80a8" + integrity sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/preset-env@7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.11.0.tgz#860ee38f2ce17ad60480c2021ba9689393efb796" + integrity sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg== + dependencies: + "@babel/compat-data" "^7.11.0" + "@babel/helper-compilation-targets" "^7.10.4" + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-proposal-async-generator-functions" "^7.10.4" + "@babel/plugin-proposal-class-properties" "^7.10.4" + "@babel/plugin-proposal-dynamic-import" "^7.10.4" + "@babel/plugin-proposal-export-namespace-from" "^7.10.4" + "@babel/plugin-proposal-json-strings" "^7.10.4" + "@babel/plugin-proposal-logical-assignment-operators" "^7.11.0" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.4" + "@babel/plugin-proposal-numeric-separator" "^7.10.4" + "@babel/plugin-proposal-object-rest-spread" "^7.11.0" + "@babel/plugin-proposal-optional-catch-binding" "^7.10.4" + "@babel/plugin-proposal-optional-chaining" "^7.11.0" + "@babel/plugin-proposal-private-methods" "^7.10.4" + "@babel/plugin-proposal-unicode-property-regex" "^7.10.4" "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-class-properties" "^7.10.4" "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - "@babel/plugin-syntax-numeric-separator" "^7.8.0" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-syntax-object-rest-spread" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" "@babel/plugin-syntax-optional-chaining" "^7.8.0" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - "@babel/plugin-transform-arrow-functions" "^7.8.3" - "@babel/plugin-transform-async-to-generator" "^7.8.3" - "@babel/plugin-transform-block-scoped-functions" "^7.8.3" - "@babel/plugin-transform-block-scoping" "^7.8.3" - "@babel/plugin-transform-classes" "^7.9.5" - "@babel/plugin-transform-computed-properties" "^7.8.3" - "@babel/plugin-transform-destructuring" "^7.9.5" - "@babel/plugin-transform-dotall-regex" "^7.8.3" - "@babel/plugin-transform-duplicate-keys" "^7.8.3" - "@babel/plugin-transform-exponentiation-operator" "^7.8.3" - "@babel/plugin-transform-for-of" "^7.9.0" - "@babel/plugin-transform-function-name" "^7.8.3" - "@babel/plugin-transform-literals" "^7.8.3" - "@babel/plugin-transform-member-expression-literals" "^7.8.3" - "@babel/plugin-transform-modules-amd" "^7.9.6" - "@babel/plugin-transform-modules-commonjs" "^7.9.6" - "@babel/plugin-transform-modules-systemjs" "^7.9.6" - "@babel/plugin-transform-modules-umd" "^7.9.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" - "@babel/plugin-transform-new-target" "^7.8.3" - "@babel/plugin-transform-object-super" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.9.5" - "@babel/plugin-transform-property-literals" "^7.8.3" - "@babel/plugin-transform-regenerator" "^7.8.7" - "@babel/plugin-transform-reserved-words" "^7.8.3" - "@babel/plugin-transform-shorthand-properties" "^7.8.3" - "@babel/plugin-transform-spread" "^7.8.3" - "@babel/plugin-transform-sticky-regex" "^7.8.3" - "@babel/plugin-transform-template-literals" "^7.8.3" - "@babel/plugin-transform-typeof-symbol" "^7.8.4" - "@babel/plugin-transform-unicode-regex" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.10.4" + "@babel/plugin-transform-arrow-functions" "^7.10.4" + "@babel/plugin-transform-async-to-generator" "^7.10.4" + "@babel/plugin-transform-block-scoped-functions" "^7.10.4" + "@babel/plugin-transform-block-scoping" "^7.10.4" + "@babel/plugin-transform-classes" "^7.10.4" + "@babel/plugin-transform-computed-properties" "^7.10.4" + "@babel/plugin-transform-destructuring" "^7.10.4" + "@babel/plugin-transform-dotall-regex" "^7.10.4" + "@babel/plugin-transform-duplicate-keys" "^7.10.4" + "@babel/plugin-transform-exponentiation-operator" "^7.10.4" + "@babel/plugin-transform-for-of" "^7.10.4" + "@babel/plugin-transform-function-name" "^7.10.4" + "@babel/plugin-transform-literals" "^7.10.4" + "@babel/plugin-transform-member-expression-literals" "^7.10.4" + "@babel/plugin-transform-modules-amd" "^7.10.4" + "@babel/plugin-transform-modules-commonjs" "^7.10.4" + "@babel/plugin-transform-modules-systemjs" "^7.10.4" + "@babel/plugin-transform-modules-umd" "^7.10.4" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.10.4" + "@babel/plugin-transform-new-target" "^7.10.4" + "@babel/plugin-transform-object-super" "^7.10.4" + "@babel/plugin-transform-parameters" "^7.10.4" + "@babel/plugin-transform-property-literals" "^7.10.4" + "@babel/plugin-transform-regenerator" "^7.10.4" + "@babel/plugin-transform-reserved-words" "^7.10.4" + "@babel/plugin-transform-shorthand-properties" "^7.10.4" + "@babel/plugin-transform-spread" "^7.11.0" + "@babel/plugin-transform-sticky-regex" "^7.10.4" + "@babel/plugin-transform-template-literals" "^7.10.4" + "@babel/plugin-transform-typeof-symbol" "^7.10.4" + "@babel/plugin-transform-unicode-escapes" "^7.10.4" + "@babel/plugin-transform-unicode-regex" "^7.10.4" "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.9.6" - browserslist "^4.11.1" + "@babel/types" "^7.11.0" + browserslist "^4.12.0" core-js-compat "^3.6.2" invariant "^2.2.2" levenary "^1.1.1" @@ -1214,10 +1223,10 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.2" -"@babel/runtime@7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.6.tgz#a9102eb5cadedf3f31d08a9ecf294af7827ea29f" - integrity sha512-64AF1xY3OAkFHqOb9s4jpgk1Mm5vDZ4L3acHvAml+53nO1XbXLuDodsVpO4OIUsmemlUHMxNdYMNJmsvOwLrvQ== +"@babel/runtime@7.11.2": + version "7.11.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736" + integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw== dependencies: regenerator-runtime "^0.13.4" @@ -1228,25 +1237,16 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/template@7.8.6", "@babel/template@^7.8.6": - version "7.8.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" - integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== +"@babel/template@7.10.4", "@babel/template@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" + integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/parser" "^7.8.6" - "@babel/types" "^7.8.6" + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/types" "^7.10.4" -"@babel/template@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.1.tgz#e167154a94cb5f14b28dc58f5356d2162f539811" - integrity sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig== - dependencies: - "@babel/code-frame" "^7.10.1" - "@babel/parser" "^7.10.1" - "@babel/types" "^7.10.1" - -"@babel/template@^7.4.0", "@babel/template@^7.7.4", "@babel/template@^7.8.3": +"@babel/template@^7.4.0", "@babel/template@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.3.tgz#e02ad04fe262a657809327f578056ca15fd4d1b8" integrity sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ== @@ -1255,22 +1255,22 @@ "@babel/parser" "^7.8.3" "@babel/types" "^7.8.3" -"@babel/traverse@^7.10.1": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.10.1.tgz#bbcef3031e4152a6c0b50147f4958df54ca0dd27" - integrity sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ== - dependencies: - "@babel/code-frame" "^7.10.1" - "@babel/generator" "^7.10.1" - "@babel/helper-function-name" "^7.10.1" - "@babel/helper-split-export-declaration" "^7.10.1" - "@babel/parser" "^7.10.1" - "@babel/types" "^7.10.1" +"@babel/traverse@^7.10.4", "@babel/traverse@^7.11.0": + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.5.tgz#be777b93b518eb6d76ee2e1ea1d143daa11e61c3" + integrity sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.5" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/parser" "^7.11.5" + "@babel/types" "^7.11.5" debug "^4.1.0" globals "^11.1.0" - lodash "^4.17.13" + lodash "^4.17.19" -"@babel/traverse@^7.4.3", "@babel/traverse@^7.7.4", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4": +"@babel/traverse@^7.4.3", "@babel/traverse@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.4.tgz#f0845822365f9d5b0e312ed3959d3f827f869e3c" integrity sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg== @@ -1285,43 +1285,13 @@ globals "^11.1.0" lodash "^4.17.13" -"@babel/traverse@^7.8.6": - version "7.8.6" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.6.tgz#acfe0c64e1cd991b3e32eae813a6eb564954b5ff" - integrity sha512-2B8l0db/DPi8iinITKuo7cbPznLCEk0kCxDoB9/N6gGNg/gxOXiR/IcymAFPiBwk5w6TtQ27w4wpElgp9btR9A== +"@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.11.5": + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d" + integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q== dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.8.6" - "@babel/helper-function-name" "^7.8.3" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/parser" "^7.8.6" - "@babel/types" "^7.8.6" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@babel/traverse@^7.9.6": - version "7.9.6" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.9.6.tgz#5540d7577697bf619cc57b92aa0f1c231a94f442" - integrity sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg== - dependencies: - "@babel/code-frame" "^7.8.3" - "@babel/generator" "^7.9.6" - "@babel/helper-function-name" "^7.9.5" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/parser" "^7.9.6" - "@babel/types" "^7.9.6" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@babel/types@^7.10.1", "@babel/types@^7.10.2": - version "7.10.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.2.tgz#30283be31cad0dbf6fb00bd40641ca0ea675172d" - integrity sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng== - dependencies: - "@babel/helper-validator-identifier" "^7.10.1" - lodash "^4.17.13" + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" to-fast-properties "^2.0.0" "@babel/types@^7.4.0", "@babel/types@^7.8.3": @@ -1333,7 +1303,7 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@babel/types@^7.4.4", "@babel/types@^7.9.0", "@babel/types@^7.9.5", "@babel/types@^7.9.6": +"@babel/types@^7.4.4": version "7.9.6" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.9.6.tgz#2c5502b427251e9de1bd2dff95add646d95cc9f7" integrity sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA== @@ -1342,15 +1312,6 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@babel/types@^7.8.6", "@babel/types@^7.8.7": - version "7.8.7" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.7.tgz#1fc9729e1acbb2337d5b6977a63979b4819f5d1d" - integrity sha512-k2TreEHxFA4CjGkL+GYjRyx35W0Mr7DP5+9q6WMkyKXB+904bYmG40syjMFV0oLlhhFCwWl0vA0DyzTDkwAiJw== - dependencies: - esutils "^2.0.2" - lodash "^4.17.13" - to-fast-properties "^2.0.0" - "@firebase/analytics-types@0.3.1": version "0.3.1" resolved "https://registry.yarnpkg.com/@firebase/analytics-types/-/analytics-types-0.3.1.tgz#3c5f5d71129c88295e17e914e34b391ffda1723c" @@ -1627,10 +1588,13 @@ semver "^6.2.0" "@grpc/grpc-js@^1.0.0": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.1.3.tgz#0b91b166d744b6a43b00430dceff0f0ff88c98d5" - integrity sha512-HtOsk2YUofBcm1GkPqGzb6pwHhv+74eC2CUO229USIDKRtg30ycbZmqC+HdNtY3nHqoc9IgcRlntFgopyQoYCA== + version "1.1.7" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.1.7.tgz#d3d71c6da95397e2d63895ccc4a05e7572f7b7e6" + integrity sha512-EuxMstI0u778dp0nk6Fe3gHXYPeV6FYsWOe0/QFwxv1NQ6bc5Wl/0Yxa4xl9uBlKElL6AIxuASmSfu7KEJhqiw== dependencies: + "@grpc/proto-loader" "^0.6.0-pre14" + "@types/node" "^12.12.47" + google-auth-library "^6.0.0" semver "^6.2.0" "@grpc/proto-loader@^0.5.0": @@ -1649,30 +1613,48 @@ lodash.camelcase "^4.3.0" protobufjs "^6.8.6" +"@grpc/proto-loader@^0.6.0-pre14": + version "0.6.0-pre9" + resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.6.0-pre9.tgz#0c6fe42f6c5ef9ce1b3cef7be64d5b09d6fe4d6d" + integrity sha512-oM+LjpEjNzW5pNJjt4/hq1HYayNeQT+eGrOPABJnYHv7TyNPDNzkQ76rDYZF86X5swJOa4EujEMzQ9iiTdPgww== + dependencies: + "@types/long" "^4.0.1" + lodash.camelcase "^4.3.0" + long "^4.0.0" + protobufjs "^6.9.0" + yargs "^15.3.1" + "@istanbuljs/schema@^0.1.2": version "0.1.2" resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== -"@jsdevtools/coverage-istanbul-loader@3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.3.tgz#102e414b02ae2f0b3c7fd45a705601e1fd4867c5" - integrity sha512-TAdNkeGB5Fe4Og+ZkAr1Kvn9by2sfL44IAHFtxlh1BA1XJ5cLpO9iSNki5opWESv3l3vSHsZ9BNKuqFKbEbFaA== +"@jsdevtools/coverage-istanbul-loader@3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.5.tgz#2a4bc65d0271df8d4435982db4af35d81754ee26" + integrity sha512-EUCPEkaRPvmHjWAAZkWMT7JDzpw7FKB00WTISaiXsbNOd5hCHg77XLA8sLYLFDo1zepYLo2w7GstN8YBqRXZfA== dependencies: convert-source-map "^1.7.0" - istanbul-lib-instrument "^4.0.1" - loader-utils "^1.4.0" + istanbul-lib-instrument "^4.0.3" + loader-utils "^2.0.0" merge-source-map "^1.1.0" - schema-utils "^2.6.4" + schema-utils "^2.7.0" -"@ngtools/webpack@10.0.1": - version "10.0.1" - resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-10.0.1.tgz#f3d5143f268cc1c3c8d94de0e048b970c95e6a27" - integrity sha512-/uUTczGcH2WJoVovCLHXdPdTzN0yQZontcf5MkoDjlA0selUdRFntV9cnUWoray9SVxzgoHqjRxBANCTsiiuuw== +"@mrmlnc/readdir-enhanced@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" + integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g== dependencies: - "@angular-devkit/core" "10.0.1" - enhanced-resolve "4.1.1" - rxjs "6.5.5" + call-me-maybe "^1.0.1" + glob-to-regexp "^0.3.0" + +"@ngtools/webpack@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-10.1.3.tgz#f65c591daab7ed0c3372a115c6a90eba701a2ca1" + integrity sha512-wEg3hY0u+HMAIypClOVnpjYaNwBp+yY0pEb1yNc3Id8bBlw76Y+wk+kGplESelkNQKlfwKDaMFk+7EjGkOrmng== + dependencies: + "@angular-devkit/core" "10.1.3" + enhanced-resolve "4.3.0" webpack-sources "1.4.3" "@nodelib/fs.scandir@2.1.3": @@ -1688,6 +1670,11 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== +"@nodelib/fs.stat@^1.1.2": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" + integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== + "@nodelib/fs.walk@^1.2.3": version "1.2.4" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" @@ -1756,26 +1743,26 @@ resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= -"@schematics/angular@10.0.1": - version "10.0.1" - resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-10.0.1.tgz#0660d5eb99169a67ecfc7a4c2946de1ea32320c0" - integrity sha512-SrWr2FzenwuofRpcaLhzJYNFVJmJwKxlKu32dWAVnclpteMO0Hnp/jVI/e70HIc6zoWzgJ4yArmwBTA+Q26yaA== +"@schematics/angular@10.1.3": + version "10.1.3" + resolved "https://registry.yarnpkg.com/@schematics/angular/-/angular-10.1.3.tgz#8b39f2d934043c68b55495bc6e44705c6fa7ef8c" + integrity sha512-X3tNnpfF/jkl1KcyCC8PaOYogQlTZ9s7Yuz0va0DAVOptIqorpf8e6+lY0PPLKshaK9TSiFUcQ8SYYnjAVKcdA== dependencies: - "@angular-devkit/core" "10.0.1" - "@angular-devkit/schematics" "10.0.1" + "@angular-devkit/core" "10.1.3" + "@angular-devkit/schematics" "10.1.3" + jsonc-parser "2.3.0" -"@schematics/update@0.1000.1": - version "0.1000.1" - resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.1000.1.tgz#bcccf6822eb2b145a0ac3d1b352ada2925a558bf" - integrity sha512-AiU3RiKMfzxquzxANgDMO88iTkk9pVKQ5fZV4UwiyZO5q/fUCW4FFx9h4Nc7e9adchM+VaCz/uEAWqrVdsPv9Q== +"@schematics/update@0.1001.3": + version "0.1001.3" + resolved "https://registry.yarnpkg.com/@schematics/update/-/update-0.1001.3.tgz#7b8e2c166948c096cb46d9d7c712b3f9fac044e0" + integrity sha512-ah4YHjEXACmpX0i3cAn5OguH5S430HD+zbxlMu4AC93A8W52ll97vqvUVF8NLZ6RKcOV/8tXmzgzvJDe07i8yQ== dependencies: - "@angular-devkit/core" "10.0.1" - "@angular-devkit/schematics" "10.0.1" + "@angular-devkit/core" "10.1.3" + "@angular-devkit/schematics" "10.1.3" "@yarnpkg/lockfile" "1.1.0" ini "1.3.5" npm-package-arg "^8.0.0" pacote "9.5.12" - rxjs "6.5.5" semver "7.3.2" semver-intersect "1.4.0" @@ -1829,7 +1816,7 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd" integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ== -"@types/long@^4.0.0": +"@types/long@^4.0.0", "@types/long@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9" integrity sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w== @@ -1854,11 +1841,21 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.15.tgz#bfff4e23e9e70be6eec450419d51e18de1daf8e7" integrity sha512-daFGV9GSs6USfPgxceDA8nlSe48XrVCJfDeYm7eokxq/ye7iuOH87hKXgMtEAVLFapkczbZsx868PMDT1Y0a6A== +"@types/node@^12.12.47": + version "12.19.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.0.tgz#a0f841c195bdbe0b5070da9278b3e22189e8c8f6" + integrity sha512-4BVAE9yp5DU3ISqBInsaRp9J474HWNaNVs8eZ1Far3dI1MwS3Wk0EvBRMM4xBh3Oz+c05hUgJmcbtAVmG8bv7w== + "@types/node@^12.7.9": version "12.12.27" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.27.tgz#d7506f73160ad30fcebbcf5b8b7d2d976e649e42" integrity sha512-odQFl/+B9idbdS0e8IxDl2ia/LP8KZLXhV3BUeI98TrZp0uoIzQPhGd+5EtzHmT0SMOIaPd7jfz6pOHLWTtl7A== +"@types/node@^13.7.0": + version "13.13.28" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.28.tgz#b6d0628b0371d6c629d729c98322de314b640219" + integrity sha512-EM/qFeRH8ZCD+TlsaIPULyyFm9vOhFIvgskY2JmHbEsWsOPgN+rtjSXrcHGgJpob4Nu17VfO95FKewr0XY7iOQ== + "@types/q@^0.0.32": version "0.0.32" resolved "https://registry.yarnpkg.com/@types/q/-/q-0.0.32.tgz#bd284e57c84f1325da702babfc82a5328190c0c5" @@ -2196,6 +2193,13 @@ agent-base@5: resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-5.1.1.tgz#e8fb3f242959db44d63be665db7a8e739537a32c" integrity sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g== +agent-base@6: + version "6.0.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.1.tgz#808007e4e5867decb0ab6ab2f928fbdb5a596db4" + integrity sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg== + dependencies: + debug "4" + agent-base@~4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" @@ -2233,10 +2237,10 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== -ajv@6.12.2, ajv@^6.12.2: - version "6.12.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" - integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ== +ajv@6.12.4: + version "6.12.4" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234" + integrity sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" @@ -2271,6 +2275,16 @@ ajv@^6.12.0: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^6.12.2: + version "6.12.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" + integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + alphanum-sort@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" @@ -2392,10 +2406,10 @@ anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" -app-root-path@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.2.1.tgz#d0df4a682ee408273583d43f6f79e9892624bc9a" - integrity sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA== +app-root-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-3.0.0.tgz#210b6f43873227e18a4b810a032283311555d5ad" + integrity sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw== append-transform@^1.0.0: version "1.0.0" @@ -2576,7 +2590,7 @@ as-array@^2.0.0: resolved "https://registry.yarnpkg.com/as-array/-/as-array-2.0.0.tgz#4f04805d87f8fce8e511bc2108f8e5e3a287d547" integrity sha1-TwSAXYf4/OjlEbwhCPjl46KH1Uc= -asap@^2.0.0, asap@^2.0.3, asap@~2.0.3: +asap@^2.0.0, asap@^2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= @@ -2664,17 +2678,17 @@ atob@^2.1.2: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -autoprefixer@9.8.0: - version "9.8.0" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.0.tgz#68e2d2bef7ba4c3a65436f662d0a56a741e56511" - integrity sha512-D96ZiIHXbDmU02dBaemyAg53ez+6F5yZmapmgKcjm35yEe1uVDYI8hGW3VYoGRaG290ZFf91YxHrR518vC0u/A== +autoprefixer@9.8.6: + version "9.8.6" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f" + integrity sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg== dependencies: browserslist "^4.12.0" - caniuse-lite "^1.0.30001061" - chalk "^2.4.2" + caniuse-lite "^1.0.30001109" + colorette "^1.2.1" normalize-range "^0.1.2" num2fraction "^1.2.2" - postcss "^7.0.30" + postcss "^7.0.32" postcss-value-parser "^4.1.0" aws-sign2@~0.7.0: @@ -2815,6 +2829,11 @@ bignumber.js@^7.0.0: resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f" integrity sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ== +bignumber.js@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" + integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== + binary-extensions@^1.0.0: version "1.13.1" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" @@ -3041,7 +3060,7 @@ browserslist@^4.0.0, browserslist@^4.8.3: electron-to-chromium "^1.3.341" node-releases "^1.1.47" -browserslist@^4.11.1, browserslist@^4.12.0: +browserslist@^4.12.0: version "4.12.0" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.12.0.tgz#06c6d5715a1ede6c51fc39ff67fd647f740b656d" integrity sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg== @@ -3171,22 +3190,22 @@ bytes@3.1.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== -cacache@15.0.3: - version "15.0.3" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.3.tgz#2225c2d1dd8e872339950d6a39c051e0e9334392" - integrity sha512-bc3jKYjqv7k4pWh7I/ixIjfcjPul4V4jme/WbjvwGS5LzoPL/GzXr4C5EgPNLO/QEZl9Oi61iGitYEdwcrwLCQ== +cacache@15.0.5, cacache@^15.0.5: + version "15.0.5" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.5.tgz#69162833da29170d6732334643c60e005f5f17d0" + integrity sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A== dependencies: + "@npmcli/move-file" "^1.0.1" chownr "^2.0.0" fs-minipass "^2.0.0" glob "^7.1.4" infer-owner "^1.0.4" - lru-cache "^5.1.1" + lru-cache "^6.0.0" minipass "^3.1.1" minipass-collect "^1.0.2" minipass-flush "^1.0.5" minipass-pipeline "^1.2.2" mkdirp "^1.0.3" - move-file "^2.0.0" p-map "^4.0.0" promise-inflight "^1.0.1" rimraf "^3.0.2" @@ -3236,7 +3255,7 @@ cacache@^12.0.2: unique-filename "^1.1.1" y18n "^4.0.0" -cacache@^15.0.3, cacache@^15.0.4: +cacache@^15.0.4: version "15.0.4" resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.0.4.tgz#b2c23cf4ac4f5ead004fb15a0efb0a20340741f1" integrity sha512-YlnKQqTbD/6iyoJvEY3KJftjrdBYroCbxxYXzhOzsFLWlp6KX4BOlEf4mTx0cMUfVaTS3ENL2QtDWeRYoGLkkw== @@ -3274,6 +3293,11 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +call-me-maybe@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" + integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= + caller-callsite@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" @@ -3323,7 +3347,7 @@ camelcase@5.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA== -camelcase@5.3.1, camelcase@^5.0.0, camelcase@^5.3.1: +camelcase@5.3.1, camelcase@^5.0.0: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== @@ -3333,16 +3357,16 @@ camelcase@^2.0.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= -camelcase@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= - camelcase@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= +camelcase@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e" + integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w== + caniuse-api@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" @@ -3368,10 +3392,10 @@ caniuse-lite@^1.0.30001043: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001051.tgz#8e944abf9c796bc7ea0bec3c3688a250561fc9ac" integrity sha512-sw8UUnTlRevawTMZKN7vpfwSjCBVoiMPlYd8oT2VwNylyPCBdMAUmLGUApnYYTtIm5JXsQegUAY7GPHqgfDzjw== -caniuse-lite@^1.0.30001061: - version "1.0.30001078" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001078.tgz#e1b6e2ae327b6a1ec11f65ec7a0dde1e7093074c" - integrity sha512-sF12qXe9VMm32IEf/+NDvmTpwJaaU7N1igpiH2FdI4DyABJSsOqG3ZAcFvszLkoLoo1y6VJLMYivukUAxaMASw== +caniuse-lite@^1.0.30001109: + version "1.0.30001137" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001137.tgz#6f0127b1d3788742561a25af3607a17fc778b803" + integrity sha512-54xKQZTqZrKVHmVz0+UvdZR6kQc7pJDgfhsMYDG19ID1BWoNnDMFm5Q3uSBSU401pBvKYMsHAt9qhEDcxmk8aw== canonical-path@1.0.0, canonical-path@^1.0.0: version "1.0.0" @@ -3445,10 +3469,10 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4 escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" - integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== +chalk@^4.0.0, chalk@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== dependencies: ansi-styles "^4.1.0" supports-color "^7.1.0" @@ -3551,6 +3575,21 @@ chokidar@^2.0.0, chokidar@^2.1.8: optionalDependencies: fsevents "^1.2.7" +chokidar@^3.4.1: + version "3.4.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.2.tgz#38dc8e658dec3809741eb3ef7bb0a47fe424232d" + integrity sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.4.0" + optionalDependencies: + fsevents "~2.1.2" + chownr@^1.1.1, chownr@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" @@ -3670,11 +3709,16 @@ cli-cursor@^3.1.0: dependencies: restore-cursor "^3.1.0" -cli-spinners@^2.0.0, cli-spinners@^2.2.0: +cli-spinners@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.2.0.tgz#e8b988d9206c692302d8ee834e7a85c0144d8f77" integrity sha512-tgU3fKwzYjiLEQgPMD9Jt+JjHVL9kW93FiIMX/l7rivvOD4/LL0Mf7gda3+4U2KJBloybwgj5KEoQgGRioMiKQ== +cli-spinners@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.4.0.tgz#c6256db216b878cfba4720e719cec7cf72685d7f" + integrity sha512-sJAofoarcm76ZGpuooaO0eDy8saEy+YoZBLjC4h8srt4jeBnkYeOgqxgsJQTpyt2LjI5PTfLJHSL+41Yu4fEJA== + cli-table@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23" @@ -3687,7 +3731,12 @@ cli-width@^2.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= -cliui@^3.0.3, cliui@^3.2.0: +cli-width@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" + integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== + +cliui@^3.0.3: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= @@ -3723,14 +3772,14 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" -clone-deep@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" - integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== +cliui@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.2.tgz#e3a412e1d5ec0ccbe50d1b4120fc8164e97881f4" + integrity sha512-lhpKkuUj67j5JgZIPZxLe7nSa4MQoojzRVWQyzMqBp2hBg6gwRjUDAwC1YDeBaC3APDBKNnjWbv2mlDF4XgOSA== dependencies: - is-plain-object "^2.0.4" - kind-of "^6.0.2" - shallow-clone "^3.0.0" + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" clone@^1.0.2: version "1.0.4" @@ -3761,23 +3810,25 @@ code-point-at@^1.0.0: resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= -codelyzer@^6.0.0-next.1: - version "6.0.0-next.1" - resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-6.0.0-next.1.tgz#f68ca751d28f57e7a0c83fe8939929fb77e6c32b" - integrity sha512-TMzAaJ6P7GEZOIAOvLthZ50MUhnmac/8nA7EFBWuy+ZUsJSqm749az1gy/NdV7FtoM7/kb/NoAdwFjmJA5Zniw== +codelyzer@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/codelyzer/-/codelyzer-6.0.0.tgz#50c98581cc2890e0e9a9f93878dc317115d836ed" + integrity sha512-edJIQCIcxD9DhVSyBEdJ38AbLikm515Wl91t5RDGNT88uA6uQdTm4phTWfn9JhzAI8kXNUcfYyAE90lJElpGtA== dependencies: - "@angular/compiler" "~8.2.14" - "@angular/core" "~8.2.14" - app-root-path "^2.2.1" + "@angular/compiler" "9.0.0" + "@angular/core" "9.0.0" + app-root-path "^3.0.0" aria-query "^3.0.0" axobject-query "2.0.2" css-selector-tokenizer "^0.7.1" cssauron "^1.4.0" damerau-levenshtein "^1.0.4" + rxjs "^6.5.3" semver-dsl "^1.0.1" source-map "^0.5.7" sprintf-js "^1.1.2" - zone.js "~0.9.1" + tslib "^1.10.0" + zone.js "~0.10.3" collapse-white-space@^1.0.0, collapse-white-space@^1.0.2: version "1.0.6" @@ -3832,6 +3883,11 @@ color@^3.0.0: color-convert "^1.9.1" color-string "^1.5.2" +colorette@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" + integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw== + colors@1.0.3, colors@1.0.x: version "1.0.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" @@ -4296,24 +4352,23 @@ css-declaration-sorter@^4.0.1: postcss "^7.0.1" timsort "^0.3.0" -css-loader@3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.5.3.tgz#95ac16468e1adcd95c844729e0bb167639eb0bcf" - integrity sha512-UEr9NH5Lmi7+dguAm+/JSPovNjYbm2k3TK58EiwQHzOHH5Jfq1Y+XoP2bQO6TMn7PptMd0opxxedAWcaSTRKHw== +css-loader@4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-4.2.2.tgz#b668b3488d566dc22ebcf9425c5f254a05808c89" + integrity sha512-omVGsTkZPVwVRpckeUnLshPp12KsmMSLqYxs12+RzM9jRR5Y+Idn/tBffjXRvOE+qW7if24cuceFJqYR5FmGBg== dependencies: - camelcase "^5.3.1" + camelcase "^6.0.0" cssesc "^3.0.0" icss-utils "^4.1.1" - loader-utils "^1.2.3" - normalize-path "^3.0.0" - postcss "^7.0.27" + loader-utils "^2.0.0" + postcss "^7.0.32" postcss-modules-extract-imports "^2.0.0" - postcss-modules-local-by-default "^3.0.2" + postcss-modules-local-by-default "^3.0.3" postcss-modules-scope "^2.2.0" postcss-modules-values "^3.0.0" - postcss-value-parser "^4.0.3" - schema-utils "^2.6.6" - semver "^6.3.0" + postcss-value-parser "^4.1.0" + schema-utils "^2.7.0" + semver "^7.3.2" css-parse@~2.0.0: version "2.0.0" @@ -4745,6 +4800,11 @@ detect-node@^2.0.4: resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== +devtools-protocol@0.0.767361: + version "0.0.767361" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.767361.tgz#5977f2558b84f9df36f62501bdddb82f3ae7b66b" + integrity sha512-ziRTdhEVQ9jEwedaUaXZ7kl9w9TF/7A3SXQ0XuqrJB+hMS62POHZUWTbumDN2ehRTfvWqTPc2Jw4gUl/jggmHA== + dezalgo@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" @@ -4963,7 +5023,7 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -ecdsa-sig-formatter@1.0.11: +ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: version "1.0.11" resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== @@ -5100,10 +5160,10 @@ engine.io@~3.2.0: engine.io-parser "~2.1.0" ws "~3.3.1" -enhanced-resolve@4.1.1, enhanced-resolve@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz#2937e2b8066cd0fe7ce0990a98f0d71a35189f66" - integrity sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA== +enhanced-resolve@4.3.0, enhanced-resolve@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126" + integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ== dependencies: graceful-fs "^4.1.2" memory-fs "^0.5.0" @@ -5141,7 +5201,7 @@ errno@^0.1.1, errno@^0.1.3, errno@~0.1.7: dependencies: prr "~1.0.1" -error-ex@^1.2.0, error-ex@^1.3.1: +error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== @@ -5253,6 +5313,11 @@ es6-weak-map@^2.0.1, es6-weak-map@^2.0.2: es6-iterator "^2.0.3" es6-symbol "^3.1.1" +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -5621,6 +5686,18 @@ fast-deep-equal@^3.1.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== +fast-glob@^2.2.6: + version "2.2.7" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" + integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw== + dependencies: + "@mrmlnc/readdir-enhanced" "^2.2.1" + "@nodelib/fs.stat" "^1.1.2" + glob-parent "^3.1.0" + is-glob "^4.0.0" + merge2 "^1.2.3" + micromatch "^3.1.10" + fast-glob@^3.1.1, fast-glob@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" @@ -5803,17 +5880,9 @@ find-cache-dir@^2.1.0: pkg-dir "^3.0.0" find-free-port@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/find-free-port/-/find-free-port-2.0.0.tgz#4b22e5f6579eb1a38c41ac6bcb3efed1b6da9b1b" - integrity sha1-SyLl9leesaOMQaxryz7+0bbamxs= - -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" + version "2.0.0" + resolved "https://registry.yarnpkg.com/find-free-port/-/find-free-port-2.0.0.tgz#4b22e5f6579eb1a38c41ac6bcb3efed1b6da9b1b" + integrity sha1-SyLl9leesaOMQaxryz7+0bbamxs= find-up@^2.1.0: version "2.1.0" @@ -6122,6 +6191,17 @@ gaxios@^2.1.0: is-stream "^2.0.0" node-fetch "^2.3.0" +gaxios@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-3.2.0.tgz#11b6f0e8fb08d94a10d4d58b044ad3bec6dd486a" + integrity sha512-+6WPeVzPvOshftpxJwRi2Ozez80tn/hdtOUag7+gajDHRJvAblKxTFSSMPtr2hmnLy7p0mvYz0rMXLBl8pSO7Q== + dependencies: + abort-controller "^3.0.0" + extend "^3.0.2" + https-proxy-agent "^5.0.0" + is-stream "^2.0.0" + node-fetch "^2.3.0" + gaze@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" @@ -6145,6 +6225,14 @@ gcp-metadata@^3.3.0: gaxios "^2.1.0" json-bigint "^0.3.0" +gcp-metadata@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-4.2.0.tgz#3b424355ccdc240ee07c5791e2fd6a60a283d89a" + integrity sha512-vQZD57cQkqIA6YPGXM/zc+PIZfNRFdukWGsGZ5+LcJzesi5xp6Gn7a02wRJi4eXPyArNMIYpPET4QMxGqtlk6Q== + dependencies: + gaxios "^3.0.0" + json-bigint "^1.0.0" + generate-function@^2.0.0: version "2.3.1" resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" @@ -6174,7 +6262,7 @@ get-caller-file@^1.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== -get-caller-file@^2.0.1: +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -6253,7 +6341,12 @@ glob-slasher@^1.0.1: lodash.isobject "^2.4.1" toxic "^1.0.0" -glob@7.1.6, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1: +glob-to-regexp@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" + integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= + +glob@7.1.6, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.1: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -6350,6 +6443,21 @@ google-auth-library@^5.0.0, google-auth-library@^5.5.0: jws "^4.0.0" lru-cache "^5.0.0" +google-auth-library@^6.0.0: + version "6.1.2" + resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-6.1.2.tgz#96a7b873068e2167d2d232a864c10f8f83aac216" + integrity sha512-X9EUX8R+kIpsf55KdSPhFWF0RNyBGuBc1zeYc/5Sjuk65eIYqq91rINJVBD22pp+w/PuM2fasHiA6H2xYjxTIQ== + dependencies: + arrify "^2.0.0" + base64-js "^1.3.0" + ecdsa-sig-formatter "^1.0.11" + fast-text-encoding "^1.0.0" + gaxios "^3.0.0" + gcp-metadata "^4.2.0" + gtoken "^5.0.4" + jws "^4.0.0" + lru-cache "^6.0.0" + google-auto-auth@^0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/google-auto-auth/-/google-auto-auth-0.7.2.tgz#bf9352d5c4a0897bf31fd9c491028b765fbea71e" @@ -6415,6 +6523,13 @@ google-p12-pem@^2.0.0: dependencies: node-forge "^0.9.0" +google-p12-pem@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-3.0.3.tgz#673ac3a75d3903a87f05878f3c75e06fc151669e" + integrity sha512-wS0ek4ZtFx/ACKYF3JhyGe5kzH7pgiQ7J5otlumqR9psmWMYc+U9cErKlCYVYHoUaidXHdZ2xbo34kB+S+24hA== + dependencies: + node-forge "^0.10.0" + got@^6.7.1: version "6.7.1" resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" @@ -6457,6 +6572,16 @@ gtoken@^4.1.0: jws "^4.0.0" mime "^2.2.0" +gtoken@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-5.0.4.tgz#e8d7456ad2ff774c70176e56b9d34b1c63fb6f0b" + integrity sha512-U9wnSp4GZ7ov6zRdPuRHG4TuqEWqRRgT1gfXGNArhzBUn9byrPeH8uTmBWU/ZiWJJvTEmkjhDIC3mqHWdVi3xQ== + dependencies: + gaxios "^3.0.0" + google-p12-pem "^3.0.3" + jws "^4.0.0" + mime "^2.2.0" + handle-thing@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754" @@ -6898,6 +7023,14 @@ https-proxy-agent@^4.0.0: agent-base "5" debug "4" +https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + humanize-ms@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" @@ -6912,12 +7045,12 @@ iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@~0.4.11, i dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.5.1.tgz#b2425d3c7b18f7219f2ca663d103bddb91718d64" - integrity sha512-ONHr16SQvKZNSqjQT9gy5z24Jw+uqfO02/ngBSBoqChZ+W8qXX7GPRa1RoUnzGADw8K63R1BXUMzarCVQBpY8Q== +iconv-lite@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.2.tgz#ce13d1875b0c3a674bd6a04b7f76b01b1b6ded01" + integrity sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ== dependencies: - safer-buffer ">= 2.1.2 < 3" + safer-buffer ">= 2.1.2 < 3.0.0" icss-utils@^4.0.0, icss-utils@^4.1.1: version "4.1.1" @@ -7076,21 +7209,21 @@ ini@1.3.5, ini@^1.3.4, ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== -inquirer@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.1.0.tgz#1298a01859883e17c7264b82870ae1034f92dd29" - integrity sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg== +inquirer@7.3.3: + version "7.3.3" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" + integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== dependencies: ansi-escapes "^4.2.1" - chalk "^3.0.0" + chalk "^4.1.0" cli-cursor "^3.1.0" - cli-width "^2.0.0" + cli-width "^3.0.0" external-editor "^3.0.3" figures "^3.0.0" - lodash "^4.17.15" + lodash "^4.17.19" mute-stream "0.0.8" run-async "^2.4.0" - rxjs "^6.5.3" + rxjs "^6.6.0" string-width "^4.1.0" strip-ansi "^6.0.0" through "^2.3.6" @@ -7623,11 +7756,6 @@ is-url@^1.2.2: resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" integrity sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww== -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= - is-whitespace-character@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7" @@ -7768,15 +7896,12 @@ istanbul-lib-instrument@^3.3.0: istanbul-lib-coverage "^2.0.5" semver "^6.0.0" -istanbul-lib-instrument@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.1.tgz#61f13ac2c96cfefb076fe7131156cc05907874e6" - integrity sha512-imIchxnodll7pvQBYOqUu88EufLCU56LMeFPZZM/fJZ1irYcYdqroaV+ACK1Ila8ls09iEYArp+nqyC6lW1Vfg== +istanbul-lib-instrument@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== dependencies: "@babel/core" "^7.7.5" - "@babel/parser" "^7.7.5" - "@babel/template" "^7.7.4" - "@babel/traverse" "^7.7.4" "@istanbuljs/schema" "^0.1.2" istanbul-lib-coverage "^3.0.0" semver "^6.3.0" @@ -7808,10 +7933,10 @@ istanbul-reports@^2.2.4: dependencies: html-escaper "^2.0.0" -jasmine-core@^3.4.0, jasmine-core@^3.5.0, jasmine-core@~3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.5.0.tgz#132c23e645af96d85c8bca13c8758b18429fc1e4" - integrity sha512-nCeAiw37MIMA9w9IXso7bRaLl+c/ef3wnxsoSAlYrzS+Ot0zTG6nU8G/cIfGkqpkjX2wNaIW9RFG0TwIFnG6bA== +jasmine-core@^3.6.0, jasmine-core@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-3.6.0.tgz#491f3bb23941799c353ceb7a45b38a950ebc5a20" + integrity sha512-8uQYa7zJN8hq9z+g8z1bqCfdC8eoDAeVnM5sfqs7KHv9/ifoJ500m018fpFc7RDaO6SWCLCXwo/wPSNcdYTgcw== jasmine-core@~2.8.0: version "2.8.0" @@ -7834,24 +7959,25 @@ jasmine@2.8.0: glob "^7.0.6" jasmine-core "~2.8.0" -jasmine@^3.4.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-3.5.0.tgz#7101eabfd043a1fc82ac24e0ab6ec56081357f9e" - integrity sha512-DYypSryORqzsGoMazemIHUfMkXM7I7easFaxAvNM3Mr6Xz3Fy36TupTrAOxZWN8MVKEU5xECv22J4tUQf3uBzQ== +jasmine@~3.6.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-3.6.1.tgz#a20456b309a669b547a3c24bb2120f16f70cfc65" + integrity sha512-Jqp8P6ZWkTVFGmJwBK46p+kJNrZCdqkQ4GL+PGuBXZwK1fM4ST9BizkYgIwCFqYYqnTizAy6+XG2Ej5dFrej9Q== dependencies: - glob "^7.1.4" - jasmine-core "~3.5.0" + fast-glob "^2.2.6" + jasmine-core "~3.6.0" jasminewd2@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/jasminewd2/-/jasminewd2-2.2.0.tgz#e37cf0b17f199cce23bea71b2039395246b4ec4e" integrity sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4= -jest-worker@26.0.0, jest-worker@^26.0.0: - version "26.0.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.0.0.tgz#4920c7714f0a96c6412464718d0c58a3df3fb066" - integrity sha512-pPaYa2+JnwmiZjK9x7p9BoZht+47ecFCDFA/CJxspHzeDvQcfVBLWzCiWyo+EGrSiQMWZtCFo9iSvMZnAAo8vw== +jest-worker@26.3.0, jest-worker@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.3.0.tgz#7c8a97e4f4364b4f05ed8bca8ca0c24de091871f" + integrity sha512-Vmpn2F6IASefL+DVBhPzI2J9/GJUsqzomdeN+P+dK8/jKxbh8R3BtFnx3FIta7wYlPU62cpJMJQo4kuOowcMnw== dependencies: + "@types/node" "*" merge-stream "^2.0.0" supports-color "^7.0.0" @@ -7944,6 +8070,13 @@ json-bigint@^0.3.0: dependencies: bignumber.js "^7.0.0" +json-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1" + integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ== + dependencies: + bignumber.js "^9.0.0" + json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -8004,6 +8137,11 @@ json5@^2.1.2: dependencies: minimist "^1.2.5" +jsonc-parser@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.3.0.tgz#7c7fc988ee1486d35734faaaa866fadb00fa91ee" + integrity sha512-b0EBt8SWFNnixVdvoR2ZtEGa9ZqLhbJnOjezn+WP+8kspFm+PFYDN8Z4Bc7pRlDjvuVcADSUkroIuTWWn/YiIA== + jsonfile@^2.1.0: version "2.4.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" @@ -8148,12 +8286,12 @@ karma-jasmine-html-reporter@^1.4.2: resolved "https://registry.yarnpkg.com/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.5.2.tgz#a846b703dbe5c8d803481e68636eb93346dc5966" integrity sha512-ILBPsXqQ3eomq+oaQsM311/jxsypw5/d0LnZXj26XkfThwq7jZ55A2CFSKJVA5VekbbOGvMyv7d3juZj0SeTxA== -karma-jasmine@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/karma-jasmine/-/karma-jasmine-3.1.1.tgz#f592b253e7619a8d84559d7daf473a647498ade8" - integrity sha512-pxBmv5K7IkBRLsFSTOpgiK/HzicQT3mfFF+oHAC7nxMfYKhaYFgxOa5qjnHW4sL5rUnmdkSajoudOnnOdPyW4Q== +karma-jasmine@~4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/karma-jasmine/-/karma-jasmine-4.0.1.tgz#b99e073b6d99a5196fc4bffc121b89313b0abd82" + integrity sha512-h8XDAhTiZjJKzfkoO1laMH+zfNlra+dEQHUAjpn5JV1zCPtOIVWGQjLBrqhnzQa/hrU2XrZwSyBa6XjEBzfXzw== dependencies: - jasmine-core "^3.5.0" + jasmine-core "^3.6.0" karma-source-map-support@1.4.0: version "1.4.0" @@ -8228,6 +8366,11 @@ klaw@^1.0.0: optionalDependencies: graceful-fs "^4.1.9" +klona@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0" + integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA== + latest-version@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" @@ -8256,22 +8399,21 @@ lcid@^2.0.0: dependencies: invert-kv "^2.0.0" -less-loader@6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-6.1.0.tgz#59fd591df408ced89a40fce11a2aea449b005631" - integrity sha512-/jLzOwLyqJ7Kt3xg5sHHkXtOyShWwFj410K9Si9WO+/h8rmYxxkSR0A3/hFEntWudE20zZnWMtpMYnLzqTVdUA== +less-loader@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-6.2.0.tgz#8b26f621c155b342eefc24f5bd6e9dc40c42a719" + integrity sha512-Cl5h95/Pz/PWub/tCBgT1oNMFeH1WTD33piG80jn5jr12T4XbxZcjThwNXDQ7AG649WEynuIzO4b0+2Tn9Qolg== dependencies: clone "^2.1.2" - less "^3.11.1" + less "^3.11.3" loader-utils "^2.0.0" - schema-utils "^2.6.6" + schema-utils "^2.7.0" -less@^3.11.1: - version "3.11.2" - resolved "https://registry.yarnpkg.com/less/-/less-3.11.2.tgz#51a484e9017287f5ac3db921cb86970eb7506e81" - integrity sha512-ed8Lir98Tu6a+LeU7+8ShpRLSUdk//lWf1sh+5w7tNju4wGItztqDHp03Z+a2o1nzU6pObVxw1n4Gu7VzQYusQ== +less@^3.11.3: + version "3.12.2" + resolved "https://registry.yarnpkg.com/less/-/less-3.12.2.tgz#157e6dd32a68869df8859314ad38e70211af3ab4" + integrity sha512-+1V2PCMFkL+OIj2/HrtrvZw0BC0sYLMICJfbQjuj/K8CEnlrFX6R5cKKgzzttsZDHyxQNL1jqMREjKN3ja/E3Q== dependencies: - clone "^2.1.2" tslib "^1.10.0" optionalDependencies: errno "^0.1.1" @@ -8279,8 +8421,7 @@ less@^3.11.1: image-size "~0.5.0" make-dir "^2.1.0" mime "^1.4.1" - promise "^7.1.1" - request "^2.83.0" + native-request "^1.0.5" source-map "~0.6.0" leven@^3.1.0: @@ -8303,10 +8444,10 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -license-webpack-plugin@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/license-webpack-plugin/-/license-webpack-plugin-2.2.0.tgz#5c964380d7d0e0c27c349d86a6f856c82924590e" - integrity sha512-XPsdL/0brSHf+7dXIlRqotnCQ58RX2au6otkOg4U3dm8uH+Ka/fW4iukEs95uXm+qKe/SBs+s1Ll/aQddKG+tg== +license-webpack-plugin@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/license-webpack-plugin/-/license-webpack-plugin-2.3.0.tgz#c00f70d5725ba0408de208acb9e66612cc2eceda" + integrity sha512-JK/DXrtN6UeYQSgkg5q1+pgJ8aiKPL9tnz9Wzw+Ikkf+8mJxG56x6t8O+OH/tAeF/5NREnelTEMyFtbJNkjH4w== dependencies: "@types/webpack-sources" "^0.1.5" webpack-sources "^1.2.0" @@ -8388,17 +8529,6 @@ listenercount@~1.0.1: resolved "https://registry.yarnpkg.com/listenercount/-/listenercount-1.0.1.tgz#84c8a72ab59c4725321480c975e6508342e70937" integrity sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc= -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" @@ -8639,6 +8769,11 @@ lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.1 resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +lodash@^4.17.19: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + log-symbols@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" @@ -8646,12 +8781,12 @@ log-symbols@^2.2.0: dependencies: chalk "^2.0.1" -log-symbols@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" - integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== +log-symbols@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" + integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== dependencies: - chalk "^2.4.2" + chalk "^4.0.0" log4js@^4.0.0: version "4.5.1" @@ -8723,6 +8858,13 @@ lru-cache@^5.0.0, lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + lru-queue@0.1: version "0.1.0" resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" @@ -8974,7 +9116,7 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.3.0: +merge2@^1.2.3, merge2@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -9056,10 +9198,10 @@ mimic-fn@^2.0.0, mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mini-css-extract-plugin@0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz#47f2cf07aa165ab35733b1fc97d4c46c0564339e" - integrity sha512-lp3GeY7ygcgAmVIcRPBVhIkf8Us7FZjA+ILpal44qLdSu11wmjKQ3d9k15lfD7pO4esu9eUIAW7qiYIBppv40A== +mini-css-extract-plugin@0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.10.0.tgz#a0e6bfcad22a9c73f6c882a3c7557a98e2d3d27d" + integrity sha512-QgKgJBjaJhxVPwrLNqqwNS0AGkuQQ31Hp4xGXEK/P7wehEg6qmNtReHKai3zRXqY60wGVWLYcOMJK2b98aGc3A== dependencies: loader-utils "^1.1.0" normalize-url "1.9.1" @@ -9170,6 +9312,11 @@ mississippi@^3.0.0: stream-each "^1.1.0" through2 "^2.0.0" +mitt@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mitt/-/mitt-2.1.0.tgz#f740577c23176c6205b121b2973514eade1b2230" + integrity sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg== + mixin-deep@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" @@ -9183,7 +9330,7 @@ mkdirp-classic@^0.5.2: resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== -"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1, mkdirp@~0.5.x: +"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= @@ -9202,7 +9349,7 @@ mkdirp@^1.0.3: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.3.tgz#4cf2e30ad45959dddea53ad97d518b6c8205e1ea" integrity sha512-6uCP4Qc0sWsgMLy1EOqqS/3rjDHOEnsStVr/4vtAIK2Y5i2kA7lFFejYrpIyiN9w0pYf4ckeCYT9f1r1P9KX5g== -mkdirp@^1.0.4: +mkdirp@^1.0.4, mkdirp@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -9230,13 +9377,6 @@ move-concurrently@^1.0.1: rimraf "^2.5.4" run-queue "^1.0.3" -move-file@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/move-file/-/move-file-2.0.0.tgz#83ffa309b5d7f69d518b28e1333e2ffadf331e3e" - integrity sha512-cdkdhNCgbP5dvS4tlGxZbD+nloio9GIimP57EjqFhwLcMjnU+XJKAZzlmg/TN/AK1LuNAdTSvm3CPPP4Xkv0iQ== - dependencies: - path-exists "^4.0.0" - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -9312,6 +9452,11 @@ nash@^3.0.0: lodash "^4.17.5" minimist "^1.1.0" +native-request@^1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/native-request/-/native-request-1.0.7.tgz#ff742dc555b4c8f2f1c14b548639ba174e573856" + integrity sha512-9nRjinI9bmz+S7dgNtf4A70+/vPhnd+2krGpy4SUlADuOuSa24IDkNaZ+R/QT1wQ6S8jBdi6wE7fLekFZNfUpQ== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -9327,6 +9472,11 @@ neo-async@^2.5.0, neo-async@^2.6.1: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + next-tick@1: version "1.1.0" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" @@ -9383,6 +9533,11 @@ node-forge@0.9.0: resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579" integrity sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ== +node-forge@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" + integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== + node-forge@^0.7.1: version "0.7.6" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.6.tgz#fdf3b418aee1f94f0ef642cd63486c77ca9724ac" @@ -9750,10 +9905,10 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" -open@7.0.4: - version "7.0.4" - resolved "https://registry.yarnpkg.com/open/-/open-7.0.4.tgz#c28a9d315e5c98340bf979fdcb2e58664aa10d83" - integrity sha512-brSA+/yq+b08Hsr4c8fsEW2CRzk1BmfN3SAK/5VCHQ9bdoZJ4qa/+AfR0xHjlbbZUyPkUHs1b8x1RqdyZdkVqQ== +open@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/open/-/open-7.2.0.tgz#212959bd7b0ce2e8e3676adc76e3cf2f0a2498b4" + integrity sha512-4HeyhxCvBTI5uBePsAdi55C5fmqnWZ2e2MlmvWi5KW5tdH5rxoiv/aMtbeVxKZc3eWkT1GymMnLG8XC4Rq4TDQ== dependencies: is-docker "^2.0.0" is-wsl "^2.1.1" @@ -9797,16 +9952,16 @@ optionator@^0.8.1, optionator@^0.8.2: type-check "~0.3.2" word-wrap "~1.2.3" -ora@4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/ora/-/ora-4.0.4.tgz#e8da697cc5b6a47266655bf68e0fb588d29a545d" - integrity sha512-77iGeVU1cIdRhgFzCK8aw1fbtT1B/iZAvWjS+l/o1x0RShMgxHUZaD2yDpWsNCPwXg9z1ZA78Kbdvr8kBmG/Ww== +ora@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-5.0.0.tgz#4f0b34f2994877b49b452a707245ab1e9f6afccb" + integrity sha512-s26qdWqke2kjN/wC4dy+IQPBIMWBJlSU/0JZhk30ZDBLelW25rv66yutUWARMigpGPzcXHb+Nac5pNhN/WsARw== dependencies: - chalk "^3.0.0" + chalk "^4.1.0" cli-cursor "^3.1.0" - cli-spinners "^2.2.0" + cli-spinners "^2.4.0" is-interactive "^1.0.0" - log-symbols "^3.0.0" + log-symbols "^4.0.0" mute-stream "0.0.8" strip-ansi "^6.0.0" wcwidth "^1.0.1" @@ -9903,13 +10058,6 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - p-limit@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.1.tgz#584784ac0722d1aed09f19f90ed2999af6ce2839" @@ -9917,6 +10065,13 @@ p-limit@^3.0.1: dependencies: p-try "^2.0.0" +p-limit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.2.tgz#1664e010af3cadc681baafd3e2a437be7b0fb5fe" + integrity sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg== + dependencies: + p-try "^2.0.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -10063,13 +10218,6 @@ parse-entities@^1.0.2, parse-entities@^1.1.0: is-decimal "^1.0.0" is-hexadecimal "^1.0.0" -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= - dependencies: - error-ex "^1.2.0" - parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" @@ -10078,10 +10226,17 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" -parse5@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" - integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA== +parse5-htmlparser2-tree-adapter@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6" + integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA== + dependencies: + parse5 "^6.0.1" + +parse5@6.0.1, parse5@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== parse5@^1.5.1: version "1.5.1" @@ -10142,13 +10297,6 @@ path-dirname@^1.0.0: resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= - dependencies: - pinkie-promise "^2.0.0" - path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -10191,15 +10339,6 @@ path-to-regexp@^1.7.0: dependencies: isarray "0.0.1" -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" @@ -10282,7 +10421,7 @@ pkg-dir@^3.0.0: dependencies: find-up "^3.0.0" -pkg-dir@^4.1.0: +pkg-dir@^4.1.0, pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== @@ -10506,15 +10645,15 @@ postcss-modules-extract-imports@^2.0.0: dependencies: postcss "^7.0.5" -postcss-modules-local-by-default@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz#e8a6561be914aaf3c052876377524ca90dbb7915" - integrity sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ== +postcss-modules-local-by-default@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0" + integrity sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw== dependencies: icss-utils "^4.1.1" - postcss "^7.0.16" + postcss "^7.0.32" postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.0.0" + postcss-value-parser "^4.1.0" postcss-modules-scope@^2.2.0: version "2.2.0" @@ -10693,7 +10832,7 @@ postcss-value-parser@^3.0.0, postcss-value-parser@^3.2.3, postcss-value-parser@^ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.3, postcss-value-parser@^4.1.0: +postcss-value-parser@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== @@ -10707,10 +10846,10 @@ postcss@7.0.21: source-map "^0.6.1" supports-color "^6.1.0" -postcss@7.0.31: - version "7.0.31" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.31.tgz#332af45cb73e26c0ee2614d7c7fb02dfcc2bd6dd" - integrity sha512-a937VDHE1ftkjk+8/7nj/mrjtmkn69xxzJgRETXdAUU+IgOYPQNJF17haGWbeDxSyk++HA14UA98FurvPyBJOA== +postcss@7.0.32: + version "7.0.32" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" + integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== dependencies: chalk "^2.4.2" source-map "^0.6.1" @@ -10725,7 +10864,7 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.5: source-map "^0.6.1" supports-color "^6.1.0" -postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.27, postcss@^7.0.6: +postcss@^7.0.14, postcss@^7.0.6: version "7.0.29" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.29.tgz#d3a903872bd52280b83bce38cdc83ce55c06129e" integrity sha512-ba0ApvR3LxGvRMMiUa9n0WR4HjzcYm7tS+ht4/2Nd0NLtHpPIH77fuB9Xh1/yJVz9O/E/95Y/dn8ygWsyffXtw== @@ -10734,10 +10873,10 @@ postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.27, postcss@^7.0.6: source-map "^0.6.1" supports-color "^6.1.0" -postcss@^7.0.30: - version "7.0.32" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" - integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== +postcss@^7.0.32: + version "7.0.34" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.34.tgz#f2baf57c36010df7de4009940f21532c16d65c20" + integrity sha512-H/7V2VeNScX9KE83GDrDZNiGT1m2H+UTnlinIzhjlLX9hfMUn1mHNnGeX81a1c8JSBdBvqk7c2ZOG6ZPn5itGw== dependencies: chalk "^2.4.2" source-map "^0.6.1" @@ -10801,13 +10940,6 @@ promise-retry@^1.1.1: err-code "^1.0.0" retry "^0.10.0" -promise@^7.1.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" - integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== - dependencies: - asap "~2.0.3" - property-information@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/property-information/-/property-information-4.2.0.tgz#f0e66e07cbd6fed31d96844d958d153ad3eb486e" @@ -10841,6 +10973,25 @@ protobufjs@^6.8.1, protobufjs@^6.8.6, protobufjs@^6.8.8: "@types/node" "^10.1.0" long "^4.0.0" +protobufjs@^6.9.0: + version "6.10.1" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.10.1.tgz#e6a484dd8f04b29629e9053344e3970cccf13cd2" + integrity sha512-pb8kTchL+1Ceg4lFd5XUpK8PdWacbvV5SK2ULH2ebrYtl4GjJmS24m6CKME67jzV53tbJxHlnNOSqQHbTsR9JQ== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/long" "^4.0.1" + "@types/node" "^13.7.0" + long "^4.0.0" + protoduck@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/protoduck/-/protoduck-5.0.1.tgz#03c3659ca18007b69a50fd82a7ebcc516261151f" @@ -10954,15 +11105,18 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -puppeteer@3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-3.3.0.tgz#95839af9fdc0aa4de7e5ee073a4c0adeb9e2d3d7" - integrity sha512-23zNqRltZ1PPoK28uRefWJ/zKb5Jhnzbbwbpcna2o5+QMn17F0khq5s1bdH3vPlyj+J36pubccR8wiNA/VE0Vw== +puppeteer@5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-5.1.0.tgz#e7bae2caa6e3a13a622755e4c27689d9812c38ca" + integrity sha512-IZBFG8XcA+oHxYo5rEpJI/HQignUis2XPijPoFpNxla2O+WufonGsUsSqrhRXgBKOME5zNfhRdUY2LvxAiKlhw== dependencies: debug "^4.1.0" + devtools-protocol "0.0.767361" extract-zip "^2.0.0" https-proxy-agent "^4.0.0" mime "^2.0.3" + mitt "^2.0.1" + pkg-dir "^4.2.0" progress "^2.0.1" proxy-from-env "^1.0.0" rimraf "^3.0.2" @@ -11118,23 +11272,6 @@ read-package-tree@5.3.1: readdir-scoped-modules "^1.0.0" util-promisify "^2.1.0" -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - read-pkg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" @@ -11204,6 +11341,13 @@ readdirp@~3.3.0: dependencies: picomatch "^2.0.7" +readdirp@~3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada" + integrity sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ== + dependencies: + picomatch "^2.2.1" + readline2@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" @@ -11251,16 +11395,21 @@ regenerate@^1.2.1, regenerate@^1.4.0: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== -regenerator-runtime@0.13.5, regenerator-runtime@^0.13.4: - version "0.13.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" - integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== +regenerator-runtime@0.13.7: + version "0.13.7" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== regenerator-runtime@^0.13.2: version "0.13.3" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw== +regenerator-runtime@^0.13.4: + version "0.13.5" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697" + integrity sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA== + regenerator-transform@^0.14.2: version "0.14.4" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.4.tgz#5266857896518d1616a78a0479337a30ea974cc7" @@ -11512,7 +11661,7 @@ replace-ext@1.0.0: resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= -request@^2.72.0, request@^2.74.0, request@^2.79.0, request@^2.81.0, request@^2.83.0, request@^2.87.0, request@^2.88.0: +request@^2.72.0, request@^2.74.0, request@^2.79.0, request@^2.81.0, request@^2.87.0, request@^2.88.0, request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -11740,10 +11889,10 @@ robots-parser@^2.0.1: resolved "https://registry.yarnpkg.com/robots-parser/-/robots-parser-2.1.1.tgz#41b289cf44a6aa136dc62be0085adca954573ab0" integrity sha512-6yWEYSdhK3bAEcYY0In3wgSBK70BiQoJArzdjZKCP/35b3gKIYu5Lc0qQqsoxjoLVebVoJiKK4VWGc5+oxvWBQ== -rollup@2.10.9: - version "2.10.9" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.10.9.tgz#17dcc6753c619efcc1be2cf61d73a87827eebdf9" - integrity sha512-dY/EbjiWC17ZCUSyk14hkxATAMAShkMsD43XmZGWjLrgFj15M3Dw2kEkA9ns64BiLFm9PKN6vTQw8neHwK74eg== +rollup@2.26.5: + version "2.26.5" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.26.5.tgz#5562ec36fcba3eed65cfd630bd78e037ad0e0307" + integrity sha512-rCyFG3ZtQdnn9YwfuAVH0l/Om34BdO5lwCA0W6Hq+bNB21dVEBbCRxhaHOmu1G7OBFDWytbzAC104u7rxHwGjA== optionalDependencies: fsevents "~2.1.2" @@ -11815,10 +11964,10 @@ rx-lite@^3.1.2: resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" integrity sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI= -rxjs@6.5.5: - version "6.5.5" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec" - integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ== +rxjs@6.6.2: + version "6.6.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.2.tgz#8096a7ac03f2cc4fe5860ef6e572810d9e01c0d2" + integrity sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg== dependencies: tslib "^1.9.0" @@ -11829,6 +11978,13 @@ rxjs@^6.4.0, rxjs@^6.5.3: dependencies: tslib "^1.9.0" +rxjs@^6.6.0: + version "6.6.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552" + integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== + dependencies: + tslib "^1.9.0" + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -11872,26 +12028,26 @@ safeps@7.0.1: taskgroup "^5.0.0" typechecker "^4.3.0" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@^2.1.2, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@^2.1.2, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sass-loader@8.0.2: - version "8.0.2" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-8.0.2.tgz#debecd8c3ce243c76454f2e8290482150380090d" - integrity sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ== +sass-loader@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-10.0.1.tgz#10c0364d8034f22fee25ddcc9eded20f99bbe3b4" + integrity sha512-b2PSldKVTS3JcFPHSrEXh3BeAfR7XknGiGCAO5aHruR3Pf3kqLP3Gb2ypXLglRrAzgZkloNxLZ7GXEGDX0hBUQ== dependencies: - clone-deep "^4.0.1" - loader-utils "^1.2.3" - neo-async "^2.6.1" - schema-utils "^2.6.1" - semver "^6.3.0" + klona "^2.0.3" + loader-utils "^2.0.0" + neo-async "^2.6.2" + schema-utils "^2.7.0" + semver "^7.3.2" -sass@1.26.5: - version "1.26.5" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.26.5.tgz#2d7aecfbbabfa298567c8f06615b6e24d2d68099" - integrity sha512-FG2swzaZUiX53YzZSjSakzvGtlds0lcbF+URuU9mxOv7WBh7NhXEVDa4kPKN4hN6fC2TkOTOKqiqp6d53N9X5Q== +sass@1.26.10: + version "1.26.10" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.26.10.tgz#851d126021cdc93decbf201d1eca2a20ee434760" + integrity sha512-bzN0uvmzfsTvjz0qwccN1sPm2HxxpNI/Xa+7PlUEMS+nQvbyuEK7Y0qFqxlPHhiNHb1Ze8WQJtU31olMObkAMw== dependencies: chokidar ">=2.0.0 <4.0.0" @@ -11925,14 +12081,6 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -schema-utils@^2.6.1, schema-utils@^2.6.4: - version "2.6.4" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.4.tgz#a27efbf6e4e78689d91872ee3ccfa57d7bdd0f53" - integrity sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ== - dependencies: - ajv "^6.10.2" - ajv-keywords "^3.4.1" - schema-utils@^2.6.5: version "2.6.5" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.5.tgz#c758f0a7e624263073d396e29cd40aa101152d8a" @@ -12011,7 +12159,7 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@7.3.2: +semver@7.3.2, semver@^7.3.2: version "7.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== @@ -12058,11 +12206,6 @@ serialize-javascript@^2.1.2: resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== -serialize-javascript@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-3.0.0.tgz#492e489a2d77b7b804ad391a5f5d97870952548e" - integrity sha512-skZcHYw2vEX4bw90nAr2iTTsz6x2SrHEnfxgKYmZlvJYBEZrvbKtobJWlQ20zczKb3bsHHXXTYt48zBA7ni9cw== - serialize-javascript@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" @@ -12141,13 +12284,6 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" -shallow-clone@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" - integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== - dependencies: - kind-of "^6.0.2" - shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -12338,16 +12474,16 @@ source-list-map@^2.0.0: resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== -source-map-loader@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-1.0.0.tgz#240b88575a9b0d27214aeecbd4e7686af95cfa56" - integrity sha512-ZayyQCSCrQazN50aCvuS84lJT4xc1ZAcykH5blHaBdVveSwjiFK8UGMPvao0ho54DTb0Jf7m57uRRG/YYUZ2Fg== +source-map-loader@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-1.0.2.tgz#b0a6582b2eaa387ede1ecf8061ae0b93c23f9eb0" + integrity sha512-oX8d6ndRjN+tVyjj6PlXSyFPhDdVAPsZA30nD3/II8g4uOv8fCz0DMn5sy8KtVbDfKQxOpGwGJnK3xIW3tauDw== dependencies: data-urls "^2.0.0" - iconv-lite "^0.5.1" + iconv-lite "^0.6.2" loader-utils "^2.0.0" - schema-utils "^2.6.6" - source-map "^0.6.0" + schema-utils "^2.7.0" + source-map "^0.6.1" source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: version "0.5.3" @@ -12628,7 +12764,7 @@ string-length@^1.0.0: dependencies: strip-ansi "^3.0.0" -string-width@^1.0.1, string-width@^1.0.2: +string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= @@ -12760,13 +12896,6 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= - dependencies: - is-utf8 "^0.2.0" - strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -12813,18 +12942,18 @@ stylus-loader@3.0.2: lodash.clonedeep "^4.5.0" when "~3.6.x" -stylus@0.54.7: - version "0.54.7" - resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.54.7.tgz#c6ce4793965ee538bcebe50f31537bfc04d88cd2" - integrity sha512-Yw3WMTzVwevT6ZTrLCYNHAFmanMxdylelL3hkWNgPMeTCpMwpV3nXjpOHuBXtFv7aiO2xRuQS6OoAdgkNcSNug== +stylus@0.54.8: + version "0.54.8" + resolved "https://registry.yarnpkg.com/stylus/-/stylus-0.54.8.tgz#3da3e65966bc567a7b044bfe0eece653e099d147" + integrity sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg== dependencies: css-parse "~2.0.0" debug "~3.1.0" - glob "^7.1.3" - mkdirp "~0.5.x" + glob "^7.1.6" + mkdirp "~1.0.4" safer-buffer "^2.1.2" sax "~1.2.4" - semver "^6.0.0" + semver "^6.3.0" source-map "^0.7.3" superstatic@^6.0.1: @@ -13056,19 +13185,19 @@ term-size@^1.2.0: dependencies: execa "^0.7.0" -terser-webpack-plugin@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-3.0.1.tgz#31928c9330a582fb5ec6f90805337289b85cb8fe" - integrity sha512-eFDtq8qPUEa9hXcUzTwKXTnugIVtlqc1Z/ZVhG8LmRT3lgRY13+pQTnFLY2N7ATB6TKCHuW/IGjoAnZz9wOIqw== +terser-webpack-plugin@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-4.1.0.tgz#6e9d6ae4e1a900d88ddce8da6a47507ea61f44bc" + integrity sha512-0ZWDPIP8BtEDZdChbufcXUigOYk6dOX/P/X0hWxqDDcVAQLb8Yy/0FAaemSfax3PAA67+DJR778oz8qVbmy4hA== dependencies: - cacache "^15.0.3" + cacache "^15.0.5" find-cache-dir "^3.3.1" - jest-worker "^26.0.0" - p-limit "^2.3.0" + jest-worker "^26.3.0" + p-limit "^3.0.2" schema-utils "^2.6.6" - serialize-javascript "^3.0.0" + serialize-javascript "^4.0.0" source-map "^0.6.1" - terser "^4.6.13" + terser "^5.0.0" webpack-sources "^1.4.3" terser-webpack-plugin@^1.4.3: @@ -13086,10 +13215,10 @@ terser-webpack-plugin@^1.4.3: webpack-sources "^1.4.0" worker-farm "^1.7.0" -terser@4.7.0, terser@^4.6.13: - version "4.7.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.7.0.tgz#15852cf1a08e3256a80428e865a2fa893ffba006" - integrity sha512-Lfb0RiZcjRDXCC3OSHJpEkxJ9Qeqs6mp2v4jf2MHfy8vGERmVDuvjXdd/EnP5Deme5F2yBRBymKmKHCBg2echw== +terser@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.3.0.tgz#c481f4afecdcc182d5e2bdd2ff2dc61555161e81" + integrity sha512-XTT3D3AwxC54KywJijmY2mxZ8nJiEjBHVYzq8l9OaYuRFWeQNBwvipuzzYEP4e+/AVcd1hqG/CqgsdIRyT45Fg== dependencies: commander "^2.20.0" source-map "~0.6.1" @@ -13104,6 +13233,15 @@ terser@^4.1.2: source-map "~0.6.1" source-map-support "~0.5.12" +terser@^5.0.0: + version "5.3.2" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.3.2.tgz#f4bea90eb92945b2a028ceef79181b9bb586e7af" + integrity sha512-H67sydwBz5jCUA32ZRL319ULu+Su1cAoZnnc+lXnenGRYWyLE3Scgkt8mNoAsMx0h5kdo758zdoS0LG9rYZXDQ== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -13329,10 +13467,10 @@ ts-pnp@^1.1.6: resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== -tslib@2.0.0, tslib@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.0.tgz#18d13fc2dce04051e20f074cc8387fd8089ce4f3" - integrity sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g== +tslib@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e" + integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ== tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0: version "1.10.0" @@ -13340,9 +13478,14 @@ tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0: integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== tslib@^1.11.1: - version "1.13.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" - integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.0.tgz#18d13fc2dce04051e20f074cc8387fd8089ce4f3" + integrity sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g== tslint@~6.1.0: version "6.1.2" @@ -13429,15 +13572,20 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +typescript@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.2.tgz#7ea7c88777c723c681e33bf7988be5d008d05ac2" + integrity sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ== + typescript@^3.2.2: version "3.7.5" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae" integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw== -typescript@~3.9.5: - version "3.9.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36" - integrity sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ== +typescript@~4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.3.tgz#153bbd468ef07725c1df9c77e8b453f8d36abba5" + integrity sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg== ua-parser-js@0.7.21: version "0.7.21" @@ -13670,7 +13818,16 @@ unist-util-visit@^1.0.0, unist-util-visit@^1.1.0, unist-util-visit@^1.1.1: dependencies: unist-util-visit-parents "^2.0.0" -universal-analytics@0.4.20, universal-analytics@^0.4.16: +universal-analytics@0.4.23: + version "0.4.23" + resolved "https://registry.yarnpkg.com/universal-analytics/-/universal-analytics-0.4.23.tgz#d915e676850c25c4156762471bdd7cf2eaaca8ac" + integrity sha512-lgMIH7XBI6OgYn1woDEmxhGdj8yDefMKg7GkWdeATAlQZFrMrNyxSkpDzY57iY0/6fdlzTbBV03OawvvzG+q7A== + dependencies: + debug "^4.1.1" + request "^2.88.2" + uuid "^3.0.0" + +universal-analytics@^0.4.16: version "0.4.20" resolved "https://registry.yarnpkg.com/universal-analytics/-/universal-analytics-0.4.20.tgz#d6b64e5312bf74f7c368e3024a922135dbf24b03" integrity sha512-gE91dtMvNkjO+kWsPstHRtSwHXz0l2axqptGYp5ceg4MsuurloM0PU3pdOfpb5zBXUvyjT4PwhWK2m39uczZuw== @@ -13861,10 +14018,10 @@ uuid@3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== -uuid@8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.1.0.tgz#6f1536eb43249f473abc6bd58ff983da1ca30d8d" - integrity sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg== +uuid@8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.0.tgz#ab738085ca22dc9a8c92725e459b1d507df5d6ea" + integrity sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ== uuid@^2.0.1: version "2.0.3" @@ -13980,14 +14137,23 @@ walkdir@^0.4.0: resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.4.1.tgz#dc119f83f4421df52e3061e514228a2db20afa39" integrity sha512-3eBwRyEln6E1MSzcxcVpQIhRG8Q1jLvEqRmCZqS3dsfXEDR/AhOF4d+jHg1qvDCpYaVRZjENPQyrVxAkQqxPgQ== -watchpack@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.1.tgz#280da0a8718592174010c078c7585a74cd8cd0e2" - integrity sha512-+IF9hfUFOrYOOaKyfaI7h7dquUIOgyEMoQMLA7OP5FxegKA2+XdXThAZ9TU2kucfhDH7rfMHs1oPYziVGWRnZA== +watchpack-chokidar2@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0" + integrity sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA== dependencies: chokidar "^2.1.8" + +watchpack@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.4.tgz#6e9da53b3c80bb2d6508188f5b200410866cd30b" + integrity sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg== + dependencies: graceful-fs "^4.1.2" neo-async "^2.5.0" + optionalDependencies: + chokidar "^3.4.1" + watchpack-chokidar2 "^2.0.0" watchr@^3.0.1: version "3.0.1" @@ -14141,10 +14307,10 @@ webpack-subresource-integrity@1.4.1: dependencies: webpack-sources "^1.3.0" -webpack@4.43.0: - version "4.43.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.43.0.tgz#c48547b11d563224c561dad1172c8aa0b8a678e6" - integrity sha512-GW1LjnPipFW2Y78OOab8NJlCflB7EFskMih2AHdvjbpKMeDJqEgSx24cXXXiPS65+WSwVyxtDsJH6jGX2czy+g== +webpack@4.44.1: + version "4.44.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.1.tgz#17e69fff9f321b8f117d1fda714edfc0b939cc21" + integrity sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ== dependencies: "@webassemblyjs/ast" "1.9.0" "@webassemblyjs/helper-module-context" "1.9.0" @@ -14154,7 +14320,7 @@ webpack@4.43.0: ajv "^6.10.2" ajv-keywords "^3.4.1" chrome-trace-event "^1.0.2" - enhanced-resolve "^4.1.0" + enhanced-resolve "^4.3.0" eslint-scope "^4.0.3" json-parse-better-errors "^1.0.2" loader-runner "^2.4.0" @@ -14167,7 +14333,7 @@ webpack@4.43.0: schema-utils "^1.0.0" tapable "^1.1.3" terser-webpack-plugin "^1.4.3" - watchpack "^1.6.1" + watchpack "^1.7.4" webpack-sources "^1.4.1" websocket-driver@0.6.5: @@ -14204,9 +14370,9 @@ whatwg-fetch@2.0.4: integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== whatwg-fetch@>=0.10.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.4.0.tgz#e11de14f4878f773fbebcde8871b2c0699af8b30" - integrity sha512-rsum2ulz2iuZH08mJkT0Yi6JnKhwdw4oeyMjokgxd+mmqYSd9cPpOQf01TIWgjxG/U4+QR+AwKq6lSbXVxkyoQ== + version "3.4.1" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.4.1.tgz#e5f871572d6879663fa5674c8f833f15a8425ab3" + integrity sha512-sofZVzE1wKwO+EYPbWfiwzaKovWiZXf4coEzjGP9b2GBVgQRLQUZ2QcuPpQExGDAW5GItpEm6Tl4OU5mywnAoQ== whatwg-mimetype@^2.3.0: version "2.3.0" @@ -14235,11 +14401,6 @@ when@~3.6.x: resolved "https://registry.yarnpkg.com/when/-/when-3.6.4.tgz#473b517ec159e2b85005497a13983f095412e34e" integrity sha1-RztRfsFZ4rhQBUl6E5g/CVQS404= -which-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= - which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" @@ -14306,10 +14467,10 @@ worker-farm@^1.7.0: dependencies: errno "~0.1.7" -worker-plugin@4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/worker-plugin/-/worker-plugin-4.0.3.tgz#7c42e600d5931ad154d3d5f187a32446df64db0f" - integrity sha512-7hFDYWiKcE3yHZvemsoM9lZis/PzurHAEX1ej8PLCu818Rt6QqUAiDdxHPCKZctzmhqzPpcFSgvMCiPbtooqAg== +worker-plugin@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/worker-plugin/-/worker-plugin-5.0.0.tgz#113b5fe1f4a5d6a957cecd29915bedafd70bb537" + integrity sha512-AXMUstURCxDD6yGam2r4E34aJg6kW85IiaeX72hi+I1cxyaMUtrvVY6sbfpGKAj5e7f68Acl62BjQF5aOOx2IQ== dependencies: loader-utils "^1.1.0" @@ -14339,6 +14500,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -14476,7 +14646,7 @@ xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== -y18n@^3.2.0, y18n@^3.2.1: +y18n@^3.2.0: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= @@ -14486,6 +14656,11 @@ y18n@^3.2.0, y18n@^3.2.1: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== +y18n@^5.0.2: + version "5.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.3.tgz#978115b82befe2b5c762bf55980b7b01a4a2d5d9" + integrity sha512-JeFbcHQ/7hVmMBXW6UB6Tg7apStHd/ztGz1JN78y3pFi/q0Ht1eA6PVkvw56gm7UA8fcJR/ziRlYEDMGoju0yQ== + yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" @@ -14525,12 +14700,10 @@ yargs-parser@^18.1.0, yargs-parser@^18.1.1, yargs-parser@^18.1.3: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" - integrity sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo= - dependencies: - camelcase "^3.0.0" +yargs-parser@^20.2.2: + version "20.2.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.2.tgz#84562c6b1c41ccec2f13d346c7dd83f8d1a0dc70" + integrity sha512-XmrpXaTl6noDsf1dKpBuUNCOHqjs0g3jRMXf/ztRxdOmb+er8kE5z5b55Lz3p5u2T8KJ59ENBnASS8/iapVJ5g== yargs@15.3.0: version "15.3.0" @@ -14613,24 +14786,18 @@ yargs@^15.3.1: y18n "^4.0.0" yargs-parser "^18.1.1" -yargs@^7.0.2: - version "7.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" - integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg= +yargs@^16.1.0: + version "16.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.1.0.tgz#fc333fe4791660eace5a894b39d42f851cd48f2a" + integrity sha512-upWFJOmDdHN0syLuESuvXDmrRcWd1QafJolHskzaw79uZa7/x53gxQKiR07W59GWY1tFhhU/Th9DrtSfpS782g== dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - y18n "^3.2.1" - yargs-parser "^5.0.0" + string-width "^4.2.0" + y18n "^5.0.2" + yargs-parser "^20.2.2" yauzl@^2.10.0: version "2.10.0" @@ -14673,8 +14840,3 @@ zone.js@~0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.10.3.tgz#3e5e4da03c607c9dcd92e37dd35687a14a140c16" integrity sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg== - -zone.js@~0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.9.1.tgz#e37c6e5c54c13fae4de26b5ffe8d8e9212da6d9b" - integrity sha512-GkPiJL8jifSrKReKaTZ5jkhrMEgXbXYC+IPo1iquBjayRa0q86w3Dipjn8b415jpitMExe9lV8iTsv8tk3DGag== diff --git a/browser-providers.conf.js b/browser-providers.conf.js index a377f4fac6543..b49dd9f26b52d 100644 --- a/browser-providers.conf.js +++ b/browser-providers.conf.js @@ -12,8 +12,10 @@ // If a category becomes empty (e.g. BS and required), then the corresponding job must be commented // out in the CI configuration. var CIconfiguration = { - 'Chrome': {unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}}, - 'Firefox': {unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}}, + // Chrome and Firefox run as part of the Bazel browser tests, so we do not run them as + // part of the legacy Saucelabs tests. + 'Chrome': {unitTest: {target: null, required: false}, e2e: {target: null, required: true}}, + 'Firefox': {unitTest: {target: null, required: false}, e2e: {target: null, required: true}}, // Set ESR as a not required browser as it fails for Ivy acceptance tests. 'FirefoxESR': {unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}}, // Disabled because using the "beta" channel of Chrome can cause non-deterministic CI results. @@ -25,8 +27,6 @@ var CIconfiguration = { // Currently deactivated due to https://github.com/angular/angular/issues/7560 'FirefoxBeta': {unitTest: {target: null, required: true}, e2e: {target: null, required: false}}, 'FirefoxDev': {unitTest: {target: null, required: true}, e2e: {target: null, required: true}}, - 'IE9': {unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}}, - 'IE10': {unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}}, 'IE11': {unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}}, 'Edge': {unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}}, 'Android7': {unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}}, @@ -88,14 +88,6 @@ var customLaunchers = { version: '13.0', device: 'iPhone 11 Simulator' }, - 'SL_IE9': - {base: 'SauceLabs', browserName: 'internet explorer', platform: 'Windows 2008', version: '9'}, - 'SL_IE10': { - base: 'SauceLabs', - browserName: 'internet explorer', - platform: 'Windows 2012', - version: '10' - }, 'SL_IE11': {base: 'SauceLabs', browserName: 'internet explorer', platform: 'Windows 8.1', version: '11'}, 'SL_EDGE': { @@ -135,15 +127,6 @@ var customLaunchers = { 'BS_CHROME': {base: 'BrowserStack', browser: 'chrome', os: 'OS X', os_version: 'Yosemite'}, 'BS_FIREFOX': {base: 'BrowserStack', browser: 'firefox', os: 'Windows', os_version: '10'}, 'BS_SAFARI10': {base: 'BrowserStack', browser: 'safari', os: 'OS X', os_version: 'Sierra'}, - 'BS_IE9': - {base: 'BrowserStack', browser: 'ie', browser_version: '9.0', os: 'Windows', os_version: '7'}, - 'BS_IE10': { - base: 'BrowserStack', - browser: 'ie', - browser_version: '10.1', - os: 'Windows', - os_version: '8' - }, 'BS_IE11': { base: 'BrowserStack', browser: 'ie', @@ -162,13 +145,12 @@ var sauceAliases = { return customLaunchers[item].base == 'SauceLabs'; }), 'DESKTOP': [ - 'SL_CHROME', 'SL_FIREFOX', 'SL_IE9', 'SL_IE10', 'SL_IE11', 'SL_EDGE', 'SL_SAFARI12', - 'SL_SAFARI13', 'SL_FIREFOXESR' + 'SL_CHROME', 'SL_FIREFOX', 'SL_IE11', 'SL_EDGE', 'SL_SAFARI12', 'SL_SAFARI13', 'SL_FIREFOXESR' ], 'MOBILE': ['SL_ANDROID7', 'SL_ANDROID8', 'SL_ANDROID9', 'SL_ANDROID10', 'SL_IOS12', 'SL_IOS13'], 'ANDROID': ['SL_ANDROID7', 'SL_ANDROID8', 'SL_ANDROID9', 'SL_ANDROID10'], 'FIREFOX': ['SL_FIREFOXESR'], - 'IE': ['SL_IE9', 'SL_IE10', 'SL_IE11'], + 'IE': ['SL_IE11'], 'IOS': ['SL_IOS12', 'SL_IOS13'], 'SAFARI': ['SL_SAFARI12', 'SL_SAFARI13'], 'BETA': ['SL_CHROMEBETA', 'SL_FIREFOXBETA'], @@ -184,14 +166,12 @@ var browserstackAliases = { 'DESKTOP': [ 'BS_CHROME', 'BS_FIREFOX', - 'BS_IE9', - 'BS_IE10', 'BS_IE11', 'BS_EDGE', ], 'MOBILE': ['BS_ANDROID7', 'BS_WINDOWSPHONE'], 'ANDROID': ['BS_ANDROID7'], - 'IE': ['BS_IE9', 'BS_IE10', 'BS_IE11'], + 'IE': ['BS_IE11'], 'IOS': [], 'SAFARI': [], 'CI_REQUIRED': buildConfiguration('unitTest', 'BS', true), diff --git a/dev-infra/BUILD.bazel b/dev-infra/BUILD.bazel index 1906e83c04aac..5492b72fddb44 100644 --- a/dev-infra/BUILD.bazel +++ b/dev-infra/BUILD.bazel @@ -1,5 +1,5 @@ load("@build_bazel_rules_nodejs//:index.bzl", "pkg_npm") -load("@npm_bazel_typescript//:index.bzl", "ts_library") +load("@npm//@bazel/typescript:index.bzl", "ts_library") ts_library( name = "cli", @@ -8,8 +8,10 @@ ts_library( ], module_name = "@angular/dev-infra-private", deps = [ + "//dev-infra/caretaker", "//dev-infra/commit-message", "//dev-infra/format", + "//dev-infra/ngbot", "//dev-infra/pr", "//dev-infra/pullapprove", "//dev-infra/release", @@ -47,7 +49,7 @@ pkg_npm( # substitutions to replace these in the published version of dev-infra. "//dev-infra/": "@npm_angular_dev_infra_private//", "//packages/benchpress": "@npm//@angular/benchpress", - "//packages/bazel/": "@npm_angular_bazel//", + "//packages/bazel": "@npm//@angular/bazel", "//packages/zone.js/bundles:zone.umd.js": "@npm//:node_modules/zone.js/dist/zone.js", "//packages/core": "@npm//@angular/core", "//packages/platform-browser": "@npm//@angular/platform-browser", @@ -55,7 +57,7 @@ pkg_npm( # This substitution is particularly verbose because we need to make sure # that only things available via Angular Bazel are imported from # tools/defaults.bzl. - "load\(\"//tools:defaults.bzl\", \"ng_module\"\)": "load(\"@npm_angular_bazel//:index.bzl\", \"ng_module\")", + "load\(\"//tools:defaults.bzl\", \"ng_module\"\)": "load(\"@npm//@angular/bazel:index.bzl\", \"ng_module\")", }, visibility = ["//visibility:public"], deps = [ diff --git a/dev-infra/benchmark/component_benchmark/benchmark_test.bzl b/dev-infra/benchmark/component_benchmark/benchmark_test.bzl index 8cbfc98a712aa..450bf051ca65e 100644 --- a/dev-infra/benchmark/component_benchmark/benchmark_test.bzl +++ b/dev-infra/benchmark/component_benchmark/benchmark_test.bzl @@ -1,4 +1,4 @@ -load("@npm_bazel_protractor//:index.bzl", "protractor_web_test_suite") +load("@npm//@bazel/protractor:index.bzl", "protractor_web_test_suite") """ Macro that can be used to define a benchmark test. This differentiates from diff --git a/dev-infra/benchmark/component_benchmark/component_benchmark.bzl b/dev-infra/benchmark/component_benchmark/component_benchmark.bzl index 809e92d2592d1..62a82272c0660 100644 --- a/dev-infra/benchmark/component_benchmark/component_benchmark.bzl +++ b/dev-infra/benchmark/component_benchmark/component_benchmark.bzl @@ -1,6 +1,6 @@ load("//dev-infra/benchmark/ng_rollup_bundle:ng_rollup_bundle.bzl", "ng_rollup_bundle") load("//tools:defaults.bzl", "ng_module") -load("@npm_bazel_typescript//:index.bzl", "ts_devserver", "ts_library") +load("@npm//@bazel/typescript:index.bzl", "ts_devserver", "ts_library") load(":benchmark_test.bzl", "benchmark_test") def copy_default_file(origin, destination): diff --git a/dev-infra/benchmark/driver-utilities/BUILD.bazel b/dev-infra/benchmark/driver-utilities/BUILD.bazel index d9086bef93d07..1117bd505709f 100644 --- a/dev-infra/benchmark/driver-utilities/BUILD.bazel +++ b/dev-infra/benchmark/driver-utilities/BUILD.bazel @@ -1,6 +1,6 @@ package(default_visibility = ["//visibility:public"]) -load("@npm_bazel_typescript//:index.bzl", "ts_library") +load("@npm//@bazel/typescript:index.bzl", "ts_library") ts_library( name = "driver-utilities", diff --git a/dev-infra/benchmark/driver-utilities/e2e_util.ts b/dev-infra/benchmark/driver-utilities/e2e_util.ts index 55d21fa96cc2d..3b391f26e4844 100644 --- a/dev-infra/benchmark/driver-utilities/e2e_util.ts +++ b/dev-infra/benchmark/driver-utilities/e2e_util.ts @@ -13,7 +13,7 @@ import * as webdriver from 'selenium-webdriver'; declare var expect: any; export function openBrowser(config: { - url: string, + url?: string, params?: {name: string, value: any}[], ignoreBrowserSynchronization?: boolean }) { diff --git a/dev-infra/benchmark/driver-utilities/perf_util.ts b/dev-infra/benchmark/driver-utilities/perf_util.ts index ab27079f0c456..b6d59a4a1d1ec 100644 --- a/dev-infra/benchmark/driver-utilities/perf_util.ts +++ b/dev-infra/benchmark/driver-utilities/perf_util.ts @@ -23,27 +23,34 @@ const globalOptions = { const runner = createBenchpressRunner(); -export async function runBenchmark(config: { +export async function runBenchmark({ + id, + url = '', + params = [], + ignoreBrowserSynchronization = true, + microMetrics, + work, + prepare, + setup, +}: { id: string, - url: string, - params: {name: string, value: any}[], + url?: string, + params?: {name: string, value: any}[], ignoreBrowserSynchronization?: boolean, microMetrics?: {[key: string]: string}, - work?: () => void, - prepare?: () => void, - setup?: () => void + work?: (() => void)|(() => Promise), + prepare?: (() => void)|(() => Promise), + setup?: (() => void)|(() => Promise), }): Promise { - openBrowser(config); - if (config.setup) { - await config.setup(); + openBrowser({url, params, ignoreBrowserSynchronization}); + if (setup) { + await setup(); } - const description: {[key: string]: any} = {}; - config.params.forEach((param) => description[param.name] = param.value); return runner.sample({ - id: config.id, - execute: config.work, - prepare: config.prepare, - microMetrics: config.microMetrics, + id, + execute: work, + prepare, + microMetrics, providers: [{provide: Options.SAMPLE_DESCRIPTION, useValue: {}}] }); } diff --git a/dev-infra/benchmark/ng_rollup_bundle/ng_rollup_bundle.bzl b/dev-infra/benchmark/ng_rollup_bundle/ng_rollup_bundle.bzl index a7eb00e66f8a5..2684c219aaefe 100644 --- a/dev-infra/benchmark/ng_rollup_bundle/ng_rollup_bundle.bzl +++ b/dev-infra/benchmark/ng_rollup_bundle/ng_rollup_bundle.bzl @@ -4,8 +4,8 @@ # found in the LICENSE file at https://angular.io/license load("@build_bazel_rules_nodejs//:index.bzl", "npm_package_bin") -load("@npm_bazel_terser//:index.bzl", "terser_minified") -load("@npm_bazel_rollup//:index.bzl", "rollup_bundle") +load("@npm//@bazel/terser:index.bzl", "terser_minified") +load("@npm//@bazel/rollup:index.bzl", "rollup_bundle") load("//dev-infra/bazel:expand_template.bzl", "expand_template") def ng_rollup_bundle( diff --git a/dev-infra/browsers/chromium/chromium.bzl b/dev-infra/browsers/chromium/chromium.bzl index 1048b85d88da2..4b2b6d1d781a4 100644 --- a/dev-infra/browsers/chromium/chromium.bzl +++ b/dev-infra/browsers/chromium/chromium.bzl @@ -12,47 +12,47 @@ def define_chromium_repositories(): platform_http_file( name = "org_chromium_chromium_amd64", licenses = ["notice"], # BSD 3-clause (maybe more?) - sha256 = "2cfd74ee58c79d8b7aada05c899a930967e2fd8bb0186582cde02c7340863f64", - # 83.0.4103 - urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Linux_x64/756066/chrome-linux.zip"], + sha256 = "0e303931d9c3e065a160f5d31f1178c647f0748fb0b58b1945b84b04fe1c1165", + # 84.0.4147 + urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Linux_x64/768968/chrome-linux.zip"], ) platform_http_file( name = "org_chromium_chromium_macos", licenses = ["notice"], # BSD 3-clause (maybe more?) - sha256 = "b841ec5ad03b08422d97593fc719f1c5b038703388ad65e6cd8cc8272d58958c", - # 83.0.4103 - urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Mac/756053/chrome-mac.zip"], + sha256 = "39118c96db1b3fdb0129f434912a329c5ca07d3a1c6c6cda673d3383d83e2f9a", + # 84.0.4147 + urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Mac/768968/chrome-mac.zip"], ) platform_http_file( name = "org_chromium_chromium_windows", licenses = ["notice"], # BSD 3-clause (maybe more?) - sha256 = "4683d7ac88dfec4b98d1da3012ecc8e42cc8c1a560a7b95589ad4cc96bf90fcb", - # 83.0.4103 - urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Win/756065/chrome-win.zip"], + sha256 = "3429746fa80c917c6f4d5d96aba4e58894b905a2b8392e43ddb470c5ba612d60", + # 84.0.4147 + urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Win/768975/chrome-win.zip"], ) platform_http_file( name = "org_chromium_chromedriver_amd64", licenses = ["reciprocal"], # BSD 3-clause, ICU, MPL 1.1, libpng (BSD/MIT-like), Academic Free License v. 2.0, BSD 2-clause, MIT - sha256 = "95dded16000b82e31445361da7d251ed707e027a4b61e9a3ec5fbd1cc2f62bb1", - # 83.0.4103 - urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Linux_x64/756066/chromedriver_linux64.zip"], + sha256 = "f6b9852031d185739a2c1816508fe8158eb92782d13e831b8345957ef2506fe8", + # 84.0.4147 + urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Linux_x64/768968/chromedriver_linux64.zip"], ) platform_http_file( name = "org_chromium_chromedriver_macos", licenses = ["reciprocal"], # BSD 3-clause, ICU, MPL 1.1, libpng (BSD/MIT-like), Academic Free License v. 2.0, BSD 2-clause, MIT - sha256 = "17260e9b2222b0c905a1861285210192baef830f4281778903e7cebb8db683cc", - # 83.0.4103 - urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Mac/756053/chromedriver_mac64.zip"], + sha256 = "aa0124085146556d5d32ad172670e5dcef79b7429380112ad02898047ba7a8b7", + # 84.0.4147 + urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Mac/768968/chromedriver_mac64.zip"], ) platform_http_file( name = "org_chromium_chromedriver_windows", licenses = ["reciprocal"], # BSD 3-clause, ICU, MPL 1.1, libpng (BSD/MIT-like), Academic Free License v. 2.0, BSD 2-clause, MIT - sha256 = "de1423b2d69f96e451e902d686e8d471610d786c345a8de59dd1a5a436e45fc2", - # 83.0.4103 - urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Win/756065/chromedriver_win32.zip"], + sha256 = "c4b04fd263e757d3aa99c596832f2c414f9f00e80d2769590e2b9044072b140e", + # 84.0.4147 + urls = ["https://commondatastorage.googleapis.com/chromium-browser-snapshots/Win/768975/chromedriver_win32.zip"], ) diff --git a/dev-infra/caretaker/BUILD.bazel b/dev-infra/caretaker/BUILD.bazel new file mode 100644 index 0000000000000..eb834938659d3 --- /dev/null +++ b/dev-infra/caretaker/BUILD.bazel @@ -0,0 +1,22 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_library") + +ts_library( + name = "caretaker", + srcs = glob([ + "**/*.ts", + ]), + module_name = "@angular/dev-infra-private/caretaker", + visibility = ["//dev-infra:__subpackages__"], + deps = [ + "//dev-infra/release/versioning", + "//dev-infra/utils", + "@npm//@types/node", + "@npm//@types/node-fetch", + "@npm//@types/yargs", + "@npm//multimatch", + "@npm//node-fetch", + "@npm//typed-graphqlify", + "@npm//yaml", + "@npm//yargs", + ], +) diff --git a/dev-infra/caretaker/check/check.ts b/dev-infra/caretaker/check/check.ts new file mode 100644 index 0000000000000..ebd51125f8342 --- /dev/null +++ b/dev-infra/caretaker/check/check.ts @@ -0,0 +1,30 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {GitClient} from '../../utils/git'; +import {getCaretakerConfig} from '../config'; + +import {printCiStatus} from './ci'; +import {printG3Comparison} from './g3'; +import {printGithubTasks} from './github'; +import {printServiceStatuses} from './services'; + + +/** Check the status of services which Angular caretakers need to monitor. */ +export async function checkServiceStatuses(githubToken: string) { + /** The configuration for the caretaker commands. */ + const config = getCaretakerConfig(); + /** The GitClient for interacting with git and Github. */ + const git = new GitClient(githubToken, config); + + // TODO(josephperrott): Allow these checks to be loaded in parallel. + await printServiceStatuses(); + await printGithubTasks(git, config.caretaker); + await printG3Comparison(git); + await printCiStatus(git); +} diff --git a/dev-infra/caretaker/check/ci.ts b/dev-infra/caretaker/check/ci.ts new file mode 100644 index 0000000000000..ff32fe052cb6f --- /dev/null +++ b/dev-infra/caretaker/check/ci.ts @@ -0,0 +1,62 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import fetch from 'node-fetch'; +import {fetchActiveReleaseTrains} from '../../release/versioning/index'; + +import {bold, debug, info} from '../../utils/console'; +import {GitClient} from '../../utils/git'; + + +/** The results of checking the status of CI. */ +interface StatusCheckResult { + status: 'success'|'failed'; +} + +/** Retrieve and log status of CI for the project. */ +export async function printCiStatus(git: GitClient) { + const releaseTrains = await fetchActiveReleaseTrains({api: git.github, ...git.remoteConfig}); + + info.group(bold(`CI`)); + for (const [trainName, train] of Object.entries(releaseTrains)) { + if (train === null) { + debug(`No active release train for ${trainName}`); + continue; + } + const status = await getStatusOfBranch(git, train.branchName); + await printStatus(`${trainName.padEnd(6)} (${train.branchName})`, status); + } + info.groupEnd(); + info(); +} + +/** Log the status of CI for a given branch to the console. */ +async function printStatus(label: string, status: StatusCheckResult|null) { + const branchName = label.padEnd(16); + if (status === null) { + info(`${branchName} was not found on CircleCI`); + } else if (status.status === 'success') { + info(`${branchName} ✅`); + } else { + info(`${branchName} ❌`); + } +} + +/** Get the CI status of a given branch from CircleCI. */ +async function getStatusOfBranch(git: GitClient, branch: string): Promise { + const {owner, name} = git.remoteConfig; + const url = `https://circleci.com/gh/${owner}/${name}/tree/${branch}.svg?style=shield`; + const result = await fetch(url).then(result => result.text()); + + if (result && !result.includes('no builds')) { + return { + status: result.includes('passing') ? 'success' : 'failed', + }; + } + return null; +} diff --git a/dev-infra/caretaker/check/cli.ts b/dev-infra/caretaker/check/cli.ts new file mode 100644 index 0000000000000..19883814238c4 --- /dev/null +++ b/dev-infra/caretaker/check/cli.ts @@ -0,0 +1,36 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {Arguments, Argv, CommandModule} from 'yargs'; + +import {addGithubTokenOption} from '../../utils/git/github-yargs'; + +import {checkServiceStatuses} from './check'; + + +export interface CaretakerCheckOptions { + githubToken: string; +} + +/** Builds the command. */ +function builder(yargs: Argv) { + return addGithubTokenOption(yargs); +} + +/** Handles the command. */ +async function handler({githubToken}: Arguments) { + await checkServiceStatuses(githubToken); +} + +/** yargs command module for checking status information for the repository */ +export const CheckModule: CommandModule<{}, CaretakerCheckOptions> = { + handler, + builder, + command: 'check', + describe: 'Check the status of information the caretaker manages for the repository', +}; diff --git a/dev-infra/caretaker/check/g3.ts b/dev-infra/caretaker/check/g3.ts new file mode 100644 index 0000000000000..1a5d8a48e63f4 --- /dev/null +++ b/dev-infra/caretaker/check/g3.ts @@ -0,0 +1,125 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {existsSync, readFileSync} from 'fs'; +import * as multimatch from 'multimatch'; +import {join} from 'path'; +import {parse as parseYaml} from 'yaml'; + +import {getRepoBaseDir} from '../../utils/config'; +import {bold, debug, info} from '../../utils/console'; +import {GitClient} from '../../utils/git'; + +/** Compare the upstream master to the upstream g3 branch, if it exists. */ +export async function printG3Comparison(git: GitClient) { + const angularRobotFilePath = join(getRepoBaseDir(), '.github/angular-robot.yml'); + if (!existsSync(angularRobotFilePath)) { + return debug('No angular robot configuration file exists, skipping.'); + } + + /** The configuration defined for the angular robot. */ + const robotConfig = parseYaml(readFileSync(angularRobotFilePath).toString()); + /** The files to be included in the g3 sync. */ + const includeFiles = robotConfig?.merge?.g3Status?.include || []; + /** The files to be expected in the g3 sync. */ + const excludeFiles = robotConfig?.merge?.g3Status?.exclude || []; + + if (includeFiles.length === 0 && excludeFiles.length === 0) { + debug('No g3Status include or exclude lists are defined in the angular robot configuration,'); + debug('skipping.'); + return; + } + + /** The latest sha for the g3 branch. */ + const g3Ref = getShaForBranchLatest('g3'); + /** The latest sha for the master branch. */ + const masterRef = getShaForBranchLatest('master'); + + if (!g3Ref && !masterRef) { + return debug('Exiting early as either the g3 or master was unable to be retrieved'); + } + + /** The statistical information about the git diff between master and g3. */ + const stats = getDiffStats(); + + info.group(bold('g3 branch check')); + info(`${stats.commits} commits between g3 and master`); + if (stats.files === 0) { + info('✅ No sync is needed at this time'); + } else { + info(`${stats.files} files changed, ${stats.insertions} insertions(+), ${ + stats.deletions} deletions(-) will be included in the next sync`); + } + info.groupEnd(); + info(); + + + /** Fetch and retrieve the latest sha for a specific branch. */ + function getShaForBranchLatest(branch: string) { + /** The result fo the fetch command. */ + const fetchResult = git.runGraceful([ + 'fetch', '-q', `https://github.com/${git.remoteConfig.owner}/${git.remoteConfig.name}.git`, + branch + ]); + + if (fetchResult.status !== 0 && + fetchResult.stderr.includes(`couldn't find remote ref ${branch}`)) { + debug(`No '${branch}' branch exists on upstream, skipping.`); + return false; + } + return git.runGraceful(['rev-parse', 'FETCH_HEAD']).stdout.trim(); + } + + /** + * Get git diff stats between master and g3, for all files and filtered to only g3 affecting + * files. + */ + function getDiffStats() { + /** The diff stats to be returned. */ + const stats = { + insertions: 0, + deletions: 0, + files: 0, + commits: 0, + }; + + // Determine the number of commits between master and g3 refs. */ + stats.commits = parseInt(git.run(['rev-list', '--count', `${g3Ref}..${masterRef}`]).stdout, 10); + + // Get the numstat information between master and g3 + git.run(['diff', `${g3Ref}...${masterRef}`, '--numstat']) + .stdout + // Remove the extra space after git's output. + .trim() + // Split each line of git output into array + .split('\n') + // Split each line from the git output into components parts: insertions, + // deletions and file name respectively + .map(line => line.split('\t')) + // Parse number value from the insertions and deletions values + // Example raw line input: + // 10\t5\tsrc/file/name.ts + .map(line => [Number(line[0]), Number(line[1]), line[2]] as [number, number, string]) + // Add each line's value to the diff stats, and conditionally to the g3 + // stats as well if the file name is included in the files synced to g3. + .forEach(([insertions, deletions, fileName]) => { + if (checkMatchAgainstIncludeAndExclude(fileName, includeFiles, excludeFiles)) { + stats.insertions += insertions; + stats.deletions += deletions; + stats.files += 1; + } + }); + return stats; + } + + /** Determine whether the file name passes both include and exclude checks. */ + function checkMatchAgainstIncludeAndExclude( + file: string, includes: string[], excludes: string[]) { + return multimatch(file, includes).length >= 1 && multimatch(file, excludes).length === 0; + } +} diff --git a/dev-infra/caretaker/check/github.ts b/dev-infra/caretaker/check/github.ts new file mode 100644 index 0000000000000..664e8b539fa62 --- /dev/null +++ b/dev-infra/caretaker/check/github.ts @@ -0,0 +1,83 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {alias, onUnion, params, types} from 'typed-graphqlify'; + +import {bold, debug, info} from '../../utils/console'; +import {GitClient} from '../../utils/git'; +import {CaretakerConfig} from '../config'; + +/** + * Cap the returned issues in the queries to an arbitrary 100. At that point, caretaker has a lot + * of work to do and showing more than that isn't really useful. + */ +const MAX_RETURNED_ISSUES = 20; + +/** Retrieve the number of matching issues for each github query. */ +export async function printGithubTasks(git: GitClient, config?: CaretakerConfig) { + if (!config?.githubQueries?.length) { + debug('No github queries defined in the configuration, skipping.'); + return; + } + info.group(bold(`Github Tasks`)); + await getGithubInfo(git, config); + info.groupEnd(); + info(); +} + +/** Retrieve query match counts and log discovered counts to the console. */ +async function getGithubInfo(git: GitClient, {githubQueries: queries = []}: CaretakerConfig) { + /** The query object for graphql. */ + const graphQlQuery: { + [key: string]: { + issueCount: number, + nodes: Array<{url: string}>, + } + } = {}; + /** The Github search filter for the configured repository. */ + const repoFilter = `repo:${git.remoteConfig.owner}/${git.remoteConfig.name}`; + queries.forEach(({name, query}) => { + /** The name of the query, with spaces removed to match GraphQL requirements. */ + const queryKey = alias(name.replace(/ /g, ''), 'search'); + graphQlQuery[queryKey] = params( + { + type: 'ISSUE', + first: MAX_RETURNED_ISSUES, + query: `"${repoFilter} ${query.replace(/"/g, '\\"')}"`, + }, + { + issueCount: types.number, + nodes: [{...onUnion({ + PullRequest: { + url: types.string, + }, + Issue: { + url: types.string, + }, + })}], + }, + ); + }); + /** The results of the generated github query. */ + const results = await git.github.graphql.query(graphQlQuery); + Object.values(results).forEach((result, i) => { + info(`${queries[i]?.name.padEnd(25)} ${result.issueCount}`); + if (result.issueCount > 0) { + const {owner, name: repo} = git.remoteConfig; + const url = encodeURI(`https://github.com/${owner}/${repo}/issues?q=${queries[i]?.query}`); + info.group(`${url}`); + if (result.nodes.length === MAX_RETURNED_ISSUES && result.nodes.length < result.issueCount) { + info(`(first ${MAX_RETURNED_ISSUES})`); + } + for (const node of result.nodes) { + info(`- ${node.url}`); + } + info.groupEnd(); + } + }); +} diff --git a/dev-infra/caretaker/check/services.ts b/dev-infra/caretaker/check/services.ts new file mode 100644 index 0000000000000..8fd3a2dbc33ef --- /dev/null +++ b/dev-infra/caretaker/check/services.ts @@ -0,0 +1,79 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import fetch from 'node-fetch'; + +import {bold, green, info, red} from '../../utils/console'; + +/** The status levels for services. */ +enum ServiceStatus { + GREEN, + RED +} + +/** The results of checking the status of a service */ +interface StatusCheckResult { + status: ServiceStatus; + description: string; + lastUpdated: Date; +} + +/** Retrieve and log stasuses for all of the services of concern. */ +export async function printServiceStatuses() { + info.group(bold(`Service Statuses (checked: ${new Date().toLocaleString()})`)); + logStatus('CircleCI', await getCircleCiStatus()); + logStatus('Github', await getGithubStatus()); + logStatus('NPM', await getNpmStatus()); + logStatus('Saucelabs', await getSaucelabsStatus()); + info.groupEnd(); + info(); +} + + +/** Log the status of the service to the console. */ +function logStatus(serviceName: string, status: StatusCheckResult) { + serviceName = serviceName.padEnd(15); + if (status.status === ServiceStatus.GREEN) { + info(`${serviceName} ${green('✅')}`); + } else if (status.status === ServiceStatus.RED) { + info.group(`${serviceName} ${red('❌')} (Updated: ${status.lastUpdated.toLocaleString()})`); + info(` Details: ${status.description}`); + info.groupEnd(); + } +} + +/** Gets the service status information for Saucelabs. */ +async function getSaucelabsStatus(): Promise { + return getStatusFromStandardApi('https://status.us-west-1.saucelabs.com/api/v2/status.json'); +} + +/** Gets the service status information for NPM. */ +async function getNpmStatus(): Promise { + return getStatusFromStandardApi('https://status.npmjs.org/api/v2/status.json'); +} + +/** Gets the service status information for CircleCI. */ +async function getCircleCiStatus(): Promise { + return getStatusFromStandardApi('https://status.circleci.com/api/v2/status.json'); +} + +/** Gets the service status information for Github. */ +async function getGithubStatus(): Promise { + return getStatusFromStandardApi('https://www.githubstatus.com/api/v2/status.json'); +} + +/** Retrieve the status information for a service which uses a standard API response. */ +async function getStatusFromStandardApi(url: string) { + const result = await fetch(url).then(result => result.json()); + const status = result.status.indicator === 'none' ? ServiceStatus.GREEN : ServiceStatus.RED; + return { + status, + description: result.status.description, + lastUpdated: new Date(result.page.updated_at) + }; +} diff --git a/dev-infra/caretaker/cli.ts b/dev-infra/caretaker/cli.ts new file mode 100644 index 0000000000000..dd464699e83a0 --- /dev/null +++ b/dev-infra/caretaker/cli.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {Argv} from 'yargs'; +import {CheckModule} from './check/cli'; + + +/** Build the parser for the caretaker commands. */ +export function buildCaretakerParser(yargs: Argv) { + return yargs.command(CheckModule); +} diff --git a/dev-infra/caretaker/config.ts b/dev-infra/caretaker/config.ts new file mode 100644 index 0000000000000..8ac7ea630335d --- /dev/null +++ b/dev-infra/caretaker/config.ts @@ -0,0 +1,24 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {assertNoErrors, getConfig, NgDevConfig} from '../utils/config'; + +export interface CaretakerConfig { + githubQueries?: {name: string; query: string;}[]; +} + +/** Retrieve and validate the config as `CaretakerConfig`. */ +export function getCaretakerConfig() { + // List of errors encountered validating the config. + const errors: string[] = []; + // The non-validated config object. + const config: Partial> = getConfig(); + + assertNoErrors(errors); + return config as Required; +} diff --git a/dev-infra/cli.ts b/dev-infra/cli.ts index a220486865826..c83db4117c546 100644 --- a/dev-infra/cli.ts +++ b/dev-infra/cli.ts @@ -13,8 +13,12 @@ import {buildCommitMessageParser} from './commit-message/cli'; import {buildFormatParser} from './format/cli'; import {buildReleaseParser} from './release/cli'; import {buildPrParser} from './pr/cli'; +import {captureLogOutputForCommand} from './utils/console'; +import {buildCaretakerParser} from './caretaker/cli'; +import {buildNgbotParser} from './ngbot/cli'; yargs.scriptName('ng-dev') + .middleware(captureLogOutputForCommand) .demandCommand() .recommendCommands() .command('commit-message ', '', buildCommitMessageParser) @@ -23,6 +27,8 @@ yargs.scriptName('ng-dev') .command('pullapprove ', '', buildPullapproveParser) .command('release ', '', buildReleaseParser) .command('ts-circular-deps ', '', tsCircularDependenciesBuilder) + .command('caretaker ', '', buildCaretakerParser) + .command('ngbot ', false, buildNgbotParser) .wrap(120) .strict() .parse(); diff --git a/dev-infra/commit-message/BUILD.bazel b/dev-infra/commit-message/BUILD.bazel index 2c6d3be371924..e6d77a54562bb 100644 --- a/dev-infra/commit-message/BUILD.bazel +++ b/dev-infra/commit-message/BUILD.bazel @@ -1,31 +1,30 @@ load("//tools:defaults.bzl", "jasmine_node_test") -load("@npm_bazel_typescript//:index.bzl", "ts_library") +load("@npm//@bazel/typescript:index.bzl", "ts_library") ts_library( name = "commit-message", - srcs = [ - "cli.ts", - "config.ts", - "validate.ts", - "validate-file.ts", - "validate-range.ts", - ], + srcs = glob( + ["**/*.ts"], + exclude = ["**/*.spec.ts"], + ), module_name = "@angular/dev-infra-private/commit-message", visibility = ["//dev-infra:__subpackages__"], deps = [ "//dev-infra/utils", + "@npm//@types/inquirer", "@npm//@types/node", "@npm//@types/shelljs", "@npm//@types/yargs", + "@npm//inquirer", "@npm//shelljs", "@npm//yargs", ], ) ts_library( - name = "validate-test", + name = "test_lib", testonly = True, - srcs = ["validate.spec.ts"], + srcs = glob(["**/*.spec.ts"]), deps = [ ":commit-message", "//dev-infra/utils", @@ -40,7 +39,6 @@ jasmine_node_test( name = "test", bootstrap = ["//tools/testing:node_no_angular_es5"], deps = [ - ":commit-message", - ":validate-test", + "test_lib", ], ) diff --git a/dev-infra/commit-message/builder.spec.ts b/dev-infra/commit-message/builder.spec.ts new file mode 100644 index 0000000000000..5b45ac4140c6f --- /dev/null +++ b/dev-infra/commit-message/builder.spec.ts @@ -0,0 +1,46 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as config from '../utils/config'; +import * as console from '../utils/console'; + +import {buildCommitMessage} from './builder'; + + +describe('commit message building:', () => { + beforeEach(() => { + // stub logging calls to prevent noise in test log + spyOn(console, 'info').and.stub(); + // provide a configuration for DevInfra when loaded + spyOn(config, 'getConfig').and.returnValue({ + commitMessage: { + scopes: ['core'], + } + } as any); + }); + + it('creates a commit message with a scope', async () => { + buildPromptResponseSpies('fix', 'core', 'This is a summary'); + + expect(await buildCommitMessage()).toMatch(/^fix\(core\): This is a summary/); + }); + + it('creates a commit message without a scope', async () => { + buildPromptResponseSpies('build', false, 'This is a summary'); + + expect(await buildCommitMessage()).toMatch(/^build: This is a summary/); + }); +}); + + +/** Create spies to return the mocked selections from prompts. */ +function buildPromptResponseSpies(type: string, scope: string|false, summary: string) { + spyOn(console, 'promptAutocomplete') + .and.returnValues(Promise.resolve(type), Promise.resolve(scope)); + spyOn(console, 'promptInput').and.returnValue(Promise.resolve(summary)); +} diff --git a/dev-infra/commit-message/builder.ts b/dev-infra/commit-message/builder.ts new file mode 100644 index 0000000000000..f663f3619d471 --- /dev/null +++ b/dev-infra/commit-message/builder.ts @@ -0,0 +1,70 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +import {ListChoiceOptions} from 'inquirer'; + +import {info, promptAutocomplete, promptInput} from '../utils/console'; + +import {COMMIT_TYPES, CommitType, getCommitMessageConfig, ScopeRequirement} from './config'; + +/** Validate commit message at the provided file path. */ +export async function buildCommitMessage() { + // TODO(josephperrott): Add support for skipping wizard with local untracked config file + // TODO(josephperrott): Add default commit message information/commenting into generated messages + info('Just a few questions to start building the commit message!'); + + /** The commit message type. */ + const type = await promptForCommitMessageType(); + /** The commit message scope. */ + const scope = await promptForCommitMessageScopeForType(type); + /** The commit message summary. */ + const summary = await promptForCommitMessageSummary(); + + return `${type.name}${scope ? '(' + scope + ')' : ''}: ${summary}\n\n`; +} + +/** Prompts in the terminal for the commit message's type. */ +async function promptForCommitMessageType(): Promise { + info('The type of change in the commit. Allows a reader to know the effect of the change,'); + info('whether it brings a new feature, adds additional testing, documents the `project, etc.'); + + /** List of commit type options for the autocomplete prompt. */ + const typeOptions: ListChoiceOptions[] = + Object.values(COMMIT_TYPES).map(({description, name}) => { + return { + name: `${name} - ${description}`, + value: name, + short: name, + }; + }); + /** The key of a commit message type, selected by the user via prompt. */ + const typeName = await promptAutocomplete('Select a type for the commit:', typeOptions); + + return COMMIT_TYPES[typeName]; +} + +/** Prompts in the terminal for the commit message's scope. */ +async function promptForCommitMessageScopeForType(type: CommitType): Promise { + // If the commit type's scope requirement is forbidden, return early. + if (type.scope === ScopeRequirement.Forbidden) { + info(`Skipping scope selection as the '${type.name}' type does not allow scopes`); + return false; + } + /** Commit message configuration */ + const config = getCommitMessageConfig(); + + info('The area of the repository the changes in this commit most affects.'); + return await promptAutocomplete( + 'Select a scope for the commit:', config.commitMessage.scopes, + type.scope === ScopeRequirement.Optional ? '' : ''); +} + +/** Prompts in the terminal for the commit message's summary. */ +async function promptForCommitMessageSummary(): Promise { + info('Provide a short summary of what the changes in the commit do'); + return await promptInput('Provide a short summary of the commit'); +} diff --git a/dev-infra/commit-message/cli.ts b/dev-infra/commit-message/cli.ts index f7b2cc8936cdc..9230b03d0ce23 100644 --- a/dev-infra/commit-message/cli.ts +++ b/dev-infra/commit-message/cli.ts @@ -7,61 +7,19 @@ */ import * as yargs from 'yargs'; -import {info} from '../utils/console'; - -import {validateFile} from './validate-file'; -import {validateCommitRange} from './validate-range'; +import {RestoreCommitMessageModule} from './restore-commit-message/cli'; +import {ValidateFileModule} from './validate-file/cli'; +import {ValidateRangeModule} from './validate-range/cli'; +import {WizardModule} from './wizard/cli'; /** Build the parser for the commit-message commands. */ export function buildCommitMessageParser(localYargs: yargs.Argv) { return localYargs.help() .strict() - .command( - 'pre-commit-validate', 'Validate the most recent commit message', { - 'file': { - type: 'string', - conflicts: ['file-env-variable'], - description: 'The path of the commit message file.', - }, - 'file-env-variable': { - type: 'string', - conflicts: ['file'], - description: - 'The key of the environment variable for the path of the commit message file.', - coerce: arg => { - const file = process.env[arg]; - if (!file) { - throw new Error(`Provided environment variable "${arg}" was not found.`); - } - return file; - }, - } - }, - args => { - const file = args.file || args.fileEnvVariable || '.git/COMMIT_EDITMSG'; - validateFile(file); - }) - .command( - 'validate-range', 'Validate a range of commit messages', { - 'range': { - description: 'The range of commits to check, e.g. --range abc123..xyz456', - demandOption: ' A range must be provided, e.g. --range abc123..xyz456', - type: 'string', - requiresArg: true, - }, - }, - argv => { - // If on CI, and not pull request number is provided, assume the branch - // being run on is an upstream branch. - if (process.env['CI'] && process.env['CI_PULL_REQUEST'] === 'false') { - info(`Since valid commit messages are enforced by PR linting on CI, we do not`); - info(`need to validate commit messages on CI runs on upstream branches.`); - info(); - info(`Skipping check of provided commit range`); - return; - } - validateCommitRange(argv.range); - }); + .command(RestoreCommitMessageModule) + .command(WizardModule) + .command(ValidateFileModule) + .command(ValidateRangeModule); } if (require.main == module) { diff --git a/dev-infra/commit-message/commit-message-draft.ts b/dev-infra/commit-message/commit-message-draft.ts new file mode 100644 index 0000000000000..86a5655fd09b0 --- /dev/null +++ b/dev-infra/commit-message/commit-message-draft.ts @@ -0,0 +1,30 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +import {existsSync, readFileSync, unlinkSync, writeFileSync} from 'fs'; + +/** Load the commit message draft from the file system if it exists. */ +export function loadCommitMessageDraft(basePath: string) { + const commitMessageDraftPath = `${basePath}.ngDevSave`; + if (existsSync(commitMessageDraftPath)) { + return readFileSync(commitMessageDraftPath).toString(); + } + return ''; +} + +/** Remove the commit message draft from the file system. */ +export function deleteCommitMessageDraft(basePath: string) { + const commitMessageDraftPath = `${basePath}.ngDevSave`; + if (existsSync(commitMessageDraftPath)) { + unlinkSync(commitMessageDraftPath); + } +} + +/** Save the commit message draft to the file system for later retrieval. */ +export function saveCommitMessageDraft(basePath: string, commitMessage: string) { + writeFileSync(`${basePath}.ngDevSave`, commitMessage); +} diff --git a/packages/platform-webworker-dynamic/public_api.ts b/dev-infra/commit-message/commit-message-source.ts similarity index 50% rename from packages/platform-webworker-dynamic/public_api.ts rename to dev-infra/commit-message/commit-message-source.ts index f6ddc07fc9139..c8a9640e839ed 100644 --- a/packages/platform-webworker-dynamic/public_api.ts +++ b/dev-infra/commit-message/commit-message-source.ts @@ -7,9 +7,7 @@ */ /** - * @module - * @description - * Entry point for all public APIs of this package. + * The source triggering the git commit message creation. + * As described in: https://git-scm.com/docs/githooks#_prepare_commit_msg */ -export * from './src/platform-webworker-dynamic'; -// This file only reexports content of the `src` folder. Keep it that way. +export type CommitMsgSource = 'message'|'template'|'merge'|'squash'|'commit'; diff --git a/dev-infra/commit-message/config.ts b/dev-infra/commit-message/config.ts index 2d9739cecf368..613c59decbd85 100644 --- a/dev-infra/commit-message/config.ts +++ b/dev-infra/commit-message/config.ts @@ -8,11 +8,11 @@ import {assertNoErrors, getConfig, NgDevConfig} from '../utils/config'; +/** Configuration for commit-message comands. */ export interface CommitMessageConfig { maxLineLength: number; minBodyLength: number; minBodyLengthTypeExcludes?: string[]; - types: string[]; scopes: string[]; } @@ -30,3 +30,66 @@ export function getCommitMessageConfig() { assertNoErrors(errors); return config as Required; } + +/** Scope requirement level to be set for each commit type. */ +export enum ScopeRequirement { + Required, + Optional, + Forbidden, +} + +/** A commit type */ +export interface CommitType { + description: string; + name: string; + scope: ScopeRequirement; +} + +/** The valid commit types for Angular commit messages. */ +export const COMMIT_TYPES: {[key: string]: CommitType} = { + build: { + name: 'build', + description: 'Changes to local repository build system and tooling', + scope: ScopeRequirement.Optional, + }, + ci: { + name: 'ci', + description: 'Changes to CI configuration and CI specific tooling', + scope: ScopeRequirement.Forbidden, + }, + docs: { + name: 'docs', + description: 'Changes which exclusively affects documentation.', + scope: ScopeRequirement.Optional, + }, + feat: { + name: 'feat', + description: 'Creates a new feature', + scope: ScopeRequirement.Required, + }, + fix: { + name: 'fix', + description: 'Fixes a previously discovered failure/bug', + scope: ScopeRequirement.Required, + }, + perf: { + name: 'perf', + description: 'Improves performance without any change in functionality or API', + scope: ScopeRequirement.Required, + }, + refactor: { + name: 'refactor', + description: 'Refactor without any change in functionality or API (includes style changes)', + scope: ScopeRequirement.Required, + }, + release: { + name: 'release', + description: 'A release point in the repository', + scope: ScopeRequirement.Forbidden, + }, + test: { + name: 'test', + description: 'Improvements or corrections made to the project\'s test suite', + scope: ScopeRequirement.Required, + }, +}; diff --git a/dev-infra/commit-message/parse.spec.ts b/dev-infra/commit-message/parse.spec.ts new file mode 100644 index 0000000000000..22a79934a923e --- /dev/null +++ b/dev-infra/commit-message/parse.spec.ts @@ -0,0 +1,105 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {parseCommitMessage, ParsedCommitMessage} from './parse'; + + +const commitValues = { + prefix: '', + type: 'fix', + scope: 'changed-area', + summary: 'This is a short summary of the change', + body: 'This is a longer description of the change Closes #1', +}; + +function buildCommitMessage(params = {}) { + const {prefix, type, scope, summary, body} = {...commitValues, ...params}; + return `${prefix}${type}${scope ? '(' + scope + ')' : ''}: ${summary}\n\n${body}`; +} + + +describe('commit message parsing:', () => { + it('parses the scope', () => { + const message = buildCommitMessage(); + expect(parseCommitMessage(message).scope).toBe(commitValues.scope); + }); + + it('parses the type', () => { + const message = buildCommitMessage(); + expect(parseCommitMessage(message).type).toBe(commitValues.type); + }); + + it('parses the header', () => { + const message = buildCommitMessage(); + expect(parseCommitMessage(message).header) + .toBe(`${commitValues.type}(${commitValues.scope}): ${commitValues.summary}`); + }); + + it('parses the body', () => { + const message = buildCommitMessage(); + expect(parseCommitMessage(message).body).toBe(commitValues.body); + }); + + it('parses the body without Github linking', () => { + const body = 'This has linking\nCloses #1'; + const message = buildCommitMessage({body}); + expect(parseCommitMessage(message).bodyWithoutLinking).toBe('This has linking\n'); + }); + + it('parses the subject', () => { + const message = buildCommitMessage(); + expect(parseCommitMessage(message).subject).toBe(commitValues.summary); + }); + + it('identifies if a commit is a fixup', () => { + const message1 = buildCommitMessage(); + expect(parseCommitMessage(message1).isFixup).toBe(false); + + const message2 = buildCommitMessage({prefix: 'fixup! '}); + expect(parseCommitMessage(message2).isFixup).toBe(true); + }); + + it('identifies if a commit is a revert', () => { + const message1 = buildCommitMessage(); + expect(parseCommitMessage(message1).isRevert).toBe(false); + + const message2 = buildCommitMessage({prefix: 'revert: '}); + expect(parseCommitMessage(message2).isRevert).toBe(true); + + const message3 = buildCommitMessage({prefix: 'revert '}); + expect(parseCommitMessage(message3).isRevert).toBe(true); + }); + + it('identifies if a commit is a squash', () => { + const message1 = buildCommitMessage(); + expect(parseCommitMessage(message1).isSquash).toBe(false); + + const message2 = buildCommitMessage({prefix: 'squash! '}); + expect(parseCommitMessage(message2).isSquash).toBe(true); + }); + + it('ignores comment lines', () => { + const message = buildCommitMessage({ + prefix: '# This is a comment line before the header.\n' + + '## This is another comment line before the headers.\n', + body: '# This is a comment line befor the body.\n' + + 'This is line 1 of the actual body.\n' + + '## This is another comment line inside the body.\n' + + 'This is line 2 of the actual body (and it also contains a # but it not a comment).\n' + + '### This is yet another comment line after the body.\n', + }); + const parsedMessage = parseCommitMessage(message); + + expect(parsedMessage.header) + .toBe(`${commitValues.type}(${commitValues.scope}): ${commitValues.summary}`); + expect(parsedMessage.body) + .toBe( + 'This is line 1 of the actual body.\n' + + 'This is line 2 of the actual body (and it also contains a # but it not a comment).\n'); + }); +}); diff --git a/dev-infra/commit-message/parse.ts b/dev-infra/commit-message/parse.ts new file mode 100644 index 0000000000000..3ccd870620de7 --- /dev/null +++ b/dev-infra/commit-message/parse.ts @@ -0,0 +1,77 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +/** A parsed commit message. */ +export interface ParsedCommitMessage { + header: string; + body: string; + bodyWithoutLinking: string; + type: string; + scope: string; + subject: string; + isFixup: boolean; + isSquash: boolean; + isRevert: boolean; +} + +/** Regex determining if a commit is a fixup. */ +const FIXUP_PREFIX_RE = /^fixup! /i; +/** Regex finding all github keyword links. */ +const GITHUB_LINKING_RE = /((closed?s?)|(fix(es)?(ed)?)|(resolved?s?))\s\#(\d+)/ig; +/** Regex determining if a commit is a squash. */ +const SQUASH_PREFIX_RE = /^squash! /i; +/** Regex determining if a commit is a revert. */ +const REVERT_PREFIX_RE = /^revert:? /i; +/** Regex determining the scope of a commit if provided. */ +const TYPE_SCOPE_RE = /^(\w+)(?:\(([^)]+)\))?\:\s(.+)$/; +/** Regex determining the entire header line of the commit. */ +const COMMIT_HEADER_RE = /^(.*)/i; +/** Regex determining the body of the commit. */ +const COMMIT_BODY_RE = /^.*\n\n([\s\S]*)$/; + +/** Parse a full commit message into its composite parts. */ +export function parseCommitMessage(commitMsg: string): ParsedCommitMessage { + // Ignore comments (i.e. lines starting with `#`). Comments are automatically removed by git and + // should not be considered part of the final commit message. + commitMsg = commitMsg.split('\n').filter(line => !line.startsWith('#')).join('\n'); + + let header = ''; + let body = ''; + let bodyWithoutLinking = ''; + let type = ''; + let scope = ''; + let subject = ''; + + if (COMMIT_HEADER_RE.test(commitMsg)) { + header = COMMIT_HEADER_RE.exec(commitMsg)![1] + .replace(FIXUP_PREFIX_RE, '') + .replace(SQUASH_PREFIX_RE, ''); + } + if (COMMIT_BODY_RE.test(commitMsg)) { + body = COMMIT_BODY_RE.exec(commitMsg)![1]; + bodyWithoutLinking = body.replace(GITHUB_LINKING_RE, ''); + } + + if (TYPE_SCOPE_RE.test(header)) { + const parsedCommitHeader = TYPE_SCOPE_RE.exec(header)!; + type = parsedCommitHeader[1]; + scope = parsedCommitHeader[2]; + subject = parsedCommitHeader[3]; + } + return { + header, + body, + bodyWithoutLinking, + type, + scope, + subject, + isFixup: FIXUP_PREFIX_RE.test(commitMsg), + isSquash: SQUASH_PREFIX_RE.test(commitMsg), + isRevert: REVERT_PREFIX_RE.test(commitMsg), + }; +} diff --git a/dev-infra/commit-message/restore-commit-message/cli.ts b/dev-infra/commit-message/restore-commit-message/cli.ts new file mode 100644 index 0000000000000..828ca1adf90b5 --- /dev/null +++ b/dev-infra/commit-message/restore-commit-message/cli.ts @@ -0,0 +1,51 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {Arguments, Argv, CommandModule} from 'yargs'; + +import {CommitMsgSource} from '../commit-message-source'; + +import {restoreCommitMessage} from './restore-commit-message'; + +export interface RestoreCommitMessageOptions { + fileEnvVariable: string[]; +} + +/** Builds the command. */ +function builder(yargs: Argv) { + return yargs.option('file-env-variable' as 'fileEnvVariable', { + type: 'string', + array: true, + demandOption: true, + description: 'The key for the environment variable which holds the arguments for the\n' + + 'prepare-commit-msg hook as described here:\n' + + 'https://git-scm.com/docs/githooks#_prepare_commit_msg', + coerce: arg => { + const [file, source] = (process.env[arg] || '').split(' '); + if (!file) { + throw new Error(`Provided environment variable "${arg}" was not found.`); + } + return [file, source]; + }, + }); +} + +/** Handles the command. */ +async function handler({fileEnvVariable}: Arguments) { + restoreCommitMessage(fileEnvVariable[0], fileEnvVariable[1] as CommitMsgSource); +} + +/** yargs command module describing the command. */ +export const RestoreCommitMessageModule: CommandModule<{}, RestoreCommitMessageOptions> = { + handler, + builder, + command: 'restore-commit-message-draft', + // Description: Restore a commit message draft if one has been saved from a failed commit attempt. + // No describe is defiend to hide the command from the --help. + describe: false, +}; diff --git a/dev-infra/commit-message/restore-commit-message/restore-commit-message.ts b/dev-infra/commit-message/restore-commit-message/restore-commit-message.ts new file mode 100644 index 0000000000000..8008728d0bca2 --- /dev/null +++ b/dev-infra/commit-message/restore-commit-message/restore-commit-message.ts @@ -0,0 +1,49 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {writeFileSync} from 'fs'; + +import {debug, log} from '../../utils/console'; + +import {loadCommitMessageDraft} from '../commit-message-draft'; +import {CommitMsgSource} from '../commit-message-source'; + +/** + * Restore the commit message draft to the git to be used as the default commit message. + * + * The source provided may be one of the sources described in + * https://git-scm.com/docs/githooks#_prepare_commit_msg + */ +export function restoreCommitMessage(filePath: string, source?: CommitMsgSource) { + if (!!source) { + log('Skipping commit message restoration attempt'); + if (source === 'message') { + debug('A commit message was already provided via the command with a -m or -F flag'); + } + if (source === 'template') { + debug('A commit message was already provided via the -t flag or config.template setting'); + } + if (source === 'squash') { + debug('A commit message was already provided as a merge action or via .git/MERGE_MSG'); + } + if (source === 'commit') { + debug('A commit message was already provided through a revision specified via --fixup, -c,'); + debug('-C or --amend flag'); + } + process.exit(0); + } + /** A draft of a commit message. */ + const commitMessage = loadCommitMessageDraft(filePath); + + // If the commit message draft has content, restore it into the provided filepath. + if (commitMessage) { + writeFileSync(filePath, commitMessage); + } + // Exit the process + process.exit(0); +} diff --git a/dev-infra/commit-message/validate-file.ts b/dev-infra/commit-message/validate-file.ts deleted file mode 100644 index f4cd5ed8309be..0000000000000 --- a/dev-infra/commit-message/validate-file.ts +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ -import {readFileSync} from 'fs'; -import {resolve} from 'path'; - -import {getRepoBaseDir} from '../utils/config'; -import {info} from '../utils/console'; - -import {validateCommitMessage} from './validate'; - -/** Validate commit message at the provided file path. */ -export function validateFile(filePath: string) { - const commitMessage = readFileSync(resolve(getRepoBaseDir(), filePath), 'utf8'); - if (validateCommitMessage(commitMessage)) { - info('√ Valid commit message'); - return; - } - // If the validation did not return true, exit as a failure. - process.exit(1); -} diff --git a/dev-infra/commit-message/validate-file/cli.ts b/dev-infra/commit-message/validate-file/cli.ts new file mode 100644 index 0000000000000..602b3145cd5a5 --- /dev/null +++ b/dev-infra/commit-message/validate-file/cli.ts @@ -0,0 +1,62 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {Arguments, Argv, CommandModule} from 'yargs'; + +import {getUserConfig} from '../../utils/config'; + +import {validateFile} from './validate-file'; + + +export interface ValidateFileOptions { + file?: string; + fileEnvVariable?: string; + error: boolean; +} + +/** Builds the command. */ +function builder(yargs: Argv) { + return yargs + .option('file', { + type: 'string', + conflicts: ['file-env-variable'], + description: 'The path of the commit message file.', + }) + .option('file-env-variable' as 'fileEnvVariable', { + type: 'string', + conflicts: ['file'], + description: 'The key of the environment variable for the path of the commit message file.', + coerce: (arg: string) => { + const file = process.env[arg]; + if (!file) { + throw new Error(`Provided environment variable "${arg}" was not found.`); + } + return file; + }, + }) + .option('error', { + type: 'boolean', + description: + 'Whether invalid commit messages should be treated as failures rather than a warning', + default: !!getUserConfig().commitMessage?.errorOnInvalidMessage || !!process.env['CI'] + }); +} + +/** Handles the command. */ +async function handler({error, file, fileEnvVariable}: Arguments) { + const filePath = file || fileEnvVariable || '.git/COMMIT_EDITMSG'; + validateFile(filePath, error); +} + +/** yargs command module describing the command. */ +export const ValidateFileModule: CommandModule<{}, ValidateFileOptions> = { + handler, + builder, + command: 'pre-commit-validate', + describe: 'Validate the most recent commit message', +}; diff --git a/dev-infra/commit-message/validate-file/validate-file.ts b/dev-infra/commit-message/validate-file/validate-file.ts new file mode 100644 index 0000000000000..459fa52fa95f0 --- /dev/null +++ b/dev-infra/commit-message/validate-file/validate-file.ts @@ -0,0 +1,47 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +import {readFileSync} from 'fs'; +import {resolve} from 'path'; + +import {getRepoBaseDir} from '../../utils/config'; +import {error, green, info, log, red, yellow} from '../../utils/console'; + +import {deleteCommitMessageDraft, saveCommitMessageDraft} from '../commit-message-draft'; +import {printValidationErrors, validateCommitMessage} from '../validate'; + +/** Validate commit message at the provided file path. */ +export function validateFile(filePath: string, isErrorMode: boolean) { + const commitMessage = readFileSync(resolve(getRepoBaseDir(), filePath), 'utf8'); + const {valid, errors} = validateCommitMessage(commitMessage); + if (valid) { + info(`${green('√')} Valid commit message`); + deleteCommitMessageDraft(filePath); + process.exitCode = 0; + return; + } + + /** Function used to print to the console log. */ + let printFn = isErrorMode ? error : log; + + printFn(`${isErrorMode ? red('✘') : yellow('!')} Invalid commit message`); + printValidationErrors(errors, printFn); + if (isErrorMode) { + printFn(red('Aborting commit attempt due to invalid commit message.')); + printFn( + red('Commit message aborted as failure rather than warning due to local configuration.')); + } else { + printFn(yellow('Before this commit can be merged into the upstream repository, it must be')); + printFn(yellow('amended to follow commit message guidelines.')); + } + + // On all invalid commit messages, the commit message should be saved as a draft to be + // restored on the next commit attempt. + saveCommitMessageDraft(filePath, commitMessage); + // Set the correct exit code based on if invalid commit message is an error. + process.exitCode = isErrorMode ? 1 : 0; +} diff --git a/dev-infra/commit-message/validate-range/cli.ts b/dev-infra/commit-message/validate-range/cli.ts new file mode 100644 index 0000000000000..6eea3ff95ea02 --- /dev/null +++ b/dev-infra/commit-message/validate-range/cli.ts @@ -0,0 +1,50 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {Arguments, Argv, CommandModule} from 'yargs'; + +import {info} from '../../utils/console'; + +import {validateCommitRange} from './validate-range'; + + +export interface ValidateRangeOptions { + range: string; +} + +/** Builds the command. */ +function builder(yargs: Argv) { + return yargs.option('range', { + description: 'The range of commits to check, e.g. --range abc123..xyz456', + demandOption: ' A range must be provided, e.g. --range abc123..xyz456', + type: 'string', + requiresArg: true, + }); +} + +/** Handles the command. */ +async function handler({range}: Arguments) { + // If on CI, and no pull request number is provided, assume the branch + // being run on is an upstream branch. + if (process.env['CI'] && process.env['CI_PULL_REQUEST'] === 'false') { + info(`Since valid commit messages are enforced by PR linting on CI, we do not`); + info(`need to validate commit messages on CI runs on upstream branches.`); + info(); + info(`Skipping check of provided commit range`); + return; + } + validateCommitRange(range); +} + +/** yargs command module describing the command. */ +export const ValidateRangeModule: CommandModule<{}, ValidateRangeOptions> = { + handler, + builder, + command: 'validate-range', + describe: 'Validate a range of commit messages', +}; diff --git a/dev-infra/commit-message/validate-range.ts b/dev-infra/commit-message/validate-range/validate-range.ts similarity index 63% rename from dev-infra/commit-message/validate-range.ts rename to dev-infra/commit-message/validate-range/validate-range.ts index 485fa06b2f57a..3c3825775f029 100644 --- a/dev-infra/commit-message/validate-range.ts +++ b/dev-infra/commit-message/validate-range/validate-range.ts @@ -5,10 +5,11 @@ * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ -import {info} from '../utils/console'; -import {exec} from '../utils/shelljs'; +import {error, info} from '../../utils/console'; +import {exec} from '../../utils/shelljs'; -import {parseCommitMessage, validateCommitMessage, ValidateCommitMessageOptions} from './validate'; +import {parseCommitMessage} from '../parse'; +import {printValidationErrors, validateCommitMessage, ValidateCommitMessageOptions} from '../validate'; // Whether the provided commit is a fixup commit. const isNonFixup = (m: string) => !parseCommitMessage(m).isFixup; @@ -18,11 +19,20 @@ const extractCommitHeader = (m: string) => parseCommitMessage(m).header; /** Validate all commits in a provided git commit range. */ export function validateCommitRange(range: string) { - // A random value is used as a string to allow for a definite split point in the git log result. + /** + * A random value is used as a string to allow for a definite split point in the git log result. + */ const randomValueSeparator = `${Math.random()}`; - // Custom git log format that provides the commit header and body, separated as expected with - // the custom separator as the trailing value. + /** + * Custom git log format that provides the commit header and body, separated as expected with the + * custom separator as the trailing value. + */ const gitLogFormat = `%s%n%n%b${randomValueSeparator}`; + /** + * A list of tuples containing a commit header string and the list of error messages for the + * commit. + */ + const errors: [commitHeader: string, errors: string[]][] = []; // Retrieve the commits in the provided range. const result = exec(`git log --reverse --format=${gitLogFormat} ${range}`); @@ -44,12 +54,22 @@ export function validateCommitRange(range: string) { undefined : commits.slice(0, i).filter(isNonFixup).map(extractCommitHeader) }; - return validateCommitMessage(m, options); + const {valid, errors: localErrors, commit} = validateCommitMessage(m, options); + if (localErrors.length) { + errors.push([commit.header, localErrors]); + } + return valid; }); if (allCommitsInRangeValid) { info('√ All commit messages in range valid.'); } else { + error('✘ Invalid commit message'); + errors.forEach(([header, validationErrors]) => { + error.group(header); + printValidationErrors(validationErrors); + error.groupEnd(); + }); // Exit with a non-zero exit code if invalid commit messages have // been discovered. process.exit(1); diff --git a/dev-infra/commit-message/validate.spec.ts b/dev-infra/commit-message/validate.spec.ts index edc0bab802d57..24fb996698c26 100644 --- a/dev-infra/commit-message/validate.spec.ts +++ b/dev-infra/commit-message/validate.spec.ts @@ -8,7 +8,7 @@ // Imports import * as validateConfig from './config'; -import {validateCommitMessage} from './validate'; +import {validateCommitMessage, ValidateCommitMessageResult} from './validate'; type CommitMessageConfig = validateConfig.CommitMessageConfig; @@ -18,13 +18,6 @@ const config: {commitMessage: CommitMessageConfig} = { commitMessage: { maxLineLength: 120, minBodyLength: 0, - types: [ - 'feat', - 'fix', - 'refactor', - 'release', - 'style', - ], scopes: [ 'common', 'compiler', @@ -33,48 +26,40 @@ const config: {commitMessage: CommitMessageConfig} = { ] } }; -const TYPES = config.commitMessage.types.join(', '); +const TYPES = Object.keys(validateConfig.COMMIT_TYPES).join(', '); const SCOPES = config.commitMessage.scopes.join(', '); const INVALID = false; const VALID = true; +function expectValidationResult( + validationResult: ValidateCommitMessageResult, valid: boolean, errors: string[] = []) { + expect(validationResult).toEqual(jasmine.objectContaining({valid, errors})); +} + // TODO(josephperrott): Clean up tests to test script rather than for // specific commit messages we want to use. describe('validate-commit-message.js', () => { - let lastError: string = ''; - beforeEach(() => { - lastError = ''; - - spyOn(console, 'error').and.callFake((msg: string) => lastError = msg); - spyOn(validateConfig, 'getCommitMessageConfig').and.returnValue(config); + spyOn(validateConfig, 'getCommitMessageConfig') + .and.returnValue(config as ReturnType); }); describe('validateMessage()', () => { it('should be valid', () => { - expect(validateCommitMessage('feat(packaging): something')).toBe(VALID); - expect(lastError).toBe(''); - - expect(validateCommitMessage('release(packaging): something')).toBe(VALID); - expect(lastError).toBe(''); - - expect(validateCommitMessage('fixup! release(packaging): something')).toBe(VALID); - expect(lastError).toBe(''); - - expect(validateCommitMessage('squash! release(packaging): something')).toBe(VALID); - expect(lastError).toBe(''); - - expect(validateCommitMessage('Revert: "release(packaging): something"')).toBe(VALID); - expect(lastError).toBe(''); + expectValidationResult(validateCommitMessage('feat(packaging): something'), VALID); + expectValidationResult(validateCommitMessage('fix(packaging): something'), VALID); + expectValidationResult(validateCommitMessage('fixup! fix(packaging): something'), VALID); + expectValidationResult(validateCommitMessage('squash! fix(packaging): something'), VALID); + expectValidationResult(validateCommitMessage('Revert: "fix(packaging): something"'), VALID); }); it('should validate max length', () => { const msg = 'fix(compiler): something super mega extra giga tera long, maybe even longer and longer and longer and longer and longer and longer...'; - expect(validateCommitMessage(msg)).toBe(INVALID); - expect(lastError).toContain(`The commit message header is longer than ${ - config.commitMessage.maxLineLength} characters`); + expectValidationResult(validateCommitMessage(msg), INVALID, [ + `The commit message header is longer than ${config.commitMessage.maxLineLength} characters` + ]); }); it('should skip max length limit for URLs', () => { @@ -83,49 +68,56 @@ describe('validate-commit-message.js', () => { 'limit. For more details see the following super long URL:\n\n' + 'https://github.com/angular/components/commit/e2ace018ddfad10608e0e32932c43dcfef4095d7#diff-9879d6db96fd29134fc802214163b95a'; - expect(validateCommitMessage(msg)).toBe(VALID); + expectValidationResult(validateCommitMessage(msg), VALID); }); it('should validate "(): " format', () => { const msg = 'not correct format'; - expect(validateCommitMessage(msg)).toBe(INVALID); - expect(lastError).toContain(`The commit message header does not match the expected format.`); + expectValidationResult( + validateCommitMessage(msg), INVALID, + [`The commit message header does not match the expected format.`]); }); it('should fail when type is invalid', () => { const msg = 'weird(core): something'; - expect(validateCommitMessage(msg)).toBe(INVALID); - expect(lastError).toContain(`'weird' is not an allowed type.\n => TYPES: ${TYPES}`); + expectValidationResult( + validateCommitMessage(msg), INVALID, + [`'weird' is not an allowed type.\n => TYPES: ${TYPES}`]); }); it('should fail when scope is invalid', () => { const errorMessageFor = (scope: string, header: string) => `'${scope}' is not an allowed scope.\n => SCOPES: ${SCOPES}`; - expect(validateCommitMessage('fix(Compiler): something')).toBe(INVALID); - expect(lastError).toContain(errorMessageFor('Compiler', 'fix(Compiler): something')); + expectValidationResult( + validateCommitMessage('fix(Compiler): something'), INVALID, + [errorMessageFor('Compiler', 'fix(Compiler): something')]); - expect(validateCommitMessage('feat(bah): something')).toBe(INVALID); - expect(lastError).toContain(errorMessageFor('bah', 'feat(bah): something')); + expectValidationResult( + validateCommitMessage('feat(bah): something'), INVALID, + [errorMessageFor('bah', 'feat(bah): something')]); - expect(validateCommitMessage('style(webworker): something')).toBe(INVALID); - expect(lastError).toContain(errorMessageFor('webworker', 'style(webworker): something')); + expectValidationResult( + validateCommitMessage('fix(webworker): something'), INVALID, + [errorMessageFor('webworker', 'fix(webworker): something')]); - expect(validateCommitMessage('refactor(security): something')).toBe(INVALID); - expect(lastError).toContain(errorMessageFor('security', 'refactor(security): something')); + expectValidationResult( + validateCommitMessage('refactor(security): something'), INVALID, + [errorMessageFor('security', 'refactor(security): something')]); - expect(validateCommitMessage('refactor(docs): something')).toBe(INVALID); - expect(lastError).toContain(errorMessageFor('docs', 'refactor(docs): something')); + expectValidationResult( + validateCommitMessage('refactor(docs): something'), INVALID, + [errorMessageFor('docs', 'refactor(docs): something')]); - expect(validateCommitMessage('release(angular): something')).toBe(INVALID); - expect(lastError).toContain(errorMessageFor('angular', 'release(angular): something')); + expectValidationResult( + validateCommitMessage('feat(angular): something'), INVALID, + [errorMessageFor('angular', 'feat(angular): something')]); }); it('should allow empty scope', () => { - expect(validateCommitMessage('fix: blablabla')).toBe(VALID); - expect(lastError).toBe(''); + expectValidationResult(validateCommitMessage('build: blablabla'), VALID); }); // We do not want to allow WIP. It is OK to fail the PR build in this case to show that there is @@ -133,30 +125,25 @@ describe('validate-commit-message.js', () => { it('should not allow "WIP: ..." syntax', () => { const msg = 'WIP: fix: something'; - expect(validateCommitMessage(msg)).toBe(INVALID); - expect(lastError).toContain(`'WIP' is not an allowed type.\n => TYPES: ${TYPES}`); + expectValidationResult( + validateCommitMessage(msg), INVALID, + [`'WIP' is not an allowed type.\n => TYPES: ${TYPES}`]); }); describe('(revert)', () => { it('should allow valid "revert: ..." syntaxes', () => { - expect(validateCommitMessage('revert: anything')).toBe(VALID); - expect(lastError).toBe(''); - - expect(validateCommitMessage('Revert: "anything"')).toBe(VALID); - expect(lastError).toBe(''); - - expect(validateCommitMessage('revert anything')).toBe(VALID); - expect(lastError).toBe(''); - - expect(validateCommitMessage('rEvErT anything')).toBe(VALID); - expect(lastError).toBe(''); + expectValidationResult(validateCommitMessage('revert: anything'), VALID); + expectValidationResult(validateCommitMessage('Revert: "anything"'), VALID); + expectValidationResult(validateCommitMessage('revert anything'), VALID); + expectValidationResult(validateCommitMessage('rEvErT anything'), VALID); }); it('should not allow "revert(scope): ..." syntax', () => { const msg = 'revert(compiler): reduce generated code payload size by 65%'; - expect(validateCommitMessage(msg)).toBe(INVALID); - expect(lastError).toContain(`'revert' is not an allowed type.\n => TYPES: ${TYPES}`); + expectValidationResult( + validateCommitMessage(msg), INVALID, + [`'revert' is not an allowed type.\n => TYPES: ${TYPES}`]); }); // https://github.com/angular/angular/issues/23479 @@ -164,28 +151,26 @@ describe('validate-commit-message.js', () => { const msg = 'Revert "fix(compiler): Pretty print object instead of [Object object] (#22689)" (#23442)'; - expect(validateCommitMessage(msg)).toBe(VALID); - expect(lastError).toBe(''); + expectValidationResult(validateCommitMessage(msg), VALID); }); }); describe('(squash)', () => { describe('without `disallowSquash`', () => { it('should return commits as valid', () => { - expect(validateCommitMessage('squash! feat(core): add feature')).toBe(VALID); - expect(validateCommitMessage('squash! fix: a bug')).toBe(VALID); - expect(validateCommitMessage('squash! fix a typo')).toBe(VALID); + expectValidationResult(validateCommitMessage('squash! feat(core): add feature'), VALID); + expectValidationResult(validateCommitMessage('squash! fix: a bug'), VALID); + expectValidationResult(validateCommitMessage('squash! fix a typo'), VALID); }); }); describe('with `disallowSquash`', () => { it('should fail', () => { - expect(validateCommitMessage('fix(core): something', {disallowSquash: true})).toBe(VALID); - expect(validateCommitMessage('squash! fix(core): something', { - disallowSquash: true - })).toBe(INVALID); - expect(lastError).toContain( - 'The commit must be manually squashed into the target commit'); + expectValidationResult( + validateCommitMessage('fix(core): something', {disallowSquash: true}), VALID); + expectValidationResult( + validateCommitMessage('squash! fix(core): something', {disallowSquash: true}), + INVALID, ['The commit must be manually squashed into the target commit']); }); }); }); @@ -193,9 +178,9 @@ describe('validate-commit-message.js', () => { describe('(fixup)', () => { describe('without `nonFixupCommitHeaders`', () => { it('should return commits as valid', () => { - expect(validateCommitMessage('fixup! feat(core): add feature')).toBe(VALID); - expect(validateCommitMessage('fixup! fix: a bug')).toBe(VALID); - expect(validateCommitMessage('fixup! fixup! fix: a bug')).toBe(VALID); + expectValidationResult(validateCommitMessage('fixup! feat(core): add feature'), VALID); + expectValidationResult(validateCommitMessage('fixup! fix: a bug'), VALID); + expectValidationResult(validateCommitMessage('fixup! fixup! fix: a bug'), VALID); }); }); @@ -203,36 +188,39 @@ describe('validate-commit-message.js', () => { it('should check that the fixup commit matches a non-fixup one', () => { const msg = 'fixup! foo'; - expect(validateCommitMessage( - msg, {disallowSquash: false, nonFixupCommitHeaders: ['foo', 'bar', 'baz']})) - .toBe(VALID); - expect(validateCommitMessage( - msg, {disallowSquash: false, nonFixupCommitHeaders: ['bar', 'baz', 'foo']})) - .toBe(VALID); - expect(validateCommitMessage( - msg, {disallowSquash: false, nonFixupCommitHeaders: ['baz', 'foo', 'bar']})) - .toBe(VALID); - - expect(validateCommitMessage( - msg, {disallowSquash: false, nonFixupCommitHeaders: ['qux', 'quux', 'quuux']})) - .toBe(INVALID); - expect(lastError).toContain( - 'Unable to find match for fixup commit among prior commits: \n' + - ' qux\n' + - ' quux\n' + - ' quuux'); + expectValidationResult( + validateCommitMessage( + msg, {disallowSquash: false, nonFixupCommitHeaders: ['foo', 'bar', 'baz']}), + VALID); + expectValidationResult( + validateCommitMessage( + msg, {disallowSquash: false, nonFixupCommitHeaders: ['bar', 'baz', 'foo']}), + VALID); + expectValidationResult( + validateCommitMessage( + msg, {disallowSquash: false, nonFixupCommitHeaders: ['baz', 'foo', 'bar']}), + VALID); + + expectValidationResult( + validateCommitMessage( + msg, {disallowSquash: false, nonFixupCommitHeaders: ['qux', 'quux', 'quuux']}), + INVALID, + ['Unable to find match for fixup commit among prior commits: \n' + + ' qux\n' + + ' quux\n' + + ' quuux']); }); it('should fail if `nonFixupCommitHeaders` is empty', () => { - expect(validateCommitMessage('refactor(core): make reactive', { - disallowSquash: false, - nonFixupCommitHeaders: [] - })).toBe(VALID); - expect(validateCommitMessage( - 'fixup! foo', {disallowSquash: false, nonFixupCommitHeaders: []})) - .toBe(INVALID); - expect(lastError).toContain( - `Unable to find match for fixup commit among prior commits: -`); + expectValidationResult( + validateCommitMessage( + 'refactor(core): make reactive', + {disallowSquash: false, nonFixupCommitHeaders: []}), + VALID); + expectValidationResult( + validateCommitMessage( + 'fixup! foo', {disallowSquash: false, nonFixupCommitHeaders: []}), + INVALID, [`Unable to find match for fixup commit among prior commits: -`]); }); }); }); @@ -243,7 +231,6 @@ describe('validate-commit-message.js', () => { maxLineLength: 120, minBodyLength: 30, minBodyLengthTypeExcludes: ['docs'], - types: ['fix', 'docs'], scopes: ['core'] } }; @@ -253,24 +240,27 @@ describe('validate-commit-message.js', () => { }); it('should fail validation if the body is shorter than `minBodyLength`', () => { - expect(validateCommitMessage( - 'fix(core): something\n\n Explanation of the motivation behind this change')) - .toBe(VALID); - expect(validateCommitMessage('fix(core): something\n\n too short')).toBe(INVALID); - expect(lastError).toContain( - 'The commit message body does not meet the minimum length of 30 characters'); - expect(validateCommitMessage('fix(core): something')).toBe(INVALID); - expect(lastError).toContain( - 'The commit message body does not meet the minimum length of 30 characters'); + expectValidationResult( + validateCommitMessage( + 'fix(core): something\n\n Explanation of the motivation behind this change'), + VALID); + expectValidationResult( + validateCommitMessage('fix(core): something\n\n too short'), INVALID, + ['The commit message body does not meet the minimum length of 30 characters']); + expectValidationResult(validateCommitMessage('fix(core): something'), INVALID, [ + + 'The commit message body does not meet the minimum length of 30 characters' + ]); }); it('should pass validation if the body is shorter than `minBodyLength` but the commit type is in the `minBodyLengthTypeExclusions` list', () => { - expect(validateCommitMessage('docs: just fixing a typo')).toBe(VALID); - expect(validateCommitMessage('docs(core): just fixing a typo')).toBe(VALID); - expect(validateCommitMessage( - 'docs(core): just fixing a typo\n\nThis was just a silly typo.')) - .toBe(VALID); + expectValidationResult(validateCommitMessage('docs: just fixing a typo'), VALID); + expectValidationResult(validateCommitMessage('docs(core): just fixing a typo'), VALID); + expectValidationResult( + validateCommitMessage( + 'docs(core): just fixing a typo\n\nThis was just a silly typo.'), + VALID); }); }); }); diff --git a/dev-infra/commit-message/validate.ts b/dev-infra/commit-message/validate.ts index 7108a63cac221..e66679b2b983e 100644 --- a/dev-infra/commit-message/validate.ts +++ b/dev-infra/commit-message/validate.ts @@ -7,7 +7,8 @@ */ import {error} from '../utils/console'; -import {getCommitMessageConfig} from './config'; +import {COMMIT_TYPES, getCommitMessageConfig, ScopeRequirement} from './config'; +import {parseCommitMessage, ParsedCommitMessage} from './parse'; /** Options for commit message validation. */ export interface ValidateCommitMessageOptions { @@ -15,159 +16,147 @@ export interface ValidateCommitMessageOptions { nonFixupCommitHeaders?: string[]; } -const FIXUP_PREFIX_RE = /^fixup! /i; -const GITHUB_LINKING_RE = /((closed?s?)|(fix(es)?(ed)?)|(resolved?s?))\s\#(\d+)/ig; -const SQUASH_PREFIX_RE = /^squash! /i; -const REVERT_PREFIX_RE = /^revert:? /i; -const TYPE_SCOPE_RE = /^(\w+)(?:\(([^)]+)\))?\:\s(.+)$/; -const COMMIT_HEADER_RE = /^(.*)/i; -const COMMIT_BODY_RE = /^.*\n\n([\s\S]*)$/; -const COMMIT_BODY_URL_LINE_RE = /^https?:\/\/.*$/; - -/** Parse a full commit message into its composite parts. */ -export function parseCommitMessage(commitMsg: string) { - let header = ''; - let body = ''; - let bodyWithoutLinking = ''; - let type = ''; - let scope = ''; - let subject = ''; - - if (COMMIT_HEADER_RE.test(commitMsg)) { - header = COMMIT_HEADER_RE.exec(commitMsg)![1] - .replace(FIXUP_PREFIX_RE, '') - .replace(SQUASH_PREFIX_RE, ''); - } - if (COMMIT_BODY_RE.test(commitMsg)) { - body = COMMIT_BODY_RE.exec(commitMsg)![1]; - bodyWithoutLinking = body.replace(GITHUB_LINKING_RE, ''); - } - - if (TYPE_SCOPE_RE.test(header)) { - const parsedCommitHeader = TYPE_SCOPE_RE.exec(header)!; - type = parsedCommitHeader[1]; - scope = parsedCommitHeader[2]; - subject = parsedCommitHeader[3]; - } - return { - header, - body, - bodyWithoutLinking, - type, - scope, - subject, - isFixup: FIXUP_PREFIX_RE.test(commitMsg), - isSquash: SQUASH_PREFIX_RE.test(commitMsg), - isRevert: REVERT_PREFIX_RE.test(commitMsg), - }; +/** The result of a commit message validation check. */ +export interface ValidateCommitMessageResult { + valid: boolean; + errors: string[]; + commit: ParsedCommitMessage; } +/** Regex matching a URL for an entire commit body line. */ +const COMMIT_BODY_URL_LINE_RE = /^https?:\/\/.*$/; + /** Validate a commit message against using the local repo's config. */ export function validateCommitMessage( - commitMsg: string, options: ValidateCommitMessageOptions = {}) { - function printError(errorMessage: string) { - error( - `INVALID COMMIT MSG: \n` + - `${'─'.repeat(40)}\n` + - `${commitMsg}\n` + - `${'─'.repeat(40)}\n` + - `ERROR: \n` + - ` ${errorMessage}` + - `\n\n` + - `The expected format for a commit is: \n` + - `(): \n\n`); - } - + commitMsg: string, options: ValidateCommitMessageOptions = {}): ValidateCommitMessageResult { const config = getCommitMessageConfig().commitMessage; const commit = parseCommitMessage(commitMsg); + const errors: string[] = []; - //////////////////////////////////// - // Checking revert, squash, fixup // - //////////////////////////////////// + /** Perform the validation checks against the parsed commit. */ + function validateCommitAndCollectErrors() { + // TODO(josephperrott): Remove early return calls when commit message errors are found - // All revert commits are considered valid. - if (commit.isRevert) { - return true; - } + //////////////////////////////////// + // Checking revert, squash, fixup // + //////////////////////////////////// - // All squashes are considered valid, as the commit will be squashed into another in - // the git history anyway, unless the options provided to not allow squash commits. - if (commit.isSquash) { - if (options.disallowSquash) { - printError('The commit must be manually squashed into the target commit'); + // All revert commits are considered valid. + if (commit.isRevert) { + return true; + } + + // All squashes are considered valid, as the commit will be squashed into another in + // the git history anyway, unless the options provided to not allow squash commits. + if (commit.isSquash) { + if (options.disallowSquash) { + errors.push('The commit must be manually squashed into the target commit'); + return false; + } + return true; + } + + // Fixups commits are considered valid, unless nonFixupCommitHeaders are provided to check + // against. If `nonFixupCommitHeaders` is not empty, we check whether there is a corresponding + // non-fixup commit (i.e. a commit whose header is identical to this commit's header after + // stripping the `fixup! ` prefix), otherwise we assume this verification will happen in another + // check. + if (commit.isFixup) { + if (options.nonFixupCommitHeaders && !options.nonFixupCommitHeaders.includes(commit.header)) { + errors.push( + 'Unable to find match for fixup commit among prior commits: ' + + (options.nonFixupCommitHeaders.map(x => `\n ${x}`).join('') || '-')); + return false; + } + + return true; + } + + //////////////////////////// + // Checking commit header // + //////////////////////////// + if (commit.header.length > config.maxLineLength) { + errors.push(`The commit message header is longer than ${config.maxLineLength} characters`); return false; } - return true; - } - // Fixups commits are considered valid, unless nonFixupCommitHeaders are provided to check - // against. If `nonFixupCommitHeaders` is not empty, we check whether there is a corresponding - // non-fixup commit (i.e. a commit whose header is identical to this commit's header after - // stripping the `fixup! ` prefix), otherwise we assume this verification will happen in another - // check. - if (commit.isFixup) { - if (options.nonFixupCommitHeaders && !options.nonFixupCommitHeaders.includes(commit.header)) { - printError( - 'Unable to find match for fixup commit among prior commits: ' + - (options.nonFixupCommitHeaders.map(x => `\n ${x}`).join('') || '-')); + if (!commit.type) { + errors.push(`The commit message header does not match the expected format.`); return false; } - return true; - } + if (COMMIT_TYPES[commit.type] === undefined) { + errors.push(`'${commit.type}' is not an allowed type.\n => TYPES: ${ + Object.keys(COMMIT_TYPES).join(', ')}`); + return false; + } - //////////////////////////// - // Checking commit header // - //////////////////////////// - if (commit.header.length > config.maxLineLength) { - printError(`The commit message header is longer than ${config.maxLineLength} characters`); - return false; - } + /** The scope requirement level for the provided type of the commit message. */ + const scopeRequirementForType = COMMIT_TYPES[commit.type].scope; - if (!commit.type) { - printError(`The commit message header does not match the expected format.`); - return false; - } + if (scopeRequirementForType === ScopeRequirement.Forbidden && commit.scope) { + errors.push(`Scopes are forbidden for commits with type '${commit.type}', but a scope of '${ + commit.scope}' was provided.`); + return false; + } - if (!config.types.includes(commit.type)) { - printError(`'${commit.type}' is not an allowed type.\n => TYPES: ${config.types.join(', ')}`); - return false; - } + if (scopeRequirementForType === ScopeRequirement.Required && !commit.scope) { + errors.push( + `Scopes are required for commits with type '${commit.type}', but no scope was provided.`); + return false; + } - if (commit.scope && !config.scopes.includes(commit.scope)) { - printError( - `'${commit.scope}' is not an allowed scope.\n => SCOPES: ${config.scopes.join(', ')}`); - return false; - } + if (commit.scope && !config.scopes.includes(commit.scope)) { + errors.push( + `'${commit.scope}' is not an allowed scope.\n => SCOPES: ${config.scopes.join(', ')}`); + return false; + } - // Commits with the type of `release` do not require a commit body. - if (commit.type === 'release') { - return true; - } + // Commits with the type of `release` do not require a commit body. + if (commit.type === 'release') { + return true; + } - ////////////////////////// - // Checking commit body // - ////////////////////////// + ////////////////////////// + // Checking commit body // + ////////////////////////// - if (!config.minBodyLengthTypeExcludes?.includes(commit.type) && - commit.bodyWithoutLinking.trim().length < config.minBodyLength) { - printError(`The commit message body does not meet the minimum length of ${ - config.minBodyLength} characters`); - return false; - } + if (!config.minBodyLengthTypeExcludes?.includes(commit.type) && + commit.bodyWithoutLinking.trim().length < config.minBodyLength) { + errors.push(`The commit message body does not meet the minimum length of ${ + config.minBodyLength} characters`); + return false; + } + + const bodyByLine = commit.body.split('\n'); + const lineExceedsMaxLength = bodyByLine.some(line => { + // Check if any line exceeds the max line length limit. The limit is ignored for + // lines that just contain an URL (as these usually cannot be wrapped or shortened). + return line.length > config.maxLineLength && !COMMIT_BODY_URL_LINE_RE.test(line); + }); + + if (lineExceedsMaxLength) { + errors.push( + `The commit message body contains lines greater than ${config.maxLineLength} characters`); + return false; + } - const bodyByLine = commit.body.split('\n'); - const lineExceedsMaxLength = bodyByLine.some(line => { - // Check if any line exceeds the max line length limit. The limit is ignored for - // lines that just contain an URL (as these usually cannot be wrapped or shortened). - return line.length > config.maxLineLength && !COMMIT_BODY_URL_LINE_RE.test(line); - }); - - if (lineExceedsMaxLength) { - printError( - `The commit message body contains lines greater than ${config.maxLineLength} characters`); - return false; + return true; } - return true; + return {valid: validateCommitAndCollectErrors(), errors, commit}; +} + + +/** Print the error messages from the commit message validation to the console. */ +export function printValidationErrors(errors: string[], print = error) { + print.group(`Error${errors.length === 1 ? '' : 's'}:`); + errors.forEach(line => print(line)); + print.groupEnd(); + print(); + print('The expected format for a commit is: '); + print('(): '); + print(); + print(''); + print(); } diff --git a/dev-infra/commit-message/wizard/cli.ts b/dev-infra/commit-message/wizard/cli.ts new file mode 100644 index 0000000000000..b4cc94cfa69f4 --- /dev/null +++ b/dev-infra/commit-message/wizard/cli.ts @@ -0,0 +1,54 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {Arguments, Argv, CommandModule} from 'yargs'; + +import {CommitMsgSource} from '../commit-message-source'; + +import {runWizard} from './wizard'; + + +export interface WizardOptions { + filePath: string; + commitSha: string|undefined; + source: CommitMsgSource|undefined; +} + +/** Builds the command. */ +function builder(yargs: Argv) { + return yargs + .positional('filePath', { + description: 'The file path to write the generated commit message into', + type: 'string', + demandOption: true, + }) + .positional('source', { + choices: ['message', 'template', 'merge', 'squash', 'commit'] as const, + description: 'The source of the commit message as described here: ' + + 'https://git-scm.com/docs/githooks#_prepare_commit_msg' + }) + .positional('commitSha', { + description: 'The commit sha if source is set to `commit`', + type: 'string', + }); +} + +/** Handles the command. */ +async function handler(args: Arguments) { + await runWizard(args); +} + +/** yargs command module describing the command. */ +export const WizardModule: CommandModule<{}, WizardOptions> = { + handler, + builder, + command: 'wizard [source] [commitSha]', + // Description: Run the wizard to build a base commit message before opening to complete. + // No describe is defiend to hide the command from the --help. + describe: false, +}; diff --git a/dev-infra/commit-message/wizard/wizard.ts b/dev-infra/commit-message/wizard/wizard.ts new file mode 100644 index 0000000000000..40623fed10250 --- /dev/null +++ b/dev-infra/commit-message/wizard/wizard.ts @@ -0,0 +1,45 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +import {writeFileSync} from 'fs'; + +import {getUserConfig} from '../../utils/config'; +import {debug, info} from '../../utils/console'; + +import {buildCommitMessage} from '../builder'; +import {CommitMsgSource} from '../commit-message-source'; + + +/** The default commit message used if the wizard does not procude a commit message. */ +const defaultCommitMessage = `(): + +# \n\n`; + +export async function runWizard( + args: {filePath: string, source?: CommitMsgSource, commitSha?: string}) { + if (getUserConfig().commitMessage?.disableWizard) { + debug('Skipping commit message wizard due to enabled `commitMessage.disableWizard` option in'); + debug('user config.'); + process.exitCode = 0; + return; + } + + if (args.source !== undefined) { + info(`Skipping commit message wizard because the commit was created via '${ + args.source}' source`); + process.exitCode = 0; + return; + } + + // Set the default commit message to be updated if the user cancels out of the wizard in progress + writeFileSync(args.filePath, defaultCommitMessage); + + /** The generated commit message. */ + const commitMessage = await buildCommitMessage(); + writeFileSync(args.filePath, commitMessage); +} diff --git a/dev-infra/format/BUILD.bazel b/dev-infra/format/BUILD.bazel index 2b340e6aebcad..255e8d7535e7c 100644 --- a/dev-infra/format/BUILD.bazel +++ b/dev-infra/format/BUILD.bazel @@ -1,4 +1,4 @@ -load("@npm_bazel_typescript//:index.bzl", "ts_library") +load("@npm//@bazel/typescript:index.bzl", "ts_library") ts_library( name = "format", @@ -10,12 +10,10 @@ ts_library( deps = [ "//dev-infra/utils", "@npm//@types/cli-progress", - "@npm//@types/inquirer", "@npm//@types/node", "@npm//@types/shelljs", "@npm//@types/yargs", "@npm//cli-progress", - "@npm//inquirer", "@npm//multimatch", "@npm//shelljs", "@npm//yargs", diff --git a/dev-infra/format/cli.ts b/dev-infra/format/cli.ts index 68ddff86e9ac2..77dc6503699bc 100644 --- a/dev-infra/format/cli.ts +++ b/dev-infra/format/cli.ts @@ -7,7 +7,7 @@ */ import * as yargs from 'yargs'; -import {allChangedFilesSince, allFiles} from '../utils/repo-files'; +import {allChangedFilesSince, allFiles, allStagedFiles} from '../utils/repo-files'; import {checkFiles, formatFiles} from './format'; @@ -22,22 +22,31 @@ export function buildFormatParser(localYargs: yargs.Argv) { description: 'Run the formatter to check formatting rather than updating code format' }) .command( - 'all', 'Run the formatter on all files in the repository', {}, + 'all', 'Run the formatter on all files in the repository', args => args, ({check}) => { const executionCmd = check ? checkFiles : formatFiles; executionCmd(allFiles()); }) .command( - 'changed [shaOrRef]', 'Run the formatter on files changed since the provided sha/ref', {}, + 'changed [shaOrRef]', 'Run the formatter on files changed since the provided sha/ref', + args => args.positional('shaOrRef', {type: 'string'}), ({shaOrRef, check}) => { const sha = shaOrRef || 'master'; const executionCmd = check ? checkFiles : formatFiles; executionCmd(allChangedFilesSince(sha)); }) - .command('files ', 'Run the formatter on provided files', {}, ({check, files}) => { - const executionCmd = check ? checkFiles : formatFiles; - executionCmd(files); - }); + .command( + 'staged', 'Run the formatter on all staged files', args => args, + ({check}) => { + const executionCmd = check ? checkFiles : formatFiles; + executionCmd(allStagedFiles()); + }) + .command( + 'files ', 'Run the formatter on provided files', + args => args.positional('files', {array: true, type: 'string'}), ({check, files}) => { + const executionCmd = check ? checkFiles : formatFiles; + executionCmd(files!); + }); } if (require.main === module) { diff --git a/dev-infra/format/format.ts b/dev-infra/format/format.ts index b7c55fbf9c8d9..e3e79f6a4076d 100644 --- a/dev-infra/format/format.ts +++ b/dev-infra/format/format.ts @@ -6,9 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {prompt} from 'inquirer'; - -import {error, info} from '../utils/console'; +import {error, info, promptConfirm} from '../utils/console'; import {runFormatterInParallel} from './run-commands-parallel'; @@ -57,11 +55,7 @@ export async function checkFiles(files: string[]) { // If the command is run in a non-CI environment, prompt to format the files immediately. let runFormatter = false; if (!process.env['CI']) { - runFormatter = (await prompt({ - type: 'confirm', - name: 'runFormatter', - message: 'Format the files now?', - })).runFormatter; + runFormatter = await promptConfirm('Format the files now?', true); } if (runFormatter) { diff --git a/dev-infra/ngbot/BUILD.bazel b/dev-infra/ngbot/BUILD.bazel new file mode 100644 index 0000000000000..08e72e9962d71 --- /dev/null +++ b/dev-infra/ngbot/BUILD.bazel @@ -0,0 +1,19 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_library") + +ts_library( + name = "ngbot", + srcs = [ + "cli.ts", + "verify.ts", + ], + module_name = "@angular/dev-infra-private/ngbot", + visibility = ["//dev-infra:__subpackages__"], + deps = [ + "//dev-infra/utils", + "@npm//@types/node", + "@npm//@types/yaml", + "@npm//@types/yargs", + "@npm//yaml", + "@npm//yargs", + ], +) diff --git a/dev-infra/ngbot/cli.ts b/dev-infra/ngbot/cli.ts new file mode 100644 index 0000000000000..9a881ee92eb73 --- /dev/null +++ b/dev-infra/ngbot/cli.ts @@ -0,0 +1,19 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +import * as yargs from 'yargs'; +import {verify} from './verify'; + +/** Build the parser for the NgBot commands. */ +export function buildNgbotParser(localYargs: yargs.Argv) { + return localYargs.help().strict().demandCommand().command( + 'verify', 'Verify the NgBot config', {}, () => verify()); +} + +if (require.main === module) { + buildNgbotParser(yargs).parse(); +} diff --git a/dev-infra/ngbot/verify.ts b/dev-infra/ngbot/verify.ts new file mode 100644 index 0000000000000..a5c244937611e --- /dev/null +++ b/dev-infra/ngbot/verify.ts @@ -0,0 +1,31 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +import {readFileSync} from 'fs'; +import {resolve} from 'path'; +import {parse as parseYaml} from 'yaml'; + +import {getRepoBaseDir} from '../utils/config'; +import {error, green, info, red} from '../utils/console'; + +export function verify() { + /** Full path to NgBot config file */ + const NGBOT_CONFIG_YAML_PATH = resolve(getRepoBaseDir(), '.github/angular-robot.yml'); + + /** The NgBot config file */ + const ngBotYaml = readFileSync(NGBOT_CONFIG_YAML_PATH, 'utf8'); + + try { + // Try parsing the config file to verify that the syntax is correct. + parseYaml(ngBotYaml); + info(`${green('√')} Valid NgBot YAML config`); + } catch (e) { + error(`${red('!')} Invalid NgBot YAML config`); + error(e); + process.exitCode = 1; + } +} diff --git a/dev-infra/pr/BUILD.bazel b/dev-infra/pr/BUILD.bazel index 023bbd69ac062..cf51a59dc973f 100644 --- a/dev-infra/pr/BUILD.bazel +++ b/dev-infra/pr/BUILD.bazel @@ -1,4 +1,4 @@ -load("@npm_bazel_typescript//:index.bzl", "ts_library") +load("@npm//@bazel/typescript:index.bzl", "ts_library") ts_library( name = "pr", @@ -6,6 +6,7 @@ ts_library( module_name = "@angular/dev-infra-private/pr", visibility = ["//dev-infra:__subpackages__"], deps = [ + "//dev-infra/pr/checkout", "//dev-infra/pr/discover-new-conflicts", "//dev-infra/pr/merge", "//dev-infra/pr/rebase", diff --git a/dev-infra/pr/checkout/BUILD.bazel b/dev-infra/pr/checkout/BUILD.bazel new file mode 100644 index 0000000000000..e7a729c10f091 --- /dev/null +++ b/dev-infra/pr/checkout/BUILD.bazel @@ -0,0 +1,13 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_library") + +ts_library( + name = "checkout", + srcs = glob(["*.ts"]), + module_name = "@angular/dev-infra-private/pr/checkout", + visibility = ["//dev-infra:__subpackages__"], + deps = [ + "//dev-infra/pr/common", + "//dev-infra/utils", + "@npm//@types/yargs", + ], +) diff --git a/dev-infra/pr/checkout/cli.ts b/dev-infra/pr/checkout/cli.ts new file mode 100644 index 0000000000000..1ea44bd937fef --- /dev/null +++ b/dev-infra/pr/checkout/cli.ts @@ -0,0 +1,36 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {Arguments, Argv, CommandModule} from 'yargs'; + +import {addGithubTokenOption} from '../../utils/git/github-yargs'; +import {checkOutPullRequestLocally} from '../common/checkout-pr'; + +export interface CheckoutOptions { + prNumber: number; + githubToken: string; +} + +/** Builds the checkout pull request command. */ +function builder(yargs: Argv) { + return addGithubTokenOption(yargs).positional('prNumber', {type: 'number', demandOption: true}); +} + +/** Handles the checkout pull request command. */ +async function handler({prNumber, githubToken}: Arguments) { + const prCheckoutOptions = {allowIfMaintainerCannotModify: true, branchName: `pr-${prNumber}`}; + await checkOutPullRequestLocally(prNumber, githubToken, prCheckoutOptions); +} + +/** yargs command module for checking out a PR */ +export const CheckoutCommandModule: CommandModule<{}, CheckoutOptions> = { + handler, + builder, + command: 'checkout ', + describe: 'Checkout a PR from the upstream repo', +}; diff --git a/dev-infra/pr/cli.ts b/dev-infra/pr/cli.ts index 0f4d312d444b4..fb080ed5c299b 100644 --- a/dev-infra/pr/cli.ts +++ b/dev-infra/pr/cli.ts @@ -8,6 +8,7 @@ import * as yargs from 'yargs'; +import {CheckoutCommandModule} from './checkout/cli'; import {buildDiscoverNewConflictsCommand, handleDiscoverNewConflictsCommand} from './discover-new-conflicts/cli'; import {buildMergeCommand, handleMergeCommand} from './merge/cli'; import {buildRebaseCommand, handleRebaseCommand} from './rebase/cli'; @@ -24,7 +25,8 @@ export function buildPrParser(localYargs: yargs.Argv) { buildDiscoverNewConflictsCommand, handleDiscoverNewConflictsCommand) .command( 'rebase ', 'Rebase a pending PR and push the rebased commits back to Github', - buildRebaseCommand, handleRebaseCommand); + buildRebaseCommand, handleRebaseCommand) + .command(CheckoutCommandModule); } if (require.main === module) { diff --git a/dev-infra/pr/common/BUILD.bazel b/dev-infra/pr/common/BUILD.bazel new file mode 100644 index 0000000000000..496961b80507a --- /dev/null +++ b/dev-infra/pr/common/BUILD.bazel @@ -0,0 +1,13 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_library") + +ts_library( + name = "common", + srcs = glob(["*.ts"]), + module_name = "@angular/dev-infra-private/pr/common", + visibility = ["//dev-infra:__subpackages__"], + deps = [ + "//dev-infra/utils", + "@npm//@types/node", + "@npm//typed-graphqlify", + ], +) diff --git a/dev-infra/pr/common/checkout-pr.ts b/dev-infra/pr/common/checkout-pr.ts new file mode 100644 index 0000000000000..dcb7be2e68734 --- /dev/null +++ b/dev-infra/pr/common/checkout-pr.ts @@ -0,0 +1,128 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {types as graphQLTypes} from 'typed-graphqlify'; + +import {info} from '../../utils/console'; +import {GitClient} from '../../utils/git'; +import {addTokenToGitHttpsUrl} from '../../utils/git/github-urls'; +import {getPr} from '../../utils/github'; + +/* GraphQL schema for the response body for a pending PR. */ +const PR_SCHEMA = { + state: graphQLTypes.string, + maintainerCanModify: graphQLTypes.boolean, + viewerDidAuthor: graphQLTypes.boolean, + headRefOid: graphQLTypes.string, + headRef: { + name: graphQLTypes.string, + repository: { + url: graphQLTypes.string, + nameWithOwner: graphQLTypes.string, + }, + }, + baseRef: { + name: graphQLTypes.string, + repository: { + url: graphQLTypes.string, + nameWithOwner: graphQLTypes.string, + }, + }, +}; + + +export class UnexpectedLocalChangesError extends Error { + constructor(m: string) { + super(m); + Object.setPrototypeOf(this, UnexpectedLocalChangesError.prototype); + } +} + +export class MaintainerModifyAccessError extends Error { + constructor(m: string) { + super(m); + Object.setPrototypeOf(this, MaintainerModifyAccessError.prototype); + } +} + +/** Options for checking out a PR */ +export interface PullRequestCheckoutOptions { + /** Whether the PR should be checked out if the maintainer cannot modify. */ + allowIfMaintainerCannotModify?: boolean; +} + +/** + * Rebase the provided PR onto its merge target branch, and push up the resulting + * commit to the PRs repository. + */ +export async function checkOutPullRequestLocally( + prNumber: number, githubToken: string, opts: PullRequestCheckoutOptions = {}) { + /** Authenticated Git client for git and Github interactions. */ + const git = new GitClient(githubToken); + + // In order to preserve local changes, checkouts cannot occur if local changes are present in the + // git environment. Checked before retrieving the PR to fail fast. + if (git.hasLocalChanges()) { + throw new UnexpectedLocalChangesError('Unable to checkout PR due to uncommitted changes.'); + } + + /** + * The branch or revision originally checked out before this method performed + * any Git operations that may change the working branch. + */ + const previousBranchOrRevision = git.getCurrentBranchOrRevision(); + /* The PR information from Github. */ + const pr = await getPr(PR_SCHEMA, prNumber, git); + /** The branch name of the PR from the repository the PR came from. */ + const headRefName = pr.headRef.name; + /** The full ref for the repository and branch the PR came from. */ + const fullHeadRef = `${pr.headRef.repository.nameWithOwner}:${headRefName}`; + /** The full URL path of the repository the PR came from with github token as authentication. */ + const headRefUrl = addTokenToGitHttpsUrl(pr.headRef.repository.url, githubToken); + // Note: Since we use a detached head for rebasing the PR and therefore do not have + // remote-tracking branches configured, we need to set our expected ref and SHA. This + // allows us to use `--force-with-lease` for the detached head while ensuring that we + // never accidentally override upstream changes that have been pushed in the meanwhile. + // See: + // https://git-scm.com/docs/git-push#Documentation/git-push.txt---force-with-leaseltrefnamegtltexpectgt + /** Flag for a force push with leage back to upstream. */ + const forceWithLeaseFlag = `--force-with-lease=${headRefName}:${pr.headRefOid}`; + + // If the PR does not allow maintainers to modify it, exit as the rebased PR cannot + // be pushed up. + if (!pr.maintainerCanModify && !pr.viewerDidAuthor && !opts.allowIfMaintainerCannotModify) { + throw new MaintainerModifyAccessError('PR is not set to allow maintainers to modify the PR'); + } + + try { + // Fetch the branch at the commit of the PR, and check it out in a detached state. + info(`Checking out PR #${prNumber} from ${fullHeadRef}`); + git.run(['fetch', headRefUrl, headRefName]); + git.run(['checkout', '--detach', 'FETCH_HEAD']); + } catch (e) { + git.checkout(previousBranchOrRevision, true); + throw e; + } + + return { + /** + * Pushes the current local branch to the PR on the upstream repository. + * + * @returns true If the command did not fail causing a GitCommandError to be thrown. + * @throws GitCommandError Thrown when the push back to upstream fails. + */ + pushToUpstream: (): true => { + git.run(['push', headRefUrl, `HEAD:${headRefName}`, forceWithLeaseFlag]); + return true; + }, + /** Restores the state of the local repository to before the PR checkout occured. */ + resetGitState: (): boolean => { + return git.checkout(previousBranchOrRevision, true); + } + }; +} diff --git a/dev-infra/pr/discover-new-conflicts/BUILD.bazel b/dev-infra/pr/discover-new-conflicts/BUILD.bazel index a0dbdca87a1ca..c625ad7aede59 100644 --- a/dev-infra/pr/discover-new-conflicts/BUILD.bazel +++ b/dev-infra/pr/discover-new-conflicts/BUILD.bazel @@ -1,4 +1,4 @@ -load("@npm_bazel_typescript//:index.bzl", "ts_library") +load("@npm//@bazel/typescript:index.bzl", "ts_library") ts_library( name = "discover-new-conflicts", diff --git a/dev-infra/pr/discover-new-conflicts/cli.ts b/dev-infra/pr/discover-new-conflicts/cli.ts index 672afb3c1432c..27f83b69e9289 100644 --- a/dev-infra/pr/discover-new-conflicts/cli.ts +++ b/dev-infra/pr/discover-new-conflicts/cli.ts @@ -12,18 +12,28 @@ import {error} from '../../utils/console'; import {discoverNewConflictsForPr} from './index'; +/** The options available to the discover-new-conflicts command via CLI. */ +export interface DiscoverNewConflictsCommandOptions { + date: number; + 'pr-number': number; +} + /** Builds the discover-new-conflicts pull request command. */ -export function buildDiscoverNewConflictsCommand(yargs: Argv) { - return yargs.option('date', { - description: 'Only consider PRs updated since provided date', - defaultDescription: '30 days ago', - coerce: Date.parse, - default: getThirtyDaysAgoDate, - }); +export function buildDiscoverNewConflictsCommand(yargs: Argv): + Argv { + return yargs + .option('date', { + description: 'Only consider PRs updated since provided date', + defaultDescription: '30 days ago', + coerce: (date) => typeof date === 'number' ? date : Date.parse(date), + default: getThirtyDaysAgoDate(), + }) + .positional('pr-number', {demandOption: true, type: 'number'}); } /** Handles the discover-new-conflicts pull request command. */ -export async function handleDiscoverNewConflictsCommand({prNumber, date}: Arguments) { +export async function handleDiscoverNewConflictsCommand( + {'pr-number': prNumber, date}: Arguments) { // If a provided date is not able to be parsed, yargs provides it as NaN. if (isNaN(date)) { error('Unable to parse the value provided via --date flag'); @@ -33,11 +43,11 @@ export async function handleDiscoverNewConflictsCommand({prNumber, date}: Argume } /** Gets a date object 30 days ago from today. */ -function getThirtyDaysAgoDate(): Date { +function getThirtyDaysAgoDate() { const date = new Date(); // Set the hours, minutes and seconds to 0 to only consider date. date.setHours(0, 0, 0, 0); // Set the date to 30 days in the past. date.setDate(date.getDate() - 30); - return date; + return date.getTime(); } diff --git a/dev-infra/pr/discover-new-conflicts/index.ts b/dev-infra/pr/discover-new-conflicts/index.ts index 790d809438437..c59f1a0698231 100644 --- a/dev-infra/pr/discover-new-conflicts/index.ts +++ b/dev-infra/pr/discover-new-conflicts/index.ts @@ -72,7 +72,7 @@ export async function discoverNewConflictsForPr( info(`Requesting pending PRs from Github`); /** List of PRs from github currently known as mergable. */ - const allPendingPRs = (await getPendingPrs(PR_SCHEMA, config.github)).map(processPr); + const allPendingPRs = (await getPendingPrs(PR_SCHEMA, git)).map(processPr); /** The PR which is being checked against. */ const requestedPr = allPendingPRs.find(pr => pr.number === newPrNumber); if (requestedPr === undefined) { diff --git a/dev-infra/pr/merge/BUILD.bazel b/dev-infra/pr/merge/BUILD.bazel index ccfb9cb507e68..52865f0a238ff 100644 --- a/dev-infra/pr/merge/BUILD.bazel +++ b/dev-infra/pr/merge/BUILD.bazel @@ -1,4 +1,4 @@ -load("@npm_bazel_typescript//:index.bzl", "ts_library") +load("@npm//@bazel/typescript:index.bzl", "ts_library") load("//tools:defaults.bzl", "jasmine_node_test") ts_library( @@ -11,6 +11,8 @@ ts_library( visibility = ["//dev-infra:__subpackages__"], deps = [ "//dev-infra/commit-message", + "//dev-infra/release/config", + "//dev-infra/release/versioning", "//dev-infra/utils", "@npm//@octokit/rest", "@npm//@types/inquirer", @@ -28,6 +30,8 @@ ts_library( srcs = glob(["**/*.spec.ts"]), deps = [ ":merge", + "//dev-infra/release/config", + "//dev-infra/release/versioning", "//dev-infra/utils", "@npm//@types/jasmine", "@npm//@types/node", diff --git a/dev-infra/pr/merge/cli.ts b/dev-infra/pr/merge/cli.ts index b1d30223d62df..0c2600351ae69 100644 --- a/dev-infra/pr/merge/cli.ts +++ b/dev-infra/pr/merge/cli.ts @@ -8,27 +8,24 @@ import {Arguments, Argv} from 'yargs'; -import {error, red, yellow} from '../../utils/console'; +import {addGithubTokenOption} from '../../utils/git/github-yargs'; -import {GITHUB_TOKEN_GENERATE_URL, mergePullRequest} from './index'; +import {mergePullRequest} from './index'; + +/** The options available to the merge command via CLI. */ +export interface MergeCommandOptions { + githubToken: string; + 'pr-number': number; +} /** Builds the options for the merge command. */ -export function buildMergeCommand(yargs: Argv) { - return yargs.help().strict().option('github-token', { - type: 'string', - description: 'Github token. If not set, token is retrieved from the environment variables.' - }); +export function buildMergeCommand(yargs: Argv): Argv { + return addGithubTokenOption(yargs).help().strict().positional( + 'pr-number', {demandOption: true, type: 'number'}); } /** Handles the merge command. i.e. performs the merge of a specified pull request. */ -export async function handleMergeCommand(args: Arguments) { - const githubToken = args.githubToken || process.env.GITHUB_TOKEN || process.env.TOKEN; - if (!githubToken) { - error(red('No Github token set. Please set the `GITHUB_TOKEN` environment variable.')); - error(red('Alternatively, pass the `--github-token` command line flag.')); - error(yellow(`You can generate a token here: ${GITHUB_TOKEN_GENERATE_URL}`)); - process.exit(1); - } - - await mergePullRequest(args.prNumber, githubToken); +export async function handleMergeCommand( + {'pr-number': pr, githubToken}: Arguments) { + await mergePullRequest(pr, githubToken); } diff --git a/dev-infra/pr/merge/defaults/branches.ts b/dev-infra/pr/merge/defaults/branches.ts deleted file mode 100644 index 0f40a2d0a2b8c..0000000000000 --- a/dev-infra/pr/merge/defaults/branches.ts +++ /dev/null @@ -1,212 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import * as semver from 'semver'; -import {GithubClient} from '../../../utils/git/github'; - -/** Type describing a Github repository with corresponding API client. */ -export interface GithubRepo { - /** API client that can access the repository. */ - api: GithubClient; - /** Owner login of the repository. */ - owner: string; - /** Name of the repository. */ - repo: string; - /** - * NPM package representing this repository. Angular repositories usually contain - * multiple packages in a monorepo scheme, but packages commonly are released with - * the same versions. This means that a single package can be used for querying - * NPM about previously published versions (e.g. to determine active LTS versions). - * */ - npmPackageName: string; -} - -/** Type describing a version-branch. */ -export interface VersionBranch { - /** Name of the branch in Git. e.g. `10.0.x`. */ - name: string; - /** - * Parsed SemVer version for the version-branch. Version branches technically do - * not follow the SemVer format, but we can have representative SemVer versions - * that can be used for comparisons, sorting and other checks. - */ - parsed: semver.SemVer; -} - -/** Branch name for the `next` branch. */ -export const nextBranchName = 'master'; - -/** Regular expression that matches version-branches for a release-train. */ -const releaseTrainBranchNameRegex = /(\d+)\.(\d+)\.x/; - -/** - * Fetches the active release train and its branches for the specified major version. i.e. - * the latest active release-train branch name is resolved and an optional version-branch for - * a currently active feature-freeze/release-candidate release-train. - */ -export async function fetchActiveReleaseTrainBranches( - repo: GithubRepo, nextVersion: semver.SemVer): Promise<{ - /** - * Name of the currently active release-candidate branch. Null if no - * feature-freeze/release-candidate is currently active. - */ - releaseCandidateBranch: string | null, - /** Name of the latest non-prerelease version branch (i.e. the patch branch). */ - latestVersionBranch: string -}> { - const majorVersionsToConsider: number[] = []; - let expectedReleaseCandidateMajor: number; - - // If the `next` branch (i.e. `master` branch) is for an upcoming major version, we know - // that there is no patch branch or feature-freeze/release-candidate branch for this major - // digit. If the current `next` version is the first minor of a major version, we know that - // the feature-freeze/release-candidate branch can only be the actual major branch. The - // patch branch is based on that, either the actual major branch or the last minor from the - // preceding major version. In all other cases, the patch branch and feature-freeze or - // release-candidate branch are part of the same major version. Consider the following: - // - // CASE 1. next: 11.0.0-next.0: patch and feature-freeze/release-candidate can only be - // most recent `10.<>.x` branches. The FF/RC branch can only be the last-minor of v10. - // CASE 2. next: 11.1.0-next.0: patch can be either `11.0.x` or last-minor in v10 based - // on whether there is a feature-freeze/release-candidate branch (=> `11.0.x`). - // CASE 3. next: 10.6.0-next.0: patch can be either `10.5.x` or `10.4.x` based on whether - // there is a feature-freeze/release-candidate branch (=> `10.5.x`) - if (nextVersion.minor === 0) { - expectedReleaseCandidateMajor = nextVersion.major - 1; - majorVersionsToConsider.push(nextVersion.major - 1); - } else if (nextVersion.minor === 1) { - expectedReleaseCandidateMajor = nextVersion.major; - majorVersionsToConsider.push(nextVersion.major, nextVersion.major - 1); - } else { - expectedReleaseCandidateMajor = nextVersion.major; - majorVersionsToConsider.push(nextVersion.major); - } - - // Collect all version-branches that should be considered for the latest version-branch, - // or the feature-freeze/release-candidate. - const branches = (await getBranchesForMajorVersions(repo, majorVersionsToConsider)); - const {latestVersionBranch, releaseCandidateBranch} = - await findActiveVersionBranches(repo, nextVersion, branches, expectedReleaseCandidateMajor); - - if (latestVersionBranch === null) { - throw Error( - `Unable to determine the latest release-train. The following branches ` + - `have been considered: [${branches.join(', ')}]`); - } - - return {releaseCandidateBranch, latestVersionBranch}; -} - -/** Gets the version of a given branch by reading the `package.json` upstream. */ -export async function getVersionOfBranch( - repo: GithubRepo, branchName: string): Promise { - const {data} = - await repo.api.repos.getContents({...repo, path: '/package.json', ref: branchName}); - const {version} = JSON.parse(Buffer.from(data.content, 'base64').toString()); - const parsedVersion = semver.parse(version); - if (parsedVersion === null) { - throw Error(`Invalid version detected in following branch: ${branchName}.`); - } - return parsedVersion; -} - -/** Whether the given branch corresponds to a release-train branch. */ -export function isReleaseTrainBranch(branchName: string): boolean { - return releaseTrainBranchNameRegex.test(branchName); -} - -/** - * Converts a given version-branch into a SemVer version that can be used with SemVer - * utilities. e.g. to determine semantic order, extract major digit, compare. - * - * For example `10.0.x` will become `10.0.0` in SemVer. The patch digit is not - * relevant but needed for parsing. SemVer does not allow `x` as patch digit. - */ -export function getVersionForReleaseTrainBranch(branchName: string): semver.SemVer|null { - // Convert a given version-branch into a SemVer version that can be used - // with the SemVer utilities. i.e. to determine semantic order. - return semver.parse(branchName.replace(releaseTrainBranchNameRegex, '$1.$2.0')); -} - -/** - * Gets the version branches for the specified major versions in descending - * order. i.e. latest version branches first. - */ -export async function getBranchesForMajorVersions( - repo: GithubRepo, majorVersions: number[]): Promise { - const {data: branchData} = await repo.api.repos.listBranches({...repo, protected: true}); - const branches: VersionBranch[] = []; - - for (const {name} of branchData) { - if (!isReleaseTrainBranch(name)) { - continue; - } - // Convert the version-branch into a SemVer version that can be used with the - // SemVer utilities. e.g. to determine semantic order, compare versions. - const parsed = getVersionForReleaseTrainBranch(name); - // Collect all version-branches that match the specified major versions. - if (parsed !== null && majorVersions.includes(parsed.major)) { - branches.push({name, parsed}); - } - } - - // Sort captured version-branches in descending order. - return branches.sort((a, b) => semver.rcompare(a.parsed, b.parsed)); -} - -export async function findActiveVersionBranches( - repo: GithubRepo, nextVersion: semver.SemVer, branches: VersionBranch[], - expectedReleaseCandidateMajor: number): Promise<{ - latestVersionBranch: string | null, - releaseCandidateBranch: string | null, -}> { - let latestVersionBranch: string|null = null; - let releaseCandidateBranch: string|null = null; - - // Iterate through the captured branches and find the latest non-prerelease branch and a - // potential release candidate branch. From the collected branches we iterate descending - // order (most recent semantic version-branch first). The first branch is either the latest - // active version branch (i.e. patch) or a feature-freeze/release-candidate branch. A FF/RC - // branch cannot be older than the latest active version-branch, so we stop iterating once - // we found such a branch. Otherwise, if we found a FF/RC branch, we continue looking for the - // next version-branch as that one is supposed to be the latest active version-branch. If it - // is not, then an error will be thrown due to two FF/RC branches existing at the same time. - for (const {name, parsed} of branches) { - // It can happen that version branches that are more recent than the version in the next - // branch (i.e. `master`) have been created. We could ignore such branches silently, but - // it might actually be symptomatic for an outdated version in the `next` branch, or an - // accidentally created branch by the caretaker. In either way we want to raise awareness. - if (semver.gte(parsed, nextVersion)) { - throw Error( - `Discovered unexpected version-branch that is representing a minor ` + - `version more recent than the one in the "${nextBranchName}" branch. Consider ` + - `deleting the branch, or check if the version in "${nextBranchName}" is outdated.`); - } - - const version = await getVersionOfBranch(repo, name); - const isPrerelease = version.prerelease[0] === 'rc' || version.prerelease[0] === 'next'; - if (isPrerelease) { - if (releaseCandidateBranch !== null) { - throw Error( - `Unable to determine latest release-train. Found two consecutive ` + - `branches in feature-freeze/release-candidate phase. Did not expect both "${name}" ` + - `and "${releaseCandidateBranch}" to be in feature-freeze/release-candidate mode.`); - } else if (version.major !== expectedReleaseCandidateMajor) { - throw Error( - `Discovered unexpected old feature-freeze/release-candidate branch. Expected no ` + - `version-branch in feature-freeze/release-candidate mode for v${version.major}.`); - } - releaseCandidateBranch = name; - } else { - latestVersionBranch = name; - break; - } - } - - return {releaseCandidateBranch, latestVersionBranch}; -} diff --git a/dev-infra/pr/merge/defaults/index.ts b/dev-infra/pr/merge/defaults/index.ts index b633d828256a0..292bf3fb3ebd7 100644 --- a/dev-infra/pr/merge/defaults/index.ts +++ b/dev-infra/pr/merge/defaults/index.ts @@ -7,5 +7,4 @@ */ export * from './labels'; -export * from './branches'; export * from './lts-branch'; diff --git a/dev-infra/pr/merge/defaults/integration.spec.ts b/dev-infra/pr/merge/defaults/integration.spec.ts index d085422e9012f..6db2cfc12fd3c 100644 --- a/dev-infra/pr/merge/defaults/integration.spec.ts +++ b/dev-infra/pr/merge/defaults/integration.spec.ts @@ -7,8 +7,9 @@ */ import * as nock from 'nock'; -import * as nodeFetch from 'node-fetch'; +import {ReleaseConfig} from '../../../release/config/index'; +import {_npmPackageInfoCache, NpmPackageInfo} from '../../../release/versioning/npm-registry'; import {GithubConfig} from '../../../utils/config'; import * as console from '../../../utils/console'; import {GithubClient} from '../../../utils/git/github'; @@ -21,13 +22,17 @@ const API_ENDPOINT = `https://api.github.com`; describe('default target labels', () => { let api: GithubClient; - let config: GithubConfig; - let npmPackageName: string; + let githubConfig: GithubConfig; + let releaseConfig: ReleaseConfig; beforeEach(() => { api = new GithubClient(); - config = {owner: 'angular', name: 'dev-infra-test'}; - npmPackageName = '@angular/dev-infra-test-pkg'; + githubConfig = {owner: 'angular', name: 'dev-infra-test'}; + releaseConfig = { + npmPackages: ['@angular/dev-infra-test-pkg'], + buildPackages: async () => [], + generateReleaseNotesForHead: async () => {}, + }; // The label determination will print warn messages. These should not be // printed to the console, so we turn `console.warn` into a spy. @@ -37,11 +42,11 @@ describe('default target labels', () => { afterEach(() => nock.cleanAll()); async function computeTargetLabels(): Promise { - return getDefaultTargetLabelConfiguration(api, config, npmPackageName); + return getDefaultTargetLabelConfiguration(api, githubConfig, releaseConfig); } function getRepoApiRequestUrl(): string { - return `${API_ENDPOINT}/repos/${config.owner}/${config.name}`; + return `${API_ENDPOINT}/repos/${githubConfig.owner}/${githubConfig.name}`; } /** @@ -61,10 +66,9 @@ describe('default target labels', () => { } /** Fakes a NPM package query API request. */ - function fakeNpmPackageQueryRequest(data: unknown) { - // Note: We only need to mock the `json` function for a `Response`. Types - // would expect us to mock more functions, so we need to cast to `any`. - spyOn(nodeFetch, 'default').and.resolveTo({json: async () => data} as any); + function fakeNpmPackageQueryRequest(data: Partial) { + _npmPackageInfoCache[releaseConfig.npmPackages[0]] = + Promise.resolve({'dist-tags': {}, versions: {}, time: {}, ...data}); } /** @@ -167,7 +171,7 @@ describe('default target labels', () => { 'time': { // v10 has been released at the given specified date. We pick a date that // guarantees that the version is no longer considered as active LTS version. - '10.0.0': new Date(1912, 5, 23), + '10.0.0': new Date(1912, 5, 23).toISOString(), } }); @@ -234,7 +238,7 @@ describe('default target labels', () => { 'time': { // v10 has been released at the given specified date. We pick a date that // guarantees that the version is no longer considered as active LTS version. - '10.0.0': new Date(1912, 5, 23), + '10.0.0': new Date(1912, 5, 23).toISOString(), } }); @@ -247,16 +251,14 @@ describe('default target labels', () => { interceptBranchVersionRequest('10.5.x', '10.5.1'); interceptBranchesListRequest(['10.5.x', '11.0.x']); - spyOn(require('node-fetch'), 'default').and.callFake(() => ({ - json: () => ({ - 'dist-tags': { - 'v10-lts': '10.5.1', - }, - 'time': { - '10.0.0': new Date().toISOString(), - } - }), - })); + fakeNpmPackageQueryRequest({ + 'dist-tags': { + 'v10-lts': '10.5.1', + }, + 'time': { + '10.0.0': new Date().toISOString(), + } + }); expect(await getBranchesForLabel('target: lts', '10.5.x')).toEqual(['10.5.x']); }); @@ -280,7 +282,21 @@ describe('default target labels', () => { .toBeRejectedWithError('Invalid version detected in following branch: 11.1.x.'); }); - it('should error if branch more recent than version in "next" branch is found', async () => { + it('should error if version-branch more recent than "next" is discovered', async () => { + interceptBranchVersionRequest('master', '11.2.0-next.0'); + interceptBranchVersionRequest('11.3.x', '11.3.0-next.0'); + interceptBranchVersionRequest('11.1.x', '11.1.5'); + interceptBranchesListRequest(['11.1.x', '11.3.x']); + + await expectAsync(getBranchesForLabel('target: lts', '10.2.x')) + .toBeRejectedWithError( + 'Discovered unexpected version-branch "11.3.x" for a release-train that is ' + + 'more recent than the release-train currently in the "master" branch. Please ' + + 'either delete the branch if created by accident, or update the outdated version ' + + 'in the next branch (master).'); + }); + + it('should error if branch is matching with release-train in the "next" branch', async () => { interceptBranchVersionRequest('master', '11.2.0-next.0'); interceptBranchVersionRequest('11.2.x', '11.2.0-next.0'); interceptBranchVersionRequest('11.1.x', '11.1.5'); @@ -288,9 +304,9 @@ describe('default target labels', () => { await expectAsync(getBranchesForLabel('target: lts', '10.2.x')) .toBeRejectedWithError( - 'Discovered unexpected version-branch that is representing a minor version more ' + - 'recent than the one in the "master" branch. Consider deleting the branch, or check ' + - 'if the version in "master" is outdated.'); + 'Discovered unexpected version-branch "11.2.x" for a release-train that is already ' + + 'active in the "master" branch. Please either delete the branch if created by ' + + 'accident, or update the version in the next branch (master).'); }); it('should allow merging PR only into patch branch with "target: patch"', async () => { diff --git a/dev-infra/pr/merge/defaults/labels.ts b/dev-infra/pr/merge/defaults/labels.ts index 1ef039bdb9ee7..57f01c166879b 100644 --- a/dev-infra/pr/merge/defaults/labels.ts +++ b/dev-infra/pr/merge/defaults/labels.ts @@ -6,12 +6,13 @@ * found in the LICENSE file at https://angular.io/license */ +import {ReleaseConfig} from '../../../release/config/index'; +import {fetchActiveReleaseTrains, isVersionBranch, nextBranchName} from '../../../release/versioning'; import {GithubConfig} from '../../../utils/config'; import {GithubClient} from '../../../utils/git/github'; import {TargetLabel} from '../config'; import {InvalidTargetBranchError, InvalidTargetLabelError} from '../target-label'; -import {fetchActiveReleaseTrainBranches, getVersionOfBranch, GithubRepo, isReleaseTrainBranch, nextBranchName} from './branches'; import {assertActiveLtsBranch} from './lts-branch'; /** @@ -19,14 +20,18 @@ import {assertActiveLtsBranch} from './lts-branch'; * organization-wide labeling and branching semantics as outlined in the specification. * * https://docs.google.com/document/d/197kVillDwx-RZtSVOBtPb4BBIAw0E9RT3q3v6DZkykU + * + * @param api Instance of an authenticated Github client. + * @param githubConfig Configuration for the Github remote. Used as Git remote + * for the release train branches. + * @param releaseConfig Configuration for the release packages. Used to fetch + * NPM version data when LTS version branches are validated. */ export async function getDefaultTargetLabelConfiguration( - api: GithubClient, github: GithubConfig, npmPackageName: string): Promise { - const repo: GithubRepo = {owner: github.owner, repo: github.name, api, npmPackageName}; - const nextVersion = await getVersionOfBranch(repo, nextBranchName); - const hasNextMajorTrain = nextVersion.minor === 0; - const {latestVersionBranch, releaseCandidateBranch} = - await fetchActiveReleaseTrainBranches(repo, nextVersion); + api: GithubClient, githubConfig: GithubConfig, + releaseConfig: ReleaseConfig): Promise { + const repo = {owner: githubConfig.owner, name: githubConfig.name, api}; + const {latest, releaseCandidate, next} = await fetchActiveReleaseTrains(repo); return [ { @@ -34,10 +39,10 @@ export async function getDefaultTargetLabelConfiguration( branches: () => { // If `next` is currently not designated to be a major version, we do not // allow merging of PRs with `target: major`. - if (!hasNextMajorTrain) { + if (!next.isMajor) { throw new InvalidTargetLabelError( - `Unable to merge pull request. The "${nextBranchName}" branch will be ` + - `released as a minor version.`); + `Unable to merge pull request. The "${nextBranchName}" branch will be released as ` + + 'a minor version.'); } return [nextBranchName]; }, @@ -59,15 +64,15 @@ export async function getDefaultTargetLabelConfiguration( // and is also labeled with `target: patch`, then we merge it directly into the // branch without doing any cherry-picking. This is useful if a PR could not be // applied cleanly, and a separate PR for the patch branch has been created. - if (githubTargetBranch === latestVersionBranch) { - return [latestVersionBranch]; + if (githubTargetBranch === latest.branchName) { + return [latest.branchName]; } // Otherwise, patch changes are always merged into the next and patch branch. - const branches = [nextBranchName, latestVersionBranch]; + const branches = [nextBranchName, latest.branchName]; // Additionally, if there is a release-candidate/feature-freeze release-train // currently active, also merge the PR into that version-branch. - if (releaseCandidateBranch !== null) { - branches.push(releaseCandidateBranch); + if (releaseCandidate !== null) { + branches.push(releaseCandidate.branchName); } return branches; } @@ -77,7 +82,7 @@ export async function getDefaultTargetLabelConfiguration( branches: githubTargetBranch => { // The `target: rc` label cannot be applied if there is no active feature-freeze // or release-candidate release train. - if (releaseCandidateBranch === null) { + if (releaseCandidate === null) { throw new InvalidTargetLabelError( `No active feature-freeze/release-candidate branch. ` + `Unable to merge pull request using "target: rc" label.`); @@ -86,11 +91,11 @@ export async function getDefaultTargetLabelConfiguration( // directly through the Github UI and has the `target: rc` label applied, merge it // only into the release candidate branch. This is useful if a PR did not apply cleanly // into the release-candidate/feature-freeze branch, and a separate PR has been created. - if (githubTargetBranch === releaseCandidateBranch) { - return [releaseCandidateBranch]; + if (githubTargetBranch === releaseCandidate.branchName) { + return [releaseCandidate.branchName]; } // Otherwise, merge into the next and active release-candidate/feature-freeze branch. - return [nextBranchName, releaseCandidateBranch]; + return [nextBranchName, releaseCandidate.branchName]; }, }, { @@ -100,23 +105,23 @@ export async function getDefaultTargetLabelConfiguration( // commonly diverge quickly. This makes cherry-picking not an option for LTS changes. pattern: 'target: lts', branches: async githubTargetBranch => { - if (!isReleaseTrainBranch(githubTargetBranch)) { + if (!isVersionBranch(githubTargetBranch)) { throw new InvalidTargetBranchError( `PR cannot be merged as it does not target a long-term support ` + `branch: "${githubTargetBranch}"`); } - if (githubTargetBranch === latestVersionBranch) { + if (githubTargetBranch === latest.branchName) { throw new InvalidTargetBranchError( `PR cannot be merged with "target: lts" into patch branch. ` + `Consider changing the label to "target: patch" if this is intentional.`); } - if (githubTargetBranch === releaseCandidateBranch && releaseCandidateBranch !== null) { + if (releaseCandidate !== null && githubTargetBranch === releaseCandidate.branchName) { throw new InvalidTargetBranchError( `PR cannot be merged with "target: lts" into feature-freeze/release-candidate ` + `branch. Consider changing the label to "target: rc" if this is intentional.`); } // Assert that the selected branch is an active LTS branch. - await assertActiveLtsBranch(repo, githubTargetBranch); + await assertActiveLtsBranch(repo, releaseConfig, githubTargetBranch); return [githubTargetBranch]; }, }, diff --git a/dev-infra/pr/merge/defaults/lts-branch.ts b/dev-infra/pr/merge/defaults/lts-branch.ts index 5db07f8ad406e..f29fab26ea27a 100644 --- a/dev-infra/pr/merge/defaults/lts-branch.ts +++ b/dev-infra/pr/merge/defaults/lts-branch.ts @@ -6,40 +6,32 @@ * found in the LICENSE file at https://angular.io/license */ -import fetch from 'node-fetch'; import * as semver from 'semver'; +import {ReleaseConfig} from '../../../release/config/index'; +import {computeLtsEndDateOfMajor, fetchProjectNpmPackageInfo, getLtsNpmDistTagOfMajor, getVersionOfBranch, GithubRepoWithApi} from '../../../release/versioning'; import {promptConfirm, red, warn, yellow} from '../../../utils/console'; import {InvalidTargetBranchError} from '../target-label'; -import {getVersionOfBranch, GithubRepo} from './branches'; - -/** - * Number of months a major version in Angular is actively supported. See: - * https://angular.io/guide/releases#support-policy-and-schedule. - */ -const majorActiveSupportDuration = 6; - -/** - * Number of months a major version has active long-term support. See: - * https://angular.io/guide/releases#support-policy-and-schedule. - */ -const majorActiveTermSupportDuration = 12; - /** * Asserts that the given branch corresponds to an active LTS version-branch that can receive - * backported fixes. Throws an error if LTS expired or an invalid branch is selected. - */ -export async function assertActiveLtsBranch(repo: GithubRepo, branchName: string) { + * backport fixes. Throws an error if LTS expired or an invalid branch is selected. + * + * @param repo Repository containing the given branch. Used for Github API queries. + * @param releaseConfig Configuration for releases. Used to query NPM about past publishes. + * @param branchName Branch that is checked to be an active LTS version-branch. + * */ +export async function assertActiveLtsBranch( + repo: GithubRepoWithApi, releaseConfig: ReleaseConfig, branchName: string) { const version = await getVersionOfBranch(repo, branchName); - const {'dist-tags': distTags, time} = - await (await fetch(`https://registry.npmjs.org/${repo.npmPackageName}`)).json(); + const {'dist-tags': distTags, time} = await fetchProjectNpmPackageInfo(releaseConfig); // LTS versions should be tagged in NPM in the following format: `v{major}-lts`. - const ltsVersion = semver.parse(distTags[`v${version.major}-lts`]); + const ltsNpmTag = getLtsNpmDistTagOfMajor(version.major); + const ltsVersion = semver.parse(distTags[ltsNpmTag]); - // Ensure that there is a LTS version tagged for the given version-branch major. e.g. - // if the version branch is `9.2.x` then we want to make sure that there is a LTS + // Ensure that there is an LTS version tagged for the given version-branch major. e.g. + // if the version branch is `9.2.x` then we want to make sure that there is an LTS // version tagged in NPM for `v9`, following the `v{major}-lts` tag convention. if (ltsVersion === null) { throw new InvalidTargetBranchError(`No LTS version tagged for v${version.major} in NPM.`); @@ -54,12 +46,8 @@ export async function assertActiveLtsBranch(repo: GithubRepo, branchName: string } const today = new Date(); - const releaseDate = new Date(time[`${version.major}.0.0`]); - const ltsEndDate = new Date( - releaseDate.getFullYear(), - releaseDate.getMonth() + majorActiveSupportDuration + majorActiveTermSupportDuration, - releaseDate.getDate(), releaseDate.getHours(), releaseDate.getMinutes(), - releaseDate.getSeconds(), releaseDate.getMilliseconds()); + const majorReleaseDate = new Date(time[`${version.major}.0.0`]); + const ltsEndDate = computeLtsEndDateOfMajor(majorReleaseDate); // Check if LTS has already expired for the targeted major version. If so, we do not // allow the merge as per our LTS guarantees. Can be forcibly overridden if desired. diff --git a/dev-infra/pr/merge/index.ts b/dev-infra/pr/merge/index.ts index 816aa679d2715..d6d28a6619757 100644 --- a/dev-infra/pr/merge/index.ts +++ b/dev-infra/pr/merge/index.ts @@ -11,14 +11,11 @@ import {getConfig, getRepoBaseDir} from '../../utils/config'; import {error, green, info, promptConfirm, red, yellow} from '../../utils/console'; import {GitClient} from '../../utils/git'; import {GithubApiRequestError} from '../../utils/git/github'; +import {GITHUB_TOKEN_GENERATE_URL} from '../../utils/git/github-urls'; -import {loadAndValidateConfig, MergeConfig, MergeConfigWithRemote} from './config'; +import {loadAndValidateConfig, MergeConfigWithRemote} from './config'; import {MergeResult, MergeStatus, PullRequestMergeTask} from './task'; -/** URL to the Github page where personal access tokens can be generated. */ -export const GITHUB_TOKEN_GENERATE_URL = `https://github.com/settings/tokens`; - - /** * Merges a given pull request based on labels configured in the given merge configuration. * Pull requests can be merged with different strategies such as the Github API merge @@ -35,6 +32,10 @@ export const GITHUB_TOKEN_GENERATE_URL = `https://github.com/settings/tokens`; export async function mergePullRequest( prNumber: number, githubToken: string, projectRoot: string = getRepoBaseDir(), config?: MergeConfigWithRemote) { + // Set the environment variable to skip all git commit hooks triggered by husky. We are unable to + // rely on `--no-verify` as some hooks still run, notably the `prepare-commit-msg` hook. + process.env['HUSKY_SKIP_HOOKS'] = '1'; + const api = await createPullRequestMergeTask(githubToken, projectRoot, config); // Perform the merge. Force mode can be activated through a command line flag. diff --git a/dev-infra/pr/merge/messages.ts b/dev-infra/pr/merge/messages.ts index dbcb0aac667f1..34a34ce3db5b2 100644 --- a/dev-infra/pr/merge/messages.ts +++ b/dev-infra/pr/merge/messages.ts @@ -11,5 +11,11 @@ import {PullRequest} from './pull-request'; export function getCaretakerNotePromptMessage(pullRequest: PullRequest): string { return red('Pull request has a caretaker note applied. Please make sure you read it.') + - `\nQuick link to PR: ${pullRequest.url}`; + `\nQuick link to PR: ${pullRequest.url}\nDo you want to proceed merging?`; +} + +export function getTargettedBranchesConfirmationPromptMessage(pullRequest: PullRequest): string { + const targetBranchListAsString = pullRequest.targetBranches.map(b => ` - ${b}\n`).join(''); + return `Pull request #${pullRequest.prNumber} will merge into:\n${ + targetBranchListAsString}\nDo you want to proceed merging?`; } diff --git a/dev-infra/pr/merge/strategies/api-merge.ts b/dev-infra/pr/merge/strategies/api-merge.ts index f52b768e00b4e..42afdd1c6fa24 100644 --- a/dev-infra/pr/merge/strategies/api-merge.ts +++ b/dev-infra/pr/merge/strategies/api-merge.ts @@ -9,7 +9,7 @@ import {PullsListCommitsResponse, PullsMergeParams} from '@octokit/rest'; import {prompt} from 'inquirer'; -import {parseCommitMessage} from '../../../commit-message/validate'; +import {parseCommitMessage} from '../../../commit-message/parse'; import {GitClient} from '../../../utils/git'; import {GithubApiMergeMethod} from '../config'; import {PullRequestFailure} from '../failures'; diff --git a/dev-infra/pr/merge/task.ts b/dev-infra/pr/merge/task.ts index 4d20d2a338e29..42ca89898fbb4 100644 --- a/dev-infra/pr/merge/task.ts +++ b/dev-infra/pr/merge/task.ts @@ -9,9 +9,9 @@ import {promptConfirm} from '../../utils/console'; import {GitClient, GitCommandError} from '../../utils/git'; -import {MergeConfig, MergeConfigWithRemote} from './config'; +import {MergeConfigWithRemote} from './config'; import {PullRequestFailure} from './failures'; -import {getCaretakerNotePromptMessage} from './messages'; +import {getCaretakerNotePromptMessage, getTargettedBranchesConfirmationPromptMessage} from './messages'; import {isPullRequest, loadAndValidatePullRequest,} from './pull-request'; import {GithubApiMergeStrategy} from './strategies/api-merge'; import {AutosquashMergeStrategy} from './strategies/autosquash-merge'; @@ -78,11 +78,16 @@ export class PullRequestMergeTask { return {status: MergeStatus.FAILED, failure: pullRequest}; } + + if (!await promptConfirm(getTargettedBranchesConfirmationPromptMessage(pullRequest))) { + return {status: MergeStatus.USER_ABORTED}; + } + + // If the pull request has a caretaker note applied, raise awareness by prompting // the caretaker. The caretaker can then decide to proceed or abort the merge. if (pullRequest.hasCaretakerNote && - !await promptConfirm( - getCaretakerNotePromptMessage(pullRequest) + `\nDo you want to proceed merging?`)) { + !await promptConfirm(getCaretakerNotePromptMessage(pullRequest))) { return {status: MergeStatus.USER_ABORTED}; } diff --git a/dev-infra/pr/rebase/BUILD.bazel b/dev-infra/pr/rebase/BUILD.bazel index 5ee5219d5de59..0e49fd70a4238 100644 --- a/dev-infra/pr/rebase/BUILD.bazel +++ b/dev-infra/pr/rebase/BUILD.bazel @@ -1,4 +1,4 @@ -load("@npm_bazel_typescript//:index.bzl", "ts_library") +load("@npm//@bazel/typescript:index.bzl", "ts_library") ts_library( name = "rebase", diff --git a/dev-infra/pr/rebase/cli.ts b/dev-infra/pr/rebase/cli.ts index 03a369d89125c..6b1c0c05f128e 100644 --- a/dev-infra/pr/rebase/cli.ts +++ b/dev-infra/pr/rebase/cli.ts @@ -8,30 +8,23 @@ import {Arguments, Argv} from 'yargs'; -import {error} from '../../utils/console'; +import {addGithubTokenOption} from '../../utils/git/github-yargs'; import {rebasePr} from './index'; -/** URL to the Github page where personal access tokens can be generated. */ -export const GITHUB_TOKEN_GENERATE_URL = `https://github.com/settings/tokens`; +/** The options available to the rebase command via CLI. */ +export interface RebaseCommandOptions { + githubToken: string; + prNumber: number; +} /** Builds the rebase pull request command. */ -export function buildRebaseCommand(yargs: Argv) { - return yargs.option('github-token', { - type: 'string', - description: 'Github token. If not set, token is retrieved from the environment variables.' - }); +export function buildRebaseCommand(yargs: Argv): Argv { + return addGithubTokenOption(yargs).positional('prNumber', {type: 'number', demandOption: true}); } /** Handles the rebase pull request command. */ -export async function handleRebaseCommand(args: Arguments) { - const githubToken = args.githubToken || process.env.GITHUB_TOKEN || process.env.TOKEN; - if (!githubToken) { - error('No Github token set. Please set the `GITHUB_TOKEN` environment variable.'); - error('Alternatively, pass the `--github-token` command line flag.'); - error(`You can generate a token here: ${GITHUB_TOKEN_GENERATE_URL}`); - process.exit(1); - } - - await rebasePr(args.prNumber, githubToken); +export async function handleRebaseCommand( + {prNumber, githubToken}: Arguments) { + await rebasePr(prNumber, githubToken); } diff --git a/dev-infra/pr/rebase/index.ts b/dev-infra/pr/rebase/index.ts index 8c0af93324c7b..7aa63e6290c5d 100644 --- a/dev-infra/pr/rebase/index.ts +++ b/dev-infra/pr/rebase/index.ts @@ -7,11 +7,11 @@ */ import {types as graphQLTypes} from 'typed-graphqlify'; -import {URL} from 'url'; import {getConfig, NgDevConfig} from '../../utils/config'; import {error, info, promptConfirm} from '../../utils/console'; import {GitClient} from '../../utils/git'; +import {addTokenToGitHttpsUrl} from '../../utils/git/github-urls'; import {getPr} from '../../utils/github'; /* GraphQL schema for the response body for each pending PR. */ @@ -55,14 +55,14 @@ export async function rebasePr( */ const previousBranchOrRevision = git.getCurrentBranchOrRevision(); /* Get the PR information from Github. */ - const pr = await getPr(PR_SCHEMA, prNumber, config.github); + const pr = await getPr(PR_SCHEMA, prNumber, git); const headRefName = pr.headRef.name; const baseRefName = pr.baseRef.name; const fullHeadRef = `${pr.headRef.repository.nameWithOwner}:${headRefName}`; const fullBaseRef = `${pr.baseRef.repository.nameWithOwner}:${baseRefName}`; - const headRefUrl = addAuthenticationToUrl(pr.headRef.repository.url, githubToken); - const baseRefUrl = addAuthenticationToUrl(pr.baseRef.repository.url, githubToken); + const headRefUrl = addTokenToGitHttpsUrl(pr.headRef.repository.url, githubToken); + const baseRefUrl = addTokenToGitHttpsUrl(pr.baseRef.repository.url, githubToken); // Note: Since we use a detached head for rebasing the PR and therefore do not have // remote-tracking branches configured, we need to set our expected ref and SHA. This @@ -99,12 +99,12 @@ export async function rebasePr( info(`Pushing rebased PR #${prNumber} to ${fullHeadRef}`); git.run(['push', headRefUrl, `HEAD:${headRefName}`, forceWithLeaseFlag]); info(`Rebased and updated PR #${prNumber}`); - cleanUpGitState(); + git.checkout(previousBranchOrRevision, true); process.exit(0); } } catch (err) { error(err.message); - cleanUpGitState(); + git.checkout(previousBranchOrRevision, true); process.exit(1); } @@ -127,23 +127,6 @@ export async function rebasePr( info(`Cleaning up git state, and restoring previous state.`); } - cleanUpGitState(); + git.checkout(previousBranchOrRevision, true); process.exit(1); - - /** Reset git back to the original branch. */ - function cleanUpGitState() { - // Ensure that any outstanding rebases are aborted. - git.runGraceful(['rebase', '--abort'], {stdio: 'ignore'}); - // Ensure that any changes in the current repo state are cleared. - git.runGraceful(['reset', '--hard'], {stdio: 'ignore'}); - // Checkout the original branch from before the run began. - git.runGraceful(['checkout', previousBranchOrRevision], {stdio: 'ignore'}); - } -} - -/** Adds the provided token as username to the provided url. */ -function addAuthenticationToUrl(urlString: string, token: string) { - const url = new URL(urlString); - url.username = token; - return url.toString(); } diff --git a/dev-infra/pullapprove/BUILD.bazel b/dev-infra/pullapprove/BUILD.bazel index 4cd28756f03be..8d452677495d9 100644 --- a/dev-infra/pullapprove/BUILD.bazel +++ b/dev-infra/pullapprove/BUILD.bazel @@ -1,4 +1,4 @@ -load("@npm_bazel_typescript//:index.bzl", "ts_library") +load("@npm//@bazel/typescript:index.bzl", "ts_library") load("//tools:defaults.bzl", "jasmine_node_test") ts_library( diff --git a/dev-infra/release/BUILD.bazel b/dev-infra/release/BUILD.bazel index 065521461eeee..16e0a5146a1be 100644 --- a/dev-infra/release/BUILD.bazel +++ b/dev-infra/release/BUILD.bazel @@ -1,18 +1,18 @@ -load("@npm_bazel_typescript//:index.bzl", "ts_library") +load("@npm//@bazel/typescript:index.bzl", "ts_library") ts_library( name = "release", srcs = glob([ - "*.ts", + "**/*.ts", ]), module_name = "@angular/dev-infra-private/release", visibility = ["//dev-infra:__subpackages__"], deps = [ + "//dev-infra/release/build", + "//dev-infra/release/publish", + "//dev-infra/release/set-dist-tag", "//dev-infra/utils", - "@npm//@types/node", - "@npm//@types/shelljs", "@npm//@types/yargs", - "@npm//shelljs", "@npm//yargs", ], ) diff --git a/dev-infra/release/build/BUILD.bazel b/dev-infra/release/build/BUILD.bazel new file mode 100644 index 0000000000000..679c0f2c1e108 --- /dev/null +++ b/dev-infra/release/build/BUILD.bazel @@ -0,0 +1,38 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_library") +load("//tools:defaults.bzl", "jasmine_node_test") + +ts_library( + name = "build", + srcs = glob( + [ + "**/*.ts", + ], + exclude = ["*.spec.ts"], + ), + module_name = "@angular/dev-infra-private/release/build", + visibility = ["//dev-infra:__subpackages__"], + deps = [ + "//dev-infra/release/config", + "//dev-infra/utils", + "@npm//@types/node", + "@npm//@types/yargs", + ], +) + +ts_library( + name = "test_lib", + srcs = glob([ + "*.spec.ts", + ]), + deps = [ + ":build", + "//dev-infra/release/config", + "@npm//@types/jasmine", + "@npm//@types/node", + ], +) + +jasmine_node_test( + name = "test", + deps = [":test_lib"], +) diff --git a/dev-infra/release/build/build-worker.ts b/dev-infra/release/build/build-worker.ts new file mode 100644 index 0000000000000..5cc090495e3e6 --- /dev/null +++ b/dev-infra/release/build/build-worker.ts @@ -0,0 +1,32 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +/* + * This file will be spawned as a separate process when the `ng-dev release build` command is + * invoked. A separate process allows us to hide any superfluous stdout output from arbitrary + * build commands that we cannot control. This is necessary as the `ng-dev release build` command + * supports stdout JSON output that should be parsable and not polluted from other stdout messages. + */ + +import {getReleaseConfig} from '../config/index'; + +// Start the release package building. +main(); + +/** Main function for building the release packages. */ +async function main() { + if (process.send === undefined) { + throw Error('This script needs to be invoked as a NodeJS worker.'); + } + + const config = getReleaseConfig(); + const builtPackages = await config.buildPackages(); + + // Transfer the built packages back to the parent process. + process.send(builtPackages); +} diff --git a/dev-infra/release/build/build.spec.ts b/dev-infra/release/build/build.spec.ts new file mode 100644 index 0000000000000..9f6ca0fb809a2 --- /dev/null +++ b/dev-infra/release/build/build.spec.ts @@ -0,0 +1,77 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as releaseConfig from '../config/index'; +import {ReleaseBuildCommandModule} from './cli'; +import * as index from './index'; + +describe('ng-dev release build', () => { + let npmPackages: string[]; + let buildPackages: jasmine.Spy; + + beforeEach(() => { + npmPackages = ['@angular/pkg1', '@angular/pkg2']; + buildPackages = jasmine.createSpy('buildPackages').and.resolveTo([ + {name: '@angular/pkg1', outputPath: 'dist/pkg1'}, + {name: '@angular/pkg2', outputPath: 'dist/pkg2'}, + ]); + + // We cannot test the worker process, so we fake the worker function and + // directly call the package build function. + spyOn(index, 'buildReleaseOutput').and.callFake(() => buildPackages()); + // We need to stub out the `process.exit` function during tests as the CLI + // handler calls those in case of failures. + spyOn(process, 'exit'); + }); + + /** Invokes the build command handler. */ + async function invokeBuild({json}: {json?: boolean} = {}) { + spyOn(releaseConfig, 'getReleaseConfig') + .and.returnValue({npmPackages, buildPackages, generateReleaseNotesForHead: async () => {}}); + await ReleaseBuildCommandModule.handler({json: !!json, $0: '', _: []}); + } + + it('should invoke configured build packages function', async () => { + await invokeBuild(); + expect(buildPackages).toHaveBeenCalledTimes(1); + expect(process.exit).toHaveBeenCalledTimes(0); + }); + + it('should print built packages as JSON if `--json` is specified', async () => { + const writeSpy = spyOn(process.stdout, 'write'); + await invokeBuild({json: true}); + + expect(buildPackages).toHaveBeenCalledTimes(1); + expect(writeSpy).toHaveBeenCalledTimes(1); + + const jsonText = writeSpy.calls.mostRecent().args[0] as string; + const parsed = JSON.parse(jsonText); + + expect(parsed).toEqual([ + {name: '@angular/pkg1', outputPath: 'dist/pkg1'}, + {name: '@angular/pkg2', outputPath: 'dist/pkg2'} + ]); + expect(process.exit).toHaveBeenCalledTimes(0); + }); + + it('should error if package has not been built', async () => { + // Set up an NPM package that is not built. + npmPackages.push('@angular/non-existent'); + + spyOn(console, 'error'); + await invokeBuild(); + + expect(console.error).toHaveBeenCalledTimes(2); + expect(console.error) + .toHaveBeenCalledWith( + jasmine.stringMatching(`Release output missing for the following packages`)); + expect(console.error).toHaveBeenCalledWith(jasmine.stringMatching(`- @angular/non-existent`)); + expect(process.exit).toHaveBeenCalledTimes(1); + expect(process.exit).toHaveBeenCalledWith(1); + }); +}); diff --git a/dev-infra/release/build/cli.ts b/dev-infra/release/build/cli.ts new file mode 100644 index 0000000000000..9898e5f74bf3b --- /dev/null +++ b/dev-infra/release/build/cli.ts @@ -0,0 +1,75 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {Arguments, Argv, CommandModule} from 'yargs'; + +import {getConfig} from '../../utils/config'; +import {error, green, info, red, warn, yellow} from '../../utils/console'; +import {BuiltPackage, getReleaseConfig} from '../config/index'; + +import {buildReleaseOutput} from './index'; + +/** Command line options for building a release. */ +export interface ReleaseBuildOptions { + json: boolean; +} + +/** Yargs command builder for configuring the `ng-dev release build` command. */ +function builder(argv: Argv): Argv { + return argv.option('json', { + type: 'boolean', + description: 'Whether the built packages should be printed to stdout as JSON.', + default: false, + }); +} + +/** Yargs command handler for building a release. */ +async function handler(args: Arguments) { + const {npmPackages} = getReleaseConfig(); + let builtPackages = await buildReleaseOutput(); + + // If package building failed, print an error and exit with an error code. + if (builtPackages === null) { + error(red(` ✘ Could not build release output. Please check output above.`)); + process.exit(1); + } + + // If no packages have been built, we assume that this is never correct + // and exit with an error code. + if (builtPackages.length === 0) { + error(red(` ✘ No release packages have been built. Please ensure that the`)); + error(red(` build script is configured correctly in ".ng-dev".`)); + process.exit(1); + } + + const missingPackages = + npmPackages.filter(pkgName => !builtPackages!.find(b => b.name === pkgName)); + + // Check for configured release packages which have not been built. We want to + // error and exit if any configured package has not been built. + if (missingPackages.length > 0) { + error(red(` ✘ Release output missing for the following packages:`)); + missingPackages.forEach(pkgName => error(red(` - ${pkgName}`))); + process.exit(1); + } + + if (args.json) { + process.stdout.write(JSON.stringify(builtPackages, null, 2)); + } else { + info(green(' ✓ Built release packages.')); + builtPackages.forEach(({name}) => info(green(` - ${name}`))); + } +} + +/** CLI command module for building release output. */ +export const ReleaseBuildCommandModule: CommandModule<{}, ReleaseBuildOptions> = { + builder, + handler, + command: 'build', + describe: 'Builds the release output for the current branch.', +}; diff --git a/dev-infra/release/build/index.ts b/dev-infra/release/build/index.ts new file mode 100644 index 0000000000000..7a024490a482a --- /dev/null +++ b/dev-infra/release/build/index.ts @@ -0,0 +1,36 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {fork} from 'child_process'; +import {BuiltPackage} from '../config/index'; + +/** + * Builds the release output without polluting the process stdout. Build scripts commonly + * print messages to stderr or stdout. This is fine in most cases, but sometimes other tooling + * reserves stdout for data transfer (e.g. when `ng release build --json` is invoked). To not + * pollute the stdout in such cases, we launch a child process for building the release packages + * and redirect all stdout output to the stderr channel (which can be read in the terminal). + */ +export async function buildReleaseOutput(): Promise { + return new Promise(resolve => { + const buildProcess = fork(require.resolve('./build-worker'), [], { + // The stdio option is set to redirect any "stdout" output directly to the "stderr" file + // descriptor. An additional "ipc" file descriptor is created to support communication with + // the build process. https://nodejs.org/api/child_process.html#child_process_options_stdio. + stdio: ['inherit', 2, 2, 'ipc'], + }); + let builtPackages: BuiltPackage[]|null = null; + + // The child process will pass the `buildPackages()` output through the + // IPC channel. We keep track of it so that we can use it as resolve value. + buildProcess.on('message', buildResponse => builtPackages = buildResponse); + + // On child process exit, resolve the promise with the received output. + buildProcess.on('exit', () => resolve(builtPackages)); + }); +} diff --git a/dev-infra/release/cli.ts b/dev-infra/release/cli.ts index bd2646260e074..988b34643792c 100644 --- a/dev-infra/release/cli.ts +++ b/dev-infra/release/cli.ts @@ -6,12 +6,23 @@ * found in the LICENSE file at https://angular.io/license */ import * as yargs from 'yargs'; -import {buildEnvStamp} from './env-stamp'; + +import {ReleaseBuildCommandModule} from './build/cli'; +import {ReleasePublishCommandModule} from './publish/cli'; +import {ReleaseSetDistTagCommand} from './set-dist-tag/cli'; +import {buildEnvStamp} from './stamping/env-stamp'; /** Build the parser for the release commands. */ export function buildReleaseParser(localYargs: yargs.Argv) { - return localYargs.help().strict().demandCommand().command( - 'build-env-stamp', 'Build the environment stamping information', {}, () => buildEnvStamp()); + return localYargs.help() + .strict() + .demandCommand() + .command(ReleasePublishCommandModule) + .command(ReleaseBuildCommandModule) + .command(ReleaseSetDistTagCommand) + .command( + 'build-env-stamp', 'Build the environment stamping information', {}, + () => buildEnvStamp()); } if (require.main === module) { diff --git a/dev-infra/release/config/BUILD.bazel b/dev-infra/release/config/BUILD.bazel new file mode 100644 index 0000000000000..186db7f542f57 --- /dev/null +++ b/dev-infra/release/config/BUILD.bazel @@ -0,0 +1,14 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_library") + +ts_library( + name = "config", + srcs = glob([ + "**/*.ts", + ]), + module_name = "@angular/dev-infra-private/release/config", + visibility = ["//dev-infra:__subpackages__"], + deps = [ + "//dev-infra/utils", + "@npm//@types/semver", + ], +) diff --git a/dev-infra/release/config/index.ts b/dev-infra/release/config/index.ts new file mode 100644 index 0000000000000..da1f75911600b --- /dev/null +++ b/dev-infra/release/config/index.ts @@ -0,0 +1,63 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as semver from 'semver'; + +import {assertNoErrors, getConfig, NgDevConfig} from '../../utils/config'; + +/** Interface describing a built package. */ +export interface BuiltPackage { + /** Name of the package. */ + name: string; + /** Path to the package output directory. */ + outputPath: string; +} + +/** Configuration for staging and publishing a release. */ +export interface ReleaseConfig { + /** Registry URL used for publishing release packages. Defaults to the NPM registry. */ + publishRegistry?: string; + /** List of NPM packages that are published as part of this project. */ + npmPackages: string[]; + /** Builds release packages and returns a list of paths pointing to the output. */ + buildPackages: () => Promise; + /** Generates the release notes from the most recent tag to `HEAD`. */ + generateReleaseNotesForHead: (outputPath: string) => Promise; + /** + * Gets a pattern for extracting the release notes of the a given version. + * @returns A pattern matching the notes for a given version (including the header). + */ + // TODO: Remove this in favor of a canonical changelog format across the Angular organization. + extractReleaseNotesPattern?: (version: semver.SemVer) => RegExp; +} + +/** Configuration for releases in the dev-infra configuration. */ +export type DevInfraReleaseConfig = NgDevConfig<{release: ReleaseConfig}>; + +/** Retrieve and validate the config as `ReleaseConfig`. */ +export function getReleaseConfig(config: Partial = getConfig()): + ReleaseConfig { + // List of errors encountered validating the config. + const errors: string[] = []; + + if (config.release === undefined) { + errors.push(`No configuration defined for "release"`); + } + if (config.release?.npmPackages === undefined) { + errors.push(`No "npmPackages" configured for releasing.`); + } + if (config.release?.buildPackages === undefined) { + errors.push(`No "buildPackages" function configured for releasing.`); + } + if (config.release?.generateReleaseNotesForHead === undefined) { + errors.push(`No "generateReleaseNotesForHead" function configured for releasing.`); + } + + assertNoErrors(errors); + return config.release!; +} diff --git a/dev-infra/release/publish/BUILD.bazel b/dev-infra/release/publish/BUILD.bazel new file mode 100644 index 0000000000000..a2f62b7dc58bf --- /dev/null +++ b/dev-infra/release/publish/BUILD.bazel @@ -0,0 +1,25 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_library") + +ts_library( + name = "publish", + srcs = glob([ + "**/*.ts", + ]), + module_name = "@angular/dev-infra-private/release/publish", + visibility = ["//dev-infra:__subpackages__"], + deps = [ + "//dev-infra/pr/merge", + "//dev-infra/release/config", + "//dev-infra/release/versioning", + "//dev-infra/utils", + "@npm//@octokit/rest", + "@npm//@types/inquirer", + "@npm//@types/node", + "@npm//@types/semver", + "@npm//@types/yargs", + "@npm//inquirer", + "@npm//ora", + "@npm//semver", + "@npm//typed-graphqlify", + ], +) diff --git a/dev-infra/release/publish/actions-error.ts b/dev-infra/release/publish/actions-error.ts new file mode 100644 index 0000000000000..517b7bcf47d6a --- /dev/null +++ b/dev-infra/release/publish/actions-error.ts @@ -0,0 +1,29 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +/** Error that will be thrown if the user manually aborted a release action. */ +export class UserAbortedReleaseActionError extends Error { + constructor() { + super(); + // Set the prototype explicitly because in ES5, the prototype is accidentally lost due to + // a limitation in down-leveling. + // https://github.com/Microsoft/TypeScript/wiki/FAQ#why-doesnt-extending-built-ins-like-error-array-and-map-work. + Object.setPrototypeOf(this, UserAbortedReleaseActionError.prototype); + } +} + +/** Error that will be thrown if the action has been aborted due to a fatal error. */ +export class FatalReleaseActionError extends Error { + constructor() { + super(); + // Set the prototype explicitly because in ES5, the prototype is accidentally lost due to + // a limitation in down-leveling. + // https://github.com/Microsoft/TypeScript/wiki/FAQ#why-doesnt-extending-built-ins-like-error-array-and-map-work. + Object.setPrototypeOf(this, FatalReleaseActionError.prototype); + } +} diff --git a/dev-infra/release/publish/actions.ts b/dev-infra/release/publish/actions.ts new file mode 100644 index 0000000000000..2bfbbb44b9619 --- /dev/null +++ b/dev-infra/release/publish/actions.ts @@ -0,0 +1,540 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {promises as fs} from 'fs'; +import * as ora from 'ora'; +import {join} from 'path'; +import * as semver from 'semver'; + +import {debug, error, green, info, promptConfirm, red, warn, yellow} from '../../utils/console'; +import {getListCommitsInBranchUrl, getRepositoryGitUrl} from '../../utils/git/github-urls'; +import {GitClient} from '../../utils/git/index'; +import {BuiltPackage, ReleaseConfig} from '../config'; +import {ActiveReleaseTrains} from '../versioning/active-release-trains'; +import {runNpmPublish} from '../versioning/npm-publish'; + +import {FatalReleaseActionError, UserAbortedReleaseActionError} from './actions-error'; +import {getCommitMessageForRelease, getReleaseNoteCherryPickCommitMessage} from './commit-message'; +import {changelogPath, packageJsonPath, waitForPullRequestInterval} from './constants'; +import {invokeReleaseBuildCommand, invokeYarnInstallCommand} from './external-commands'; +import {findOwnedForksOfRepoQuery} from './graphql-queries'; +import {getPullRequestState} from './pull-request-state'; +import {getDefaultExtractReleaseNotesPattern, getLocalChangelogFilePath} from './release-notes'; + +/** Interface describing a Github repository. */ +export interface GithubRepo { + owner: string; + name: string; +} + +/** Interface describing a Github pull request. */ +export interface PullRequest { + /** Unique id for the pull request (i.e. the PR number). */ + id: number; + /** URL that resolves to the pull request in Github. */ + url: string; + /** Fork containing the head branch of this pull request. */ + fork: GithubRepo; + /** Branch name in the fork that defines this pull request. */ + forkBranch: string; +} + +/** Constructor type for instantiating a release action */ +export interface ReleaseActionConstructor { + /** Whether the release action is currently active. */ + isActive(active: ActiveReleaseTrains): Promise; + /** Constructs a release action. */ + new(...args: [ActiveReleaseTrains, GitClient, ReleaseConfig, string]): T; +} + +/** + * Abstract base class for a release action. A release action is selectable by the caretaker + * if active, and can perform changes for releasing, such as staging a release, bumping the + * version, cherry-picking the changelog, branching off from master. etc. + */ +export abstract class ReleaseAction { + /** Whether the release action is currently active. */ + static isActive(_trains: ActiveReleaseTrains): Promise { + throw Error('Not implemented.'); + } + + /** Gets the description for a release action. */ + abstract getDescription(): Promise; + /** + * Performs the given release action. + * @throws {UserAbortedReleaseActionError} When the user manually aborted the action. + * @throws {FatalReleaseActionError} When the action has been aborted due to a fatal error. + */ + abstract perform(): Promise; + + /** Cached found fork of the configured project. */ + private _cachedForkRepo: GithubRepo|null = null; + + constructor( + protected active: ActiveReleaseTrains, protected git: GitClient, + protected config: ReleaseConfig, protected projectDir: string) {} + + /** Updates the version in the project top-level `package.json` file. */ + protected async updateProjectVersion(newVersion: semver.SemVer) { + const pkgJsonPath = join(this.projectDir, packageJsonPath); + const pkgJson = JSON.parse(await fs.readFile(pkgJsonPath, 'utf8')); + pkgJson.version = newVersion.format(); + // Write the `package.json` file. Note that we add a trailing new line + // to avoid unnecessary diff. IDEs usually add a trailing new line. + await fs.writeFile(pkgJsonPath, `${JSON.stringify(pkgJson, null, 2)}\n`); + info(green(` ✓ Updated project version to ${pkgJson.version}`)); + } + + /** Gets the most recent commit of a specified branch. */ + private async _getCommitOfBranch(branchName: string): Promise { + const {data: {commit}} = + await this.git.github.repos.getBranch({...this.git.remoteParams, branch: branchName}); + return commit.sha; + } + + /** Verifies that the latest commit for the given branch is passing all statuses. */ + protected async verifyPassingGithubStatus(branchName: string) { + const commitSha = await this._getCommitOfBranch(branchName); + const {data: {state}} = await this.git.github.repos.getCombinedStatusForRef( + {...this.git.remoteParams, ref: commitSha}); + const branchCommitsUrl = getListCommitsInBranchUrl(this.git, branchName); + + if (state === 'failure') { + error( + red(` ✘ Cannot stage release. Commit "${commitSha}" does not pass all github ` + + 'status checks. Please make sure this commit passes all checks before re-running.')); + error(` Please have a look at: ${branchCommitsUrl}`); + + if (await promptConfirm('Do you want to ignore the Github status and proceed?')) { + info(yellow( + ' ⚠ Upstream commit is failing CI checks, but status has been forcibly ignored.')); + return; + } + throw new UserAbortedReleaseActionError(); + } else if (state === 'pending') { + error( + red(` ✘ Commit "${commitSha}" still has pending github statuses that ` + + 'need to succeed before staging a release.')); + error(red(` Please have a look at: ${branchCommitsUrl}`)); + if (await promptConfirm('Do you want to ignore the Github status and proceed?')) { + info(yellow(' ⚠ Upstream commit is pending CI, but status has been forcibly ignored.')); + return; + } + throw new UserAbortedReleaseActionError(); + } + + info(green(' ✓ Upstream commit is passing all github status checks.')); + } + + /** Generates the changelog for the specified for the current `HEAD`. */ + private async _generateReleaseNotesForHead(version: semver.SemVer) { + const changelogPath = getLocalChangelogFilePath(this.projectDir); + await this.config.generateReleaseNotesForHead(changelogPath); + info(green(` ✓ Updated the changelog to capture changes for "${version}".`)); + } + + /** Extract the release notes for the given version from the changelog file. */ + private _extractReleaseNotesForVersion(changelogContent: string, version: semver.SemVer): string + |null { + const pattern = this.config.extractReleaseNotesPattern !== undefined ? + this.config.extractReleaseNotesPattern(version) : + getDefaultExtractReleaseNotesPattern(version); + const matchedNotes = pattern.exec(changelogContent); + return matchedNotes === null ? null : matchedNotes[1]; + } + + /** + * Prompts the user for potential release notes edits that need to be made. Once + * confirmed, a new commit for the release point is created. + */ + protected async waitForEditsAndCreateReleaseCommit(newVersion: semver.SemVer) { + info(yellow( + ' ⚠ Please review the changelog and ensure that the log contains only changes ' + + 'that apply to the public API surface. Manual changes can be made. When done, please ' + + 'proceed with the prompt below.')); + + if (!await promptConfirm('Do you want to proceed and commit the changes?')) { + throw new UserAbortedReleaseActionError(); + } + + // Commit message for the release point. + const commitMessage = getCommitMessageForRelease(newVersion); + // Create a release staging commit including changelog and version bump. + await this.createCommit(commitMessage, [packageJsonPath, changelogPath]); + + info(green(` ✓ Created release commit for: "${newVersion}".`)); + } + + /** + * Gets an owned fork for the configured project of the authenticated user. Aborts the + * process with an error if no fork could be found. Also caches the determined fork + * repository as the authenticated user cannot change during action execution. + */ + private async _getForkOfAuthenticatedUser(): Promise { + if (this._cachedForkRepo !== null) { + return this._cachedForkRepo; + } + + const {owner, name} = this.git.remoteConfig; + const result = await this.git.github.graphql.query(findOwnedForksOfRepoQuery, {owner, name}); + const forks = result.repository.forks.nodes; + + if (forks.length === 0) { + error(red(' ✘ Unable to find fork for currently authenticated user.')); + error(red(` Please ensure you created a fork of: ${owner}/${name}.`)); + throw new FatalReleaseActionError(); + } + + const fork = forks[0]; + return this._cachedForkRepo = {owner: fork.owner.login, name: fork.name}; + } + + /** Checks whether a given branch name is reserved in the specified repository. */ + private async _isBranchNameReservedInRepo(repo: GithubRepo, name: string): Promise { + try { + await this.git.github.repos.getBranch({owner: repo.owner, repo: repo.name, branch: name}); + return true; + } catch (e) { + // If the error has a `status` property set to `404`, then we know that the branch + // does not exist. Otherwise, it might be an API error that we want to report/re-throw. + if (e.status === 404) { + return false; + } + throw e; + } + } + + /** Finds a non-reserved branch name in the repository with respect to a base name. */ + private async _findAvailableBranchName(repo: GithubRepo, baseName: string): Promise { + let currentName = baseName; + let suffixNum = 0; + while (await this._isBranchNameReservedInRepo(repo, currentName)) { + suffixNum++; + currentName = `${baseName}_${suffixNum}`; + } + return currentName; + } + + /** + * Creates a local branch from the current Git `HEAD`. Will override + * existing branches in case of a collision. + */ + protected async createLocalBranchFromHead(branchName: string) { + this.git.run(['checkout', '-B', branchName]); + } + + /** Pushes the current Git `HEAD` to the given remote branch in the configured project. */ + protected async pushHeadToRemoteBranch(branchName: string) { + // Push the local `HEAD` to the remote branch in the configured project. + this.git.run(['push', this.git.repoGitUrl, `HEAD:refs/heads/${branchName}`]); + } + + /** + * Pushes the current Git `HEAD` to a fork for the configured project that is owned by + * the authenticated user. If the specified branch name exists in the fork already, a + * unique one will be generated based on the proposed name to avoid collisions. + * @param proposedBranchName Proposed branch name for the fork. + * @param trackLocalBranch Whether the fork branch should be tracked locally. i.e. whether + * a local branch with remote tracking should be set up. + * @returns The fork and branch name containing the pushed changes. + */ + private async _pushHeadToFork(proposedBranchName: string, trackLocalBranch: boolean): + Promise<{fork: GithubRepo, branchName: string}> { + const fork = await this._getForkOfAuthenticatedUser(); + // Compute a repository URL for pushing to the fork. Note that we want to respect + // the SSH option from the dev-infra github configuration. + const repoGitUrl = + getRepositoryGitUrl({...fork, useSsh: this.git.remoteConfig.useSsh}, this.git.githubToken); + const branchName = await this._findAvailableBranchName(fork, proposedBranchName); + const pushArgs: string[] = []; + // If a local branch should track the remote fork branch, create a branch matching + // the remote branch. Later with the `git push`, the remote is set for the branch. + if (trackLocalBranch) { + await this.createLocalBranchFromHead(branchName); + pushArgs.push('--set-upstream'); + } + // Push the local `HEAD` to the remote branch in the fork. + this.git.run(['push', repoGitUrl, `HEAD:refs/heads/${branchName}`, ...pushArgs]); + return {fork, branchName}; + } + + /** + * Pushes changes to a fork for the configured project that is owned by the currently + * authenticated user. A pull request is then created for the pushed changes on the + * configured project that targets the specified target branch. + * @returns An object describing the created pull request. + */ + protected async pushChangesToForkAndCreatePullRequest( + targetBranch: string, proposedForkBranchName: string, title: string, + body?: string): Promise { + const repoSlug = `${this.git.remoteParams.owner}/${this.git.remoteParams.repo}`; + const {fork, branchName} = await this._pushHeadToFork(proposedForkBranchName, true); + const {data} = await this.git.github.pulls.create({ + ...this.git.remoteParams, + head: `${fork.owner}:${branchName}`, + base: targetBranch, + body, + title, + }); + + info(green(` ✓ Created pull request #${data.number} in ${repoSlug}.`)); + return { + id: data.number, + url: data.html_url, + fork, + forkBranch: branchName, + }; + } + + /** + * Waits for the given pull request to be merged. Default interval for checking the Github + * API is 10 seconds (to not exceed any rate limits). If the pull request is closed without + * merge, the script will abort gracefully (considering a manual user abort). + */ + protected async waitForPullRequestToBeMerged(id: number, interval = waitForPullRequestInterval): + Promise { + return new Promise((resolve, reject) => { + debug(`Waiting for pull request #${id} to be merged.`); + + const spinner = ora().start(`Waiting for pull request #${id} to be merged.`); + const intervalId = setInterval(async () => { + const prState = await getPullRequestState(this.git, id); + if (prState === 'merged') { + spinner.stop(); + info(green(` ✓ Pull request #${id} has been merged.`)); + clearInterval(intervalId); + resolve(); + } else if (prState === 'closed') { + spinner.stop(); + warn(yellow(` ✘ Pull request #${id} has been closed.`)); + clearInterval(intervalId); + reject(new UserAbortedReleaseActionError()); + } + }, interval); + }); + } + + /** + * Prepend releases notes for a version published in a given branch to the changelog in + * the current Git `HEAD`. This is useful for cherry-picking the changelog. + * @returns A boolean indicating whether the release notes have been prepended. + */ + protected async prependReleaseNotesFromVersionBranch( + version: semver.SemVer, containingBranch: string): Promise { + const {data} = await this.git.github.repos.getContents( + {...this.git.remoteParams, path: '/' + changelogPath, ref: containingBranch}); + const branchChangelog = Buffer.from(data.content, 'base64').toString(); + let releaseNotes = this._extractReleaseNotesForVersion(branchChangelog, version); + // If no release notes could be extracted, return "false" so that the caller + // can tell that changelog prepending failed. + if (releaseNotes === null) { + return false; + } + const localChangelogPath = getLocalChangelogFilePath(this.projectDir); + const localChangelog = await fs.readFile(localChangelogPath, 'utf8'); + // If the extracted release notes do not have any new lines at the end and the + // local changelog is not empty, we add lines manually so that there is space + // between the previous and cherry-picked release notes. + if (!/[\r\n]+$/.test(releaseNotes) && localChangelog !== '') { + releaseNotes = `${releaseNotes}\n\n`; + } + // Prepend the extracted release notes to the local changelog and write it back. + await fs.writeFile(localChangelogPath, releaseNotes + localChangelog); + return true; + } + + /** Checks out an upstream branch with a detached head. */ + protected async checkoutUpstreamBranch(branchName: string) { + this.git.run(['fetch', this.git.repoGitUrl, branchName]); + this.git.run(['checkout', 'FETCH_HEAD', '--detach']); + } + + /** + * Creates a commit for the specified files with the given message. + * @param message Message for the created commit + * @param files List of project-relative file paths to be commited. + */ + protected async createCommit(message: string, files: string[]) { + this.git.run(['commit', '--no-verify', '-m', message, ...files]); + } + + /** + * Creates a cherry-pick commit for the release notes of the specified version that + * has been pushed to the given branch. + * @returns a boolean indicating whether the commit has been created successfully. + */ + protected async createCherryPickReleaseNotesCommitFrom( + version: semver.SemVer, branchName: string): Promise { + const commitMessage = getReleaseNoteCherryPickCommitMessage(version); + + // Fetch, extract and prepend the release notes to the local changelog. If that is not + // possible, abort so that we can ask the user to manually cherry-pick the changelog. + if (!await this.prependReleaseNotesFromVersionBranch(version, branchName)) { + return false; + } + + // Create a changelog cherry-pick commit. + await this.createCommit(commitMessage, [changelogPath]); + + info(green(` ✓ Created changelog cherry-pick commit for: "${version}".`)); + return true; + } + + /** + * Stages the specified new version for the current branch and creates a + * pull request that targets the given base branch. + * @returns an object describing the created pull request. + */ + protected async stageVersionForBranchAndCreatePullRequest( + newVersion: semver.SemVer, pullRequestBaseBranch: string): Promise { + await this.updateProjectVersion(newVersion); + await this._generateReleaseNotesForHead(newVersion); + await this.waitForEditsAndCreateReleaseCommit(newVersion); + + const pullRequest = await this.pushChangesToForkAndCreatePullRequest( + pullRequestBaseBranch, `release-stage-${newVersion}`, + `Bump version to "v${newVersion}" with changelog.`); + + info(green(' ✓ Release staging pull request has been created.')); + info(yellow(` Please ask team members to review: ${pullRequest.url}.`)); + + return pullRequest; + } + + /** + * Checks out the specified target branch, verifies its CI status and stages + * the specified new version in order to create a pull request. + * @returns an object describing the created pull request. + */ + protected async checkoutBranchAndStageVersion(newVersion: semver.SemVer, stagingBranch: string): + Promise { + await this.verifyPassingGithubStatus(stagingBranch); + await this.checkoutUpstreamBranch(stagingBranch); + return await this.stageVersionForBranchAndCreatePullRequest(newVersion, stagingBranch); + } + + /** + * Cherry-picks the release notes of a version that have been pushed to a given branch + * into the `next` primary development branch. A pull request is created for this. + * @returns a boolean indicating successful creation of the cherry-pick pull request. + */ + protected async cherryPickChangelogIntoNextBranch( + newVersion: semver.SemVer, stagingBranch: string): Promise { + const nextBranch = this.active.next.branchName; + const commitMessage = getReleaseNoteCherryPickCommitMessage(newVersion); + + // Checkout the next branch. + await this.checkoutUpstreamBranch(nextBranch); + + // Cherry-pick the release notes into the current branch. If it fails, + // ask the user to manually copy the release notes into the next branch. + if (!await this.createCherryPickReleaseNotesCommitFrom(newVersion, stagingBranch)) { + error(yellow(` ✘ Could not cherry-pick release notes for v${newVersion}.`)); + error( + yellow(` Please copy the release notes manually into the "${nextBranch}" branch.`)); + return false; + } + + // Create a cherry-pick pull request that should be merged by the caretaker. + const {url} = await this.pushChangesToForkAndCreatePullRequest( + nextBranch, `changelog-cherry-pick-${newVersion}`, commitMessage, + `Cherry-picks the changelog from the "${stagingBranch}" branch to the next ` + + `branch (${nextBranch}).`); + + info(green( + ` ✓ Pull request for cherry-picking the changelog into "${nextBranch}" ` + + 'has been created.')); + info(yellow(` Please ask team members to review: ${url}.`)); + return true; + } + + /** + * Creates a Github release for the specified version in the configured project. + * The release is created by tagging the specified commit SHA. + */ + private async _createGithubReleaseForVersion( + newVersion: semver.SemVer, versionBumpCommitSha: string) { + const tagName = newVersion.format(); + await this.git.github.git.createRef({ + ...this.git.remoteParams, + ref: `refs/tags/${tagName}`, + sha: versionBumpCommitSha, + }); + info(green(` ✓ Tagged v${newVersion} release upstream.`)); + + await this.git.github.repos.createRelease({ + ...this.git.remoteParams, + name: `v${newVersion}`, + tag_name: tagName, + }); + info(green(` ✓ Created v${newVersion} release in Github.`)); + } + + /** + * Builds and publishes the given version in the specified branch. + * @param newVersion The new version to be published. + * @param publishBranch Name of the branch that contains the new version. + * @param npmDistTag NPM dist tag where the version should be published to. + */ + protected async buildAndPublish( + newVersion: semver.SemVer, publishBranch: string, npmDistTag: string) { + const versionBumpCommitSha = await this._getCommitOfBranch(publishBranch); + + if (!await this._isCommitForVersionStaging(newVersion, versionBumpCommitSha)) { + error(red(` ✘ Latest commit in "${publishBranch}" branch is not a staging commit.`)); + error(red(' Please make sure the staging pull request has been merged.')); + throw new FatalReleaseActionError(); + } + + // Checkout the publish branch and build the release packages. + await this.checkoutUpstreamBranch(publishBranch); + + // Install the project dependencies for the publish branch, and then build the release + // packages. Note that we do not directly call the build packages function from the release + // config. We only want to build and publish packages that have been configured in the given + // publish branch. e.g. consider we publish patch version and a new package has been + // created in the `next` branch. The new package would not be part of the patch branch, + // so we cannot build and publish it. + await invokeYarnInstallCommand(this.projectDir); + const builtPackages = await invokeReleaseBuildCommand(); + + // Create a Github release for the new version. + await this._createGithubReleaseForVersion(newVersion, versionBumpCommitSha); + + // Walk through all built packages and publish them to NPM. + for (const builtPackage of builtPackages) { + await this._publishBuiltPackageToNpm(builtPackage, npmDistTag); + } + + info(green(' ✓ Published all packages successfully')); + } + + /** Publishes the given built package to NPM with the specified NPM dist tag. */ + private async _publishBuiltPackageToNpm(pkg: BuiltPackage, npmDistTag: string) { + debug(`Starting publish of "${pkg.name}".`); + const spinner = ora().start(`Publishing "${pkg.name}"`); + + try { + await runNpmPublish(pkg.outputPath, npmDistTag, this.config.publishRegistry); + spinner.stop(); + info(green(` ✓ Successfully published "${pkg.name}.`)); + } catch (e) { + spinner.stop(); + error(e); + error(red(` ✘ An error occurred while publishing "${pkg.name}".`)); + throw new FatalReleaseActionError(); + } + } + + /** Checks whether the given commit represents a staging commit for the specified version. */ + private async _isCommitForVersionStaging(version: semver.SemVer, commitSha: string) { + const {data} = + await this.git.github.repos.getCommit({...this.git.remoteParams, ref: commitSha}); + return data.commit.message.startsWith(getCommitMessageForRelease(version)); + } +} diff --git a/dev-infra/release/publish/actions/configure-next-as-major.ts b/dev-infra/release/publish/actions/configure-next-as-major.ts new file mode 100644 index 0000000000000..b4ced15a52009 --- /dev/null +++ b/dev-infra/release/publish/actions/configure-next-as-major.ts @@ -0,0 +1,53 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as semver from 'semver'; + +import {green, info, yellow} from '../../../utils/console'; +import {ActiveReleaseTrains} from '../../versioning/active-release-trains'; +import {ReleaseAction} from '../actions'; +import {getCommitMessageForNextBranchMajorSwitch} from '../commit-message'; +import {packageJsonPath} from '../constants'; + +/** + * Release action that configures the active next release-train to be for a major + * version. This means that major changes can land in the next branch. + */ +export class ConfigureNextAsMajorAction extends ReleaseAction { + private _newVersion = semver.parse(`${this.active.next.version.major + 1}.0.0-next.0`)!; + + async getDescription() { + const {branchName} = this.active.next; + const newVersion = this._newVersion; + return `Configure the "${branchName}" branch to be released as major (v${newVersion}).`; + } + + async perform() { + const {branchName} = this.active.next; + const newVersion = this._newVersion; + + await this.verifyPassingGithubStatus(branchName); + await this.checkoutUpstreamBranch(branchName); + await this.updateProjectVersion(newVersion); + await this.createCommit( + getCommitMessageForNextBranchMajorSwitch(newVersion), [packageJsonPath]); + const pullRequest = await this.pushChangesToForkAndCreatePullRequest( + branchName, `switch-next-to-major-${newVersion}`, + `Configure next branch to receive major changes for v${newVersion}`); + + info(green(' ✓ Next branch update pull request has been created.')); + info(yellow(` Please ask team members to review: ${pullRequest.url}.`)); + } + + static async isActive(active: ActiveReleaseTrains) { + // The `next` branch can always be switched to a major version, unless it already + // is targeting a new major. A major can contain minor changes, so we can always + // change the target from a minor to a major. + return !active.next.isMajor; + } +} diff --git a/dev-infra/release/publish/actions/cut-lts-patch.ts b/dev-infra/release/publish/actions/cut-lts-patch.ts new file mode 100644 index 0000000000000..a3593f4929df8 --- /dev/null +++ b/dev-infra/release/publish/actions/cut-lts-patch.ts @@ -0,0 +1,93 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {ListChoiceOptions, prompt} from 'inquirer'; +import * as semver from 'semver'; + +import {ActiveReleaseTrains} from '../../versioning/active-release-trains'; +import {semverInc} from '../../versioning/inc-semver'; +import {fetchLongTermSupportBranchesFromNpm} from '../../versioning/long-term-support'; +import {ReleaseAction} from '../actions'; + +/** Interface describing an LTS version branch. */ +interface LtsBranch { + /** Name of the branch. */ + name: string; + /** Most recent version for the given LTS branch. */ + version: semver.SemVer; + /** NPM dist tag for the LTS version. */ + npmDistTag: string; +} + +/** + * Release action that cuts a new patch release for an active release-train in the long-term + * support phase. The patch segment is incremented. The changelog is generated for the new + * patch version, but also needs to be cherry-picked into the next development branch. + */ +export class CutLongTermSupportPatchAction extends ReleaseAction { + /** Promise resolving an object describing long-term support branches. */ + ltsBranches = fetchLongTermSupportBranchesFromNpm(this.config); + + async getDescription() { + const {active} = await this.ltsBranches; + return `Cut a new release for an active LTS branch (${active.length} active).`; + } + + async perform() { + const ltsBranch = await this._promptForTargetLtsBranch(); + const newVersion = semverInc(ltsBranch.version, 'patch'); + const {id} = await this.checkoutBranchAndStageVersion(newVersion, ltsBranch.name); + + await this.waitForPullRequestToBeMerged(id); + await this.buildAndPublish(newVersion, ltsBranch.name, ltsBranch.npmDistTag); + await this.cherryPickChangelogIntoNextBranch(newVersion, ltsBranch.name); + } + + /** Prompts the user to select an LTS branch for which a patch should but cut. */ + private async _promptForTargetLtsBranch(): Promise { + const {active, inactive} = await this.ltsBranches; + const activeBranchChoices = active.map(branch => this._getChoiceForLtsBranch(branch)); + + // If there are inactive LTS branches, we allow them to be selected. In some situations, + // patch releases are still cut for inactive LTS branches. e.g. when the LTS duration + // has been increased due to exceptional events () + if (inactive.length !== 0) { + activeBranchChoices.push({name: 'Inactive LTS versions (not recommended)', value: null}); + } + + const {activeLtsBranch, inactiveLtsBranch} = + await prompt<{activeLtsBranch: LtsBranch | null, inactiveLtsBranch: LtsBranch}>([ + { + name: 'activeLtsBranch', + type: 'list', + message: 'Please select a version for which you want to cut an LTS patch', + choices: activeBranchChoices, + }, + { + name: 'inactiveLtsBranch', + type: 'list', + when: o => o.activeLtsBranch === null, + message: 'Please select an inactive LTS version for which you want to cut an LTS patch', + choices: inactive.map(branch => this._getChoiceForLtsBranch(branch)), + } + ]); + return activeLtsBranch ?? inactiveLtsBranch; + } + + /** Gets an inquirer choice for the given LTS branch. */ + private _getChoiceForLtsBranch(branch: LtsBranch): ListChoiceOptions { + return {name: `v${branch.version.major} (from ${branch.name})`, value: branch}; + } + + static async isActive(active: ActiveReleaseTrains) { + // LTS patch versions can be only cut if there are release trains in LTS phase. + // This action is always selectable as we support publishing of old LTS branches, + // and have prompt for selecting an LTS branch when the action performs. + return true; + } +} diff --git a/dev-infra/release/publish/actions/cut-new-patch.ts b/dev-infra/release/publish/actions/cut-new-patch.ts new file mode 100644 index 0000000000000..fe8d79203f078 --- /dev/null +++ b/dev-infra/release/publish/actions/cut-new-patch.ts @@ -0,0 +1,43 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {ActiveReleaseTrains} from '../../versioning/active-release-trains'; +import {semverInc} from '../../versioning/inc-semver'; +import {ReleaseAction} from '../actions'; + +/** + * Release action that cuts a new patch release for the current latest release-train version + * branch (i.e. the patch branch). The patch segment is incremented. The changelog is generated + * for the new patch version, but also needs to be cherry-picked into the next development branch. + */ +export class CutNewPatchAction extends ReleaseAction { + private _newVersion = semverInc(this.active.latest.version, 'patch'); + + async getDescription() { + const {branchName} = this.active.latest; + const newVersion = this._newVersion; + return `Cut a new patch release for the "${branchName}" branch (v${newVersion}).`; + } + + async perform() { + const {branchName} = this.active.latest; + const newVersion = this._newVersion; + + const {id} = await this.checkoutBranchAndStageVersion(newVersion, branchName); + + await this.waitForPullRequestToBeMerged(id); + await this.buildAndPublish(newVersion, branchName, 'latest'); + await this.cherryPickChangelogIntoNextBranch(newVersion, branchName); + } + + static async isActive(active: ActiveReleaseTrains) { + // Patch versions can be cut at any time. See: + // https://hackmd.io/2Le8leq0S6G_R5VEVTNK9A#Release-prompt-options. + return true; + } +} diff --git a/dev-infra/release/publish/actions/cut-next-prerelease.ts b/dev-infra/release/publish/actions/cut-next-prerelease.ts new file mode 100644 index 0000000000000..40ecb20fd1c41 --- /dev/null +++ b/dev-infra/release/publish/actions/cut-next-prerelease.ts @@ -0,0 +1,72 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as semver from 'semver'; + +import {semverInc} from '../../versioning/inc-semver'; +import {computeNewPrereleaseVersionForNext} from '../../versioning/next-prerelease-version'; +import {ReleaseTrain} from '../../versioning/release-trains'; +import {ReleaseAction} from '../actions'; + +/** + * Release action that cuts a prerelease for the next branch. A version in the next + * branch can have an arbitrary amount of next pre-releases. + */ +export class CutNextPrereleaseAction extends ReleaseAction { + /** Promise resolving with the new version if a NPM next pre-release is cut. */ + private _newVersion: Promise = this._computeNewVersion(); + + async getDescription() { + const {branchName} = this._getActivePrereleaseTrain(); + const newVersion = await this._newVersion; + return `Cut a new next pre-release for the "${branchName}" branch (v${newVersion}).`; + } + + async perform() { + const releaseTrain = this._getActivePrereleaseTrain(); + const {branchName} = releaseTrain; + const newVersion = await this._newVersion; + + const {id} = await this.checkoutBranchAndStageVersion(newVersion, branchName); + + await this.waitForPullRequestToBeMerged(id); + await this.buildAndPublish(newVersion, branchName, 'next'); + + // If the pre-release has been cut from a branch that is not corresponding + // to the next release-train, cherry-pick the changelog into the primary + // development branch. i.e. the `next` branch that is usually `master`. + if (releaseTrain !== this.active.next) { + await this.cherryPickChangelogIntoNextBranch(newVersion, branchName); + } + } + + /** Gets the release train for which NPM next pre-releases should be cut. */ + private _getActivePrereleaseTrain(): ReleaseTrain { + return this.active.releaseCandidate ?? this.active.next; + } + + /** Gets the new pre-release version for this release action. */ + private async _computeNewVersion(): Promise { + const releaseTrain = this._getActivePrereleaseTrain(); + // If a pre-release is cut for the next release-train, the new version is computed + // with respect to special cases surfacing with FF/RC branches. Otherwise, the basic + // pre-release increment of the version is used as new version. + if (releaseTrain === this.active.next) { + return await computeNewPrereleaseVersionForNext(this.active, this.config); + } else { + return semverInc(releaseTrain.version, 'prerelease'); + } + } + + static async isActive() { + // Pre-releases for the `next` NPM dist tag can always be cut. Depending on whether + // there is a feature-freeze/release-candidate branch, the next pre-releases are either + // cut from such a branch, or from the actual `next` release-train branch (i.e. master). + return true; + } +} diff --git a/dev-infra/release/publish/actions/cut-release-candidate.ts b/dev-infra/release/publish/actions/cut-release-candidate.ts new file mode 100644 index 0000000000000..716446a1eef65 --- /dev/null +++ b/dev-infra/release/publish/actions/cut-release-candidate.ts @@ -0,0 +1,42 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {ActiveReleaseTrains} from '../../versioning/active-release-trains'; +import {semverInc} from '../../versioning/inc-semver'; +import {ReleaseAction} from '../actions'; + +/** + * Cuts the first release candidate for a release-train currently in the + * feature-freeze phase. The version is bumped from `next` to `rc.0`. + */ +export class CutReleaseCandidateAction extends ReleaseAction { + private _newVersion = semverInc(this.active.releaseCandidate!.version, 'prerelease', 'rc'); + + async getDescription() { + const newVersion = this._newVersion; + return `Cut a first release-candidate for the feature-freeze branch (v${newVersion}).`; + } + + async perform() { + const {branchName} = this.active.releaseCandidate!; + const newVersion = this._newVersion; + + const {id} = await this.checkoutBranchAndStageVersion(newVersion, branchName); + + await this.waitForPullRequestToBeMerged(id); + await this.buildAndPublish(newVersion, branchName, 'next'); + await this.cherryPickChangelogIntoNextBranch(newVersion, branchName); + } + + static async isActive(active: ActiveReleaseTrains) { + // A release-candidate can be cut for an active release-train currently + // in the feature-freeze phase. + return active.releaseCandidate !== null && + active.releaseCandidate.version.prerelease[0] === 'next'; + } +} diff --git a/dev-infra/release/publish/actions/cut-stable.ts b/dev-infra/release/publish/actions/cut-stable.ts new file mode 100644 index 0000000000000..dee7e88ee875e --- /dev/null +++ b/dev-infra/release/publish/actions/cut-stable.ts @@ -0,0 +1,71 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as semver from 'semver'; + +import {ActiveReleaseTrains} from '../../versioning/active-release-trains'; +import {getLtsNpmDistTagOfMajor} from '../../versioning/long-term-support'; +import {ReleaseAction} from '../actions'; +import {invokeSetNpmDistCommand, invokeYarnInstallCommand} from '../external-commands'; + +/** + * Release action that cuts a stable version for the current release-train in the release + * candidate phase. The pre-release release-candidate version label is removed. + */ +export class CutStableAction extends ReleaseAction { + private _newVersion = this._computeNewVersion(); + + async getDescription() { + const newVersion = this._newVersion; + return `Cut a stable release for the release-candidate branch (v${newVersion}).`; + } + + async perform() { + const {branchName} = this.active.releaseCandidate!; + const newVersion = this._newVersion; + const isNewMajor = this.active.releaseCandidate?.isMajor; + + + const {id} = await this.checkoutBranchAndStageVersion(newVersion, branchName); + + await this.waitForPullRequestToBeMerged(id); + await this.buildAndPublish(newVersion, branchName, 'latest'); + + // If a new major version is published and becomes the "latest" release-train, we need + // to set the LTS npm dist tag for the previous latest release-train (the current patch). + if (isNewMajor) { + const previousPatchVersion = this.active.latest.version; + const ltsTagForPatch = getLtsNpmDistTagOfMajor(previousPatchVersion.major); + + // Instead of directly setting the NPM dist tags, we invoke the ng-dev command for + // setting the NPM dist tag to the specified version. We do this because release NPM + // packages could be different in the previous patch branch, and we want to set the + // LTS tag for all packages part of the last major. It would not be possible to set the + // NPM dist tag for new packages part of the released major, nor would it be acceptable + // to skip the LTS tag for packages which are no longer part of the new major. + await invokeYarnInstallCommand(this.projectDir); + await invokeSetNpmDistCommand(ltsTagForPatch, previousPatchVersion); + } + + await this.cherryPickChangelogIntoNextBranch(newVersion, branchName); + } + + /** Gets the new stable version of the release candidate release-train. */ + private _computeNewVersion(): semver.SemVer { + const {version} = this.active.releaseCandidate!; + return semver.parse(`${version.major}.${version.minor}.${version.patch}`)!; + } + + static async isActive(active: ActiveReleaseTrains) { + // A stable version can be cut for an active release-train currently in the + // release-candidate phase. Note: It is not possible to directly release from + // feature-freeze phase into a stable version. + return active.releaseCandidate !== null && + active.releaseCandidate.version.prerelease[0] === 'rc'; + } +} diff --git a/dev-infra/release/publish/actions/index.ts b/dev-infra/release/publish/actions/index.ts new file mode 100644 index 0000000000000..85ad7ba1566cd --- /dev/null +++ b/dev-infra/release/publish/actions/index.ts @@ -0,0 +1,29 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {ReleaseActionConstructor} from '../actions'; + +import {CutLongTermSupportPatchAction} from './cut-lts-patch'; +import {CutNewPatchAction} from './cut-new-patch'; +import {CutNextPrereleaseAction} from './cut-next-prerelease'; +import {CutReleaseCandidateAction} from './cut-release-candidate'; +import {CutStableAction} from './cut-stable'; +import {MoveNextIntoFeatureFreezeAction} from './move-next-into-feature-freeze'; + +/** + * List of release actions supported by the release staging tool. These are sorted + * by priority. Actions which are selectable are sorted based on this declaration order. + */ +export const actions: ReleaseActionConstructor[] = [ + CutStableAction, + CutReleaseCandidateAction, + CutNewPatchAction, + CutNextPrereleaseAction, + MoveNextIntoFeatureFreezeAction, + CutLongTermSupportPatchAction, +]; diff --git a/dev-infra/release/publish/actions/move-next-into-feature-freeze.ts b/dev-infra/release/publish/actions/move-next-into-feature-freeze.ts new file mode 100644 index 0000000000000..0ecf6322270f2 --- /dev/null +++ b/dev-infra/release/publish/actions/move-next-into-feature-freeze.ts @@ -0,0 +1,109 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as semver from 'semver'; + +import {error, green, info, yellow} from '../../../utils/console'; +import {ActiveReleaseTrains} from '../../versioning/active-release-trains'; +import {computeNewPrereleaseVersionForNext} from '../../versioning/next-prerelease-version'; +import {ReleaseAction} from '../actions'; +import {getCommitMessageForExceptionalNextVersionBump} from '../commit-message'; +import {packageJsonPath} from '../constants'; + +/** + * Release action that moves the next release-train into the feature-freeze phase. This means + * that a new version branch is created from the next branch, and a new next pre-release is + * cut indicating the started feature-freeze. + */ +export class MoveNextIntoFeatureFreezeAction extends ReleaseAction { + private _newVersion = computeNewPrereleaseVersionForNext(this.active, this.config); + + async getDescription() { + const {branchName} = this.active.next; + const newVersion = await this._newVersion; + return `Move the "${branchName}" branch into feature-freeze phase (v${newVersion}).`; + } + + async perform() { + const newVersion = await this._newVersion; + const newBranch = `${newVersion.major}.${newVersion.minor}.x`; + + // Branch-off the next branch into a feature-freeze branch. + await this._createNewVersionBranchFromNext(newBranch); + + // Stage the new version for the newly created branch, and push changes to a + // fork in order to create a staging pull request. Note that we re-use the newly + // created branch instead of re-fetching from the upstream. + const stagingPullRequest = + await this.stageVersionForBranchAndCreatePullRequest(newVersion, newBranch); + + // Wait for the staging PR to be merged. Then build and publish the feature-freeze next + // pre-release. Finally, cherry-pick the release notes into the next branch in combination + // with bumping the version to the next minor too. + await this.waitForPullRequestToBeMerged(stagingPullRequest.id); + await this.buildAndPublish(newVersion, newBranch, 'next'); + await this._createNextBranchUpdatePullRequest(newVersion, newBranch); + } + + /** Creates a new version branch from the next branch. */ + private async _createNewVersionBranchFromNext(newBranch: string) { + const {branchName: nextBranch} = this.active.next; + await this.verifyPassingGithubStatus(nextBranch); + await this.checkoutUpstreamBranch(nextBranch); + await this.createLocalBranchFromHead(newBranch); + await this.pushHeadToRemoteBranch(newBranch); + info(green(` ✓ Version branch "${newBranch}" created.`)); + } + + /** + * Creates a pull request for the next branch that bumps the version to the next + * minor, and cherry-picks the changelog for the newly branched-off feature-freeze version. + */ + private async _createNextBranchUpdatePullRequest(newVersion: semver.SemVer, newBranch: string) { + const {branchName: nextBranch, version} = this.active.next; + // We increase the version for the next branch to the next minor. The team can decide + // later if they want next to be a major through the `Configure Next as Major` release action. + const newNextVersion = semver.parse(`${version.major}.${version.minor + 1}.0-next.0`)!; + const bumpCommitMessage = getCommitMessageForExceptionalNextVersionBump(newNextVersion); + + await this.checkoutUpstreamBranch(nextBranch); + await this.updateProjectVersion(newNextVersion); + + // Create an individual commit for the next version bump. The changelog should go into + // a separate commit that makes it clear where the changelog is cherry-picked from. + await this.createCommit(bumpCommitMessage, [packageJsonPath]); + + let nextPullRequestMessage = `The previous "next" release-train has moved into the ` + + `release-candidate phase. This PR updates the next branch to the subsequent ` + + `release-train.`; + const hasChangelogCherryPicked = + await this.createCherryPickReleaseNotesCommitFrom(newVersion, newBranch); + + if (hasChangelogCherryPicked) { + nextPullRequestMessage += `\n\nAlso this PR cherry-picks the changelog for ` + + `v${newVersion} into the ${nextBranch} branch so that the changelog is up to date.`; + } else { + error(yellow(` ✘ Could not cherry-pick release notes for v${newVersion}.`)); + error(yellow(` Please copy the release note manually into "${nextBranch}".`)); + } + + const nextUpdatePullRequest = await this.pushChangesToForkAndCreatePullRequest( + nextBranch, `next-release-train-${newNextVersion}`, + `Update next branch to reflect new release-train "v${newNextVersion}".`, + nextPullRequestMessage); + + info(green(` ✓ Pull request for updating the "${nextBranch}" branch has been created.`)); + info(yellow(` Please ask team members to review: ${nextUpdatePullRequest.url}.`)); + } + + static async isActive(active: ActiveReleaseTrains) { + // A new feature-freeze/release-candidate branch can only be created if there + // is no active release-train in feature-freeze/release-candidate phase. + return active.releaseCandidate === null; + } +} diff --git a/dev-infra/release/publish/cli.ts b/dev-infra/release/publish/cli.ts new file mode 100644 index 0000000000000..5a61dd8072559 --- /dev/null +++ b/dev-infra/release/publish/cli.ts @@ -0,0 +1,56 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {Arguments, Argv, CommandModule} from 'yargs'; + +import {getConfig, getRepoBaseDir} from '../../utils/config'; +import {error, green, info, red, yellow} from '../../utils/console'; +import {addGithubTokenOption} from '../../utils/git/github-yargs'; +import {getReleaseConfig} from '../config'; + +import {CompletionState, ReleaseTool} from './index'; + +/** Command line options for publishing a release. */ +export interface ReleasePublishOptions { + githubToken: string; +} + +/** Yargs command builder for configuring the `ng-dev release publish` command. */ +function builder(argv: Argv): Argv { + return addGithubTokenOption(argv); +} + +/** Yargs command handler for staging a release. */ +async function handler(args: Arguments) { + const config = getConfig(); + const releaseConfig = getReleaseConfig(config); + const projectDir = getRepoBaseDir(); + const task = new ReleaseTool(releaseConfig, config.github, args.githubToken, projectDir); + const result = await task.run(); + + switch (result) { + case CompletionState.FATAL_ERROR: + error(red(`Release action has been aborted due to fatal errors. See above.`)); + process.exitCode = 1; + break; + case CompletionState.MANUALLY_ABORTED: + info(yellow(`Release action has been manually aborted.`)); + break; + case CompletionState.SUCCESS: + info(green(`Release action has completed successfully.`)); + break; + } +} + +/** CLI command module for publishing a release. */ +export const ReleasePublishCommandModule: CommandModule<{}, ReleasePublishOptions> = { + builder, + handler, + command: 'publish', + describe: 'Publish new releases and configure version branches.', +}; diff --git a/dev-infra/release/publish/commit-message.ts b/dev-infra/release/publish/commit-message.ts new file mode 100644 index 0000000000000..a4bc73aa2c3cb --- /dev/null +++ b/dev-infra/release/publish/commit-message.ts @@ -0,0 +1,39 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as semver from 'semver'; + +/** Gets the commit message for a new release point in the project. */ +export function getCommitMessageForRelease(newVersion: semver.SemVer): string { + return `release: cut the v${newVersion} release`; +} + +/** + * Gets the commit message for an exceptional version bump in the next branch. The next + * branch version will be bumped without the release being published in some situations. + * More details can be found in the `MoveNextIntoFeatureFreeze` release action and in: + * https://hackmd.io/2Le8leq0S6G_R5VEVTNK9A. + */ +export function getCommitMessageForExceptionalNextVersionBump(newVersion: semver.SemVer) { + return `release: bump the next branch to v${newVersion}`; +} + +/** + * Gets the commit message for a version update in the next branch to a major version. The next + * branch version will be updated without the release being published if the branch is configured + * as a major. More details can be found in the `ConfigureNextAsMajor` release action and in: + * https://hackmd.io/2Le8leq0S6G_R5VEVTNK9A. + */ +export function getCommitMessageForNextBranchMajorSwitch(newVersion: semver.SemVer) { + return `release: switch the next branch to v${newVersion}`; +} + +/** Gets the commit message for a release notes cherry-pick commit */ +export function getReleaseNoteCherryPickCommitMessage(newVersion: semver.SemVer): string { + return `docs: release notes for the v${newVersion} release`; +} diff --git a/dev-infra/release/publish/constants.ts b/dev-infra/release/publish/constants.ts new file mode 100644 index 0000000000000..f108f0abf1743 --- /dev/null +++ b/dev-infra/release/publish/constants.ts @@ -0,0 +1,16 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +/** Project-relative path for the changelog file. */ +export const changelogPath = 'CHANGELOG.md'; + +/** Project-relative path for the "package.json" file. */ +export const packageJsonPath = 'package.json'; + +/** Default interval in milliseconds to check whether a pull request has been merged. */ +export const waitForPullRequestInterval = 10000; diff --git a/dev-infra/release/publish/external-commands.ts b/dev-infra/release/publish/external-commands.ts new file mode 100644 index 0000000000000..8b27c14f311fc --- /dev/null +++ b/dev-infra/release/publish/external-commands.ts @@ -0,0 +1,92 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as ora from 'ora'; +import * as semver from 'semver'; + +import {spawnWithDebugOutput} from '../../utils/child-process'; +import {error, green, info, red} from '../../utils/console'; +import {BuiltPackage} from '../config/index'; + +import {FatalReleaseActionError} from './actions-error'; + +/* + * ############################################################### + * + * This file contains helpers for invoking external `ng-dev` commands. A subset of actions, + * like building release output or setting aν NPM dist tag for release packages, cannot be + * performed directly as part of the release tool and need to be delegated to external `ng-dev` + * commands that exist across arbitrary version branches. + * + * In a concrete example: Consider a new patch version is released and that a new release + * package has been added to the `next` branch. The patch branch will not contain the new + * release package, so we could not build the release output for it. To work around this, we + * call the ng-dev build command for the patch version branch and expect it to return a list + * of built packages that need to be released as part of this release train. + * + * ############################################################### + */ + +/** + * Invokes the `ng-dev release set-dist-tag` command in order to set the specified + * NPM dist tag for all packages in the checked out branch to the given version. + */ +export async function invokeSetNpmDistCommand(npmDistTag: string, version: semver.SemVer) { + try { + // Note: No progress indicator needed as that is the responsibility of the command. + await spawnWithDebugOutput( + 'yarn', ['--silent', 'ng-dev', 'release', 'set-dist-tag', npmDistTag, version.format()]); + info(green(` ✓ Set "${npmDistTag}" NPM dist tag for all packages to v${version}.`)); + } catch (e) { + error(e); + error(red(` ✘ An error occurred while setting the NPM dist tag for "${npmDistTag}".`)); + throw new FatalReleaseActionError(); + } +} + +/** + * Invokes the `ng-dev release build` command in order to build the release + * packages for the currently checked out branch. + */ +export async function invokeReleaseBuildCommand(): Promise { + const spinner = ora().start('Building release output.'); + try { + // Since we expect JSON to be printed from the `ng-dev release build` command, + // we spawn the process in silent mode. We have set up an Ora progress spinner. + const {stdout} = await spawnWithDebugOutput( + 'yarn', ['--silent', 'ng-dev', 'release', 'build', '--json'], {mode: 'silent'}); + spinner.stop(); + info(green(' ✓ Built release output for all packages.')); + // The `ng-dev release build` command prints a JSON array to stdout + // that represents the built release packages and their output paths. + return JSON.parse(stdout.trim()); + } catch (e) { + spinner.stop(); + error(e); + error(red(' ✘ An error occurred while building the release packages.')); + throw new FatalReleaseActionError(); + } +} + +/** + * Invokes the `yarn install` command in order to install dependencies for + * the configured project with the currently checked out revision. + */ +export async function invokeYarnInstallCommand(projectDir: string): Promise { + try { + // Note: No progress indicator needed as that is the responsibility of the command. + // TODO: Consider using an Ora spinner instead to ensure minimal console output. + await spawnWithDebugOutput( + 'yarn', ['install', '--frozen-lockfile', '--non-interactive'], {cwd: projectDir}); + info(green(' ✓ Installed project dependencies.')); + } catch (e) { + error(e); + error(red(' ✘ An error occurred while installing dependencies.')); + throw new FatalReleaseActionError(); + } +} diff --git a/dev-infra/release/publish/graphql-queries.ts b/dev-infra/release/publish/graphql-queries.ts new file mode 100644 index 0000000000000..63679d7a77bd5 --- /dev/null +++ b/dev-infra/release/publish/graphql-queries.ts @@ -0,0 +1,31 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {params, types} from 'typed-graphqlify'; + +/** + * Graphql Github API query that can be used to find forks of a given repository + * that are owned by the current viewer authenticated with the Github API. + */ +export const findOwnedForksOfRepoQuery = params( + { + $owner: 'String!', + $name: 'String!', + }, + { + repository: params({owner: '$owner', name: '$name'}, { + forks: params({affiliations: 'OWNER', first: 1}, { + nodes: [{ + owner: { + login: types.string, + }, + name: types.string, + }], + }), + }), + }); diff --git a/dev-infra/release/publish/index.ts b/dev-infra/release/publish/index.ts new file mode 100644 index 0000000000000..99c999c1679df --- /dev/null +++ b/dev-infra/release/publish/index.ts @@ -0,0 +1,132 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {ListChoiceOptions, prompt} from 'inquirer'; + +import {GithubConfig} from '../../utils/config'; +import {error, info, log, red, yellow} from '../../utils/console'; +import {GitClient} from '../../utils/git/index'; +import {ReleaseConfig} from '../config'; +import {ActiveReleaseTrains, fetchActiveReleaseTrains, nextBranchName} from '../versioning/active-release-trains'; +import {printActiveReleaseTrains} from '../versioning/print-active-trains'; +import {GithubRepoWithApi} from '../versioning/version-branches'; + +import {ReleaseAction} from './actions'; +import {FatalReleaseActionError, UserAbortedReleaseActionError} from './actions-error'; +import {actions} from './actions/index'; + +export enum CompletionState { + SUCCESS, + FATAL_ERROR, + MANUALLY_ABORTED, +} + +export class ReleaseTool { + /** Client for interacting with the Github API and the local Git command. */ + private _git = new GitClient(this._githubToken, {github: this._github}, this._projectRoot); + + constructor( + protected _config: ReleaseConfig, protected _github: GithubConfig, + protected _githubToken: string, protected _projectRoot: string) {} + + /** Runs the interactive release tool. */ + async run(): Promise { + log(); + log(yellow('--------------------------------------------')); + log(yellow(' Angular Dev-Infra release staging script')); + log(yellow('--------------------------------------------')); + log(); + + if (!await this._verifyNoUncommittedChanges() || !await this._verifyRunningFromNextBranch()) { + return CompletionState.FATAL_ERROR; + } + + const {owner, name} = this._github; + const repo: GithubRepoWithApi = {owner, name, api: this._git.github}; + const releaseTrains = await fetchActiveReleaseTrains(repo); + + // Print the active release trains so that the caretaker can access + // the current project branching state without switching context. + await printActiveReleaseTrains(releaseTrains, this._config); + + const action = await this._promptForReleaseAction(releaseTrains); + const previousGitBranchOrRevision = this._git.getCurrentBranchOrRevision(); + + try { + await action.perform(); + } catch (e) { + if (e instanceof UserAbortedReleaseActionError) { + return CompletionState.MANUALLY_ABORTED; + } + // Only print the error message and stack if the error is not a known fatal release + // action error (for which we print the error gracefully to the console with colors). + if (!(e instanceof FatalReleaseActionError) && e instanceof Error) { + console.error(e); + } + return CompletionState.FATAL_ERROR; + } finally { + this._git.checkout(previousGitBranchOrRevision, true); + } + + return CompletionState.SUCCESS; + } + + /** Prompts the caretaker for a release action that should be performed. */ + private async _promptForReleaseAction(activeTrains: ActiveReleaseTrains) { + const choices: ListChoiceOptions[] = []; + + // Find and instantiate all release actions which are currently valid. + for (let actionType of actions) { + if (await actionType.isActive(activeTrains)) { + const action: ReleaseAction = + new actionType(activeTrains, this._git, this._config, this._projectRoot); + choices.push({name: await action.getDescription(), value: action}); + } + } + + info('Please select the type of release you want to perform.'); + + const {releaseAction} = await prompt<{releaseAction: ReleaseAction}>({ + name: 'releaseAction', + message: 'Please select an action:', + type: 'list', + choices, + }); + + return releaseAction; + } + + /** + * Verifies that there are no uncommitted changes in the project. + * @returns a boolean indicating success or failure. + */ + private async _verifyNoUncommittedChanges(): Promise { + if (this._git.hasUncommittedChanges()) { + error(red(' ✘ There are changes which are not committed and should be discarded.')); + return false; + } + return true; + } + + /** + * Verifies that the next branch from the configured repository is checked out. + * @returns a boolean indicating success or failure. + */ + private async _verifyRunningFromNextBranch(): Promise { + const headSha = this._git.run(['rev-parse', 'HEAD']).stdout.trim(); + const {data} = + await this._git.github.repos.getBranch({...this._git.remoteParams, branch: nextBranchName}); + + if (headSha !== data.commit.sha) { + error(red(' ✘ Running release tool from an outdated local branch.')); + error(red(` Please make sure you are running from the "${nextBranchName}" branch.`)); + return false; + } + return true; + } +} diff --git a/dev-infra/release/publish/pull-request-state.ts b/dev-infra/release/publish/pull-request-state.ts new file mode 100644 index 0000000000000..9f318ee406b72 --- /dev/null +++ b/dev-infra/release/publish/pull-request-state.ts @@ -0,0 +1,73 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as Octokit from '@octokit/rest'; +import {GitClient} from '../../utils/git/index'; + +/** State of a pull request in Github. */ +export type PullRequestState = 'merged'|'closed'|'open'; + +/** Gets whether a given pull request has been merged. */ +export async function getPullRequestState(api: GitClient, id: number): Promise { + const {data} = await api.github.pulls.get({...api.remoteParams, pull_number: id}); + if (data.merged) { + return 'merged'; + } else if (data.closed_at !== null) { + return await isPullRequestClosedWithAssociatedCommit(api, id) ? 'merged' : 'closed'; + } else { + return 'open'; + } +} + +/** + * Whether the pull request has been closed with an associated commit. This is usually + * the case if a PR has been merged using the autosquash merge script strategy. Since + * the merge is not fast-forward, Github does not consider the PR as merged and instead + * shows the PR as closed. See for example: https://github.com/angular/angular/pull/37918. + */ +async function isPullRequestClosedWithAssociatedCommit(api: GitClient, id: number) { + const request = + api.github.issues.listEvents.endpoint.merge({...api.remoteParams, issue_number: id}); + const events: Octokit.IssuesListEventsResponse = await api.github.paginate(request); + // Iterate through the events of the pull request in reverse. We want to find the most + // recent events and check if the PR has been closed with a commit associated with it. + // If the PR has been closed through a commit, we assume that the PR has been merged + // using the autosquash merge strategy. For more details. See the `AutosquashMergeStrategy`. + for (let i = events.length - 1; i >= 0; i--) { + const {event, commit_id} = events[i]; + // If we come across a "reopened" event, we abort looking for referenced commits. Any + // commits that closed the PR before, are no longer relevant and did not close the PR. + if (event === 'reopened') { + return false; + } + // If a `closed` event is captured with a commit assigned, then we assume that + // this PR has been merged properly. + if (event === 'closed' && commit_id) { + return true; + } + // If the PR has been referenced by a commit, check if the commit closes this pull + // request. Note that this is needed besides checking `closed` as PRs could be merged + // into any non-default branch where the `Closes <..>` keyword does not work and the PR + // is simply closed without an associated `commit_id`. For more details see: + // https://docs.github.com/en/enterprise/2.16/user/github/managing-your-work-on-github/closing-issues-using-keywords#:~:text=non-default. + if (event === 'referenced' && commit_id && + await isCommitClosingPullRequest(api, commit_id, id)) { + return true; + } + } + return false; +} + +/** Checks whether the specified commit is closing the given pull request. */ +async function isCommitClosingPullRequest(api: GitClient, sha: string, id: number) { + const {data} = await api.github.repos.getCommit({...api.remoteParams, ref: sha}); + // Matches the closing keyword supported in commit messages. See: + // https://docs.github.com/en/enterprise/2.16/user/github/managing-your-work-on-github/closing-issues-using-keywords. + return data.commit.message.match( + new RegExp(`(?:close[sd]?|fix(?:e[sd]?)|resolve[sd]?):? #${id}(?!\\d)`, 'i')); +} diff --git a/dev-infra/release/publish/release-notes.ts b/dev-infra/release/publish/release-notes.ts new file mode 100644 index 0000000000000..c48d17a554f41 --- /dev/null +++ b/dev-infra/release/publish/release-notes.ts @@ -0,0 +1,27 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {join} from 'path'; +import * as semver from 'semver'; +import {changelogPath} from './constants'; + +/** + * Gets the default pattern for extracting release notes for the given version. + * This pattern matches for the conventional-changelog Angular preset. + */ +export function getDefaultExtractReleaseNotesPattern(version: semver.SemVer): RegExp { + const escapedVersion = version.format().replace('.', '\\.'); + // TODO: Change this once we have a canonical changelog generation tool. Also update this + // based on the conventional-changelog version. They removed anchors in more recent versions. + return new RegExp(`(.*?)(?: { + const baseReleaseTrains: ActiveReleaseTrains = { + releaseCandidate: null, + next: new ReleaseTrain('master', parse('10.1.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.1')), + }; + + describe('version computation', async () => { + const testReleaseTrain: ActiveReleaseTrains = { + releaseCandidate: new ReleaseTrain('10.1.x', parse('10.1.0-next.3')), + next: new ReleaseTrain('master', parse('10.2.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.1')), + }; + + it('should not modify release train versions and cause invalid other actions', async () => { + const {releaseConfig, gitClient} = getTestingMocksForReleaseAction(); + const descriptions: string[] = []; + + for (const actionCtor of actions) { + if (await actionCtor.isActive(testReleaseTrain)) { + const action = new actionCtor(testReleaseTrain, gitClient, releaseConfig, testTmpDir); + descriptions.push(await action.getDescription()); + } + } + + expect(descriptions).toEqual([ + `Cut a first release-candidate for the feature-freeze branch (v10.1.0-rc.0).`, + `Cut a new patch release for the "10.0.x" branch (v10.0.2).`, + `Cut a new next pre-release for the "10.1.x" branch (v10.1.0-next.4).`, + `Cut a new release for an active LTS branch (0 active).` + ]); + }); + }); + + describe('build and publishing', () => { + it('should support a custom NPM registry', async () => { + const {repo, instance, releaseConfig} = + setupReleaseActionForTesting(TestAction, baseReleaseTrains); + const {version, branchName} = baseReleaseTrains.next; + const tagName = version.format(); + const customRegistryUrl = 'https://custom-npm-registry.google.com'; + + repo.expectBranchRequest(branchName, 'STAGING_SHA') + .expectCommitRequest('STAGING_SHA', `release: cut the v${version} release`) + .expectTagToBeCreated(tagName, 'STAGING_SHA') + .expectReleaseToBeCreated(`v${version}`, tagName); + + // Set up a custom NPM registry. + releaseConfig.publishRegistry = customRegistryUrl; + + await instance.testBuildAndPublish(version, branchName, 'latest'); + + expect(npm.runNpmPublish).toHaveBeenCalledTimes(2); + expect(npm.runNpmPublish) + .toHaveBeenCalledWith(`${testTmpDir}/dist/pkg1`, 'latest', customRegistryUrl); + expect(npm.runNpmPublish) + .toHaveBeenCalledWith(`${testTmpDir}/dist/pkg2`, 'latest', customRegistryUrl); + }); + }); + + describe('changelog cherry-picking', () => { + const {version, branchName} = baseReleaseTrains.latest; + const fakeReleaseNotes = getChangelogForVersion(version.format()); + const forkBranchName = `changelog-cherry-pick-${version}`; + + it('should prepend fetched changelog', async () => { + const {repo, fork, instance, testTmpDir} = + setupReleaseActionForTesting(TestAction, baseReleaseTrains); + + // Expect the changelog to be fetched and return a fake changelog to test that + // it is properly appended. Also expect a pull request to be created in the fork. + repo.expectChangelogFetch(branchName, fakeReleaseNotes) + .expectFindForkRequest(fork) + .expectPullRequestToBeCreated('master', fork, forkBranchName, 200); + + // Simulate that the fork branch name is available. + fork.expectBranchRequest(forkBranchName, null); + + await instance.testCherryPickWithPullRequest(version, branchName); + + const changelogContent = readFileSync(join(testTmpDir, changelogPath), 'utf8'); + expect(changelogContent).toEqual(`${fakeReleaseNotes}Existing changelog`); + }); + + it('should respect a custom release note extraction pattern', async () => { + const {repo, fork, instance, testTmpDir, releaseConfig} = + setupReleaseActionForTesting(TestAction, baseReleaseTrains); + + // Custom pattern matching changelog output sections grouped through + // basic level-1 markdown headers (compared to the default anchor pattern). + releaseConfig.extractReleaseNotesPattern = version => + new RegExp(`(# v${version} \\("[^"]+"\\).*?)(?:# v|$)`, 's'); + + const customReleaseNotes = `# v${version} ("newton-kepler")\n\nNew Content!`; + + // Expect the changelog to be fetched and return a fake changelog to test that + // it is properly appended. Also expect a pull request to be created in the fork. + repo.expectChangelogFetch(branchName, customReleaseNotes) + .expectFindForkRequest(fork) + .expectPullRequestToBeCreated('master', fork, forkBranchName, 200); + + // Simulate that the fork branch name is available. + fork.expectBranchRequest(forkBranchName, null); + + await instance.testCherryPickWithPullRequest(version, branchName); + + const changelogContent = readFileSync(join(testTmpDir, changelogPath), 'utf8'); + expect(changelogContent).toEqual(`${customReleaseNotes}\n\nExisting changelog`); + }); + + it('should print an error if release notes cannot be extracted', async () => { + const {repo, fork, instance, testTmpDir, releaseConfig} = + setupReleaseActionForTesting(TestAction, baseReleaseTrains); + + // Expect the changelog to be fetched and return a fake changelog to test that + // it is properly appended. Also expect a pull request to be created in the fork. + repo.expectChangelogFetch(branchName, `non analyzable changelog`) + .expectFindForkRequest(fork) + .expectPullRequestToBeCreated('master', fork, forkBranchName, 200); + + // Simulate that the fork branch name is available. + fork.expectBranchRequest(forkBranchName, null); + + spyOn(console, 'error'); + + await instance.testCherryPickWithPullRequest(version, branchName); + + expect(console.error) + .toHaveBeenCalledWith( + jasmine.stringMatching(`Could not cherry-pick release notes for v${version}`)); + expect(console.error) + .toHaveBeenCalledWith(jasmine.stringMatching( + `Please copy the release notes manually into the "master" branch.`)); + + const changelogContent = readFileSync(join(testTmpDir, changelogPath), 'utf8'); + expect(changelogContent).toEqual(`Existing changelog`); + }); + + it('should push changes to a fork for creating a pull request', async () => { + const {repo, fork, instance, gitClient} = + setupReleaseActionForTesting(TestAction, baseReleaseTrains); + + // Expect the changelog to be fetched and return a fake changelog to test that + // it is properly appended. Also expect a pull request to be created in the fork. + repo.expectChangelogFetch(branchName, fakeReleaseNotes) + .expectFindForkRequest(fork) + .expectPullRequestToBeCreated('master', fork, forkBranchName, 200); + + // Simulate that the fork branch name is available. + fork.expectBranchRequest(forkBranchName, null); + + await instance.testCherryPickWithPullRequest(version, branchName); + + expect(gitClient.pushed.length).toBe(1); + expect(gitClient.pushed[0]).toEqual(getBranchPushMatcher({ + targetBranch: forkBranchName, + targetRepo: fork, + baseBranch: 'master', + baseRepo: repo, + expectedCommits: [{ + message: `docs: release notes for the v${version} release`, + files: ['CHANGELOG.md'], + }], + })); + }); + }); +}); + +/** + * Test release action that exposes protected units of the base + * release action class. This allows us to add unit tests. + */ +class TestAction extends ReleaseAction { + async getDescription() { + return 'Test action'; + } + + async perform() { + throw Error('Not implemented.'); + } + + async testBuildAndPublish(newVersion: semver.SemVer, publishBranch: string, distTag: string) { + await this.buildAndPublish(newVersion, publishBranch, distTag); + } + + async testCherryPickWithPullRequest(version: semver.SemVer, branch: string) { + await this.cherryPickChangelogIntoNextBranch(version, branch); + } +} diff --git a/dev-infra/release/publish/test/configure-next-as-major.spec.ts b/dev-infra/release/publish/test/configure-next-as-major.spec.ts new file mode 100644 index 0000000000000..10fb3b5639b73 --- /dev/null +++ b/dev-infra/release/publish/test/configure-next-as-major.spec.ts @@ -0,0 +1,79 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {getBranchPushMatcher} from '../../../utils/testing'; +import {ReleaseTrain} from '../../versioning/release-trains'; +import {ConfigureNextAsMajorAction} from '../actions/configure-next-as-major'; + +import {parse, setupReleaseActionForTesting} from './test-utils'; + +describe('configure next as major action', () => { + it('should be active if the next branch is for a minor', async () => { + expect(await ConfigureNextAsMajorAction.isActive({ + releaseCandidate: null, + next: new ReleaseTrain('master', parse('10.1.0-next.3')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + })).toBe(true); + }); + + it('should be active regardless of a feature-freeze/release-candidate train', async () => { + expect(await ConfigureNextAsMajorAction.isActive({ + releaseCandidate: new ReleaseTrain('10.1.x', parse('10.1.0-rc.1')), + next: new ReleaseTrain('master', parse('10.2.0-next.3')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + })).toBe(true); + }); + + it('should not be active if the next branch is for a major', async () => { + expect(await ConfigureNextAsMajorAction.isActive({ + releaseCandidate: null, + next: new ReleaseTrain('master', parse('11.0.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + })).toBe(false); + }); + + it('should compute proper version and create staging pull request', async () => { + const action = setupReleaseActionForTesting(ConfigureNextAsMajorAction, { + releaseCandidate: null, + next: new ReleaseTrain('master', parse('10.1.0-next.3')), + latest: new ReleaseTrain('10.0.x', parse('10.0.2')), + }); + + const {repo, fork, gitClient} = action; + const expectedVersion = `11.0.0-next.0`; + const expectedForkBranch = `switch-next-to-major-${expectedVersion}`; + + // We first mock the commit status check for the next branch, then expect two pull + // requests from a fork that are targeting next and the new feature-freeze branch. + repo.expectBranchRequest('master', 'MASTER_COMMIT_SHA') + .expectCommitStatusCheck('MASTER_COMMIT_SHA', 'success') + .expectFindForkRequest(fork) + .expectPullRequestToBeCreated('master', fork, expectedForkBranch, 200); + + // In the fork, we make the staging branch appear as non-existent, + // so that the PR can be created properly without collisions. + fork.expectBranchRequest(expectedForkBranch, null); + + await action.instance.perform(); + + expect(gitClient.pushed.length).toBe(1); + expect(gitClient.pushed[0]) + .toEqual( + getBranchPushMatcher({ + baseBranch: 'master', + baseRepo: repo, + targetBranch: expectedForkBranch, + targetRepo: fork, + expectedCommits: [{ + message: `release: switch the next branch to v${expectedVersion}`, + files: ['package.json'], + }], + }), + 'Expected the update branch to be created in fork for a pull request.'); + }); +}); diff --git a/dev-infra/release/publish/test/cut-lts-patch.spec.ts b/dev-infra/release/publish/test/cut-lts-patch.spec.ts new file mode 100644 index 0000000000000..d27bbd60883d6 --- /dev/null +++ b/dev-infra/release/publish/test/cut-lts-patch.spec.ts @@ -0,0 +1,110 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {matchesVersion} from '../../../utils/testing/semver-matchers'; +import {fetchLongTermSupportBranchesFromNpm} from '../../versioning/long-term-support'; +import {ReleaseTrain} from '../../versioning/release-trains'; +import {CutLongTermSupportPatchAction} from '../actions/cut-lts-patch'; + +import {expectStagingAndPublishWithCherryPick, fakeNpmPackageQueryRequest, getTestingMocksForReleaseAction, parse, setupReleaseActionForTesting, testTmpDir} from './test-utils'; + +describe('cut an LTS patch action', () => { + it('should be active', async () => { + expect(await CutLongTermSupportPatchAction.isActive({ + releaseCandidate: null, + next: new ReleaseTrain('master', parse('10.1.0-next.3')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + })).toBe(true); + }); + + it('should be active if there is a feature-freeze train', async () => { + expect(await CutLongTermSupportPatchAction.isActive({ + releaseCandidate: new ReleaseTrain('10.1.x', parse('10.1.0-next.3')), + next: new ReleaseTrain('master', parse('10.2.0-next.3')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + })).toBe(true); + }); + + it('should be active if there is a release-candidate train', async () => { + expect(await CutLongTermSupportPatchAction.isActive({ + releaseCandidate: new ReleaseTrain('10.1.x', parse('10.1.0-rc.0')), + next: new ReleaseTrain('master', parse('10.2.0-next.3')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + })).toBe(true); + }); + + it('should compute proper new version and select correct branch', async () => { + const action = setupReleaseActionForTesting(CutLongTermSupportPatchAction, { + releaseCandidate: null, + next: new ReleaseTrain('master', parse('10.1.0-next.3')), + latest: new ReleaseTrain('10.0.x', parse('10.0.2')), + }); + + spyOn(action.instance, '_promptForTargetLtsBranch') + .and.resolveTo({name: '9.2.x', version: parse('9.2.4'), npmDistTag: 'v9-lts'}); + + await expectStagingAndPublishWithCherryPick(action, '9.2.x', '9.2.5', 'v9-lts'); + }); + + it('should include number of active LTS branches in action description', async () => { + const {releaseConfig, gitClient} = getTestingMocksForReleaseAction(); + const activeReleaseTrains = { + releaseCandidate: null, + next: new ReleaseTrain('master', parse('10.1.0-next.3')), + latest: new ReleaseTrain('10.0.x', parse('10.0.2')), + }; + + fakeNpmPackageQueryRequest(releaseConfig.npmPackages[0], { + 'dist-tags': {'v9-lts': '9.1.2', 'v8-lts': '8.2.2'}, + 'time': { + '9.0.0': new Date().toISOString(), + '8.0.0': new Date().toISOString(), + }, + }); + + const action = new CutLongTermSupportPatchAction( + activeReleaseTrains, gitClient, releaseConfig, testTmpDir); + + expect(await action.getDescription()) + .toEqual(`Cut a new release for an active LTS branch (2 active).`); + }); + + it('should properly determine active and inactive LTS branches', async () => { + const {releaseConfig} = getTestingMocksForReleaseAction(); + fakeNpmPackageQueryRequest(releaseConfig.npmPackages[0], { + 'dist-tags': { + 'v9-lts': '9.2.3', + 'v8-lts': '8.4.4', + 'v7-lts': '7.0.1', + 'v6-lts': '6.0.0', + }, + time: { + '9.0.0': new Date().toISOString(), + '8.0.0': new Date().toISOString(), + // We pick dates for the v6 and v7 major versions that guarantee that the version + // is no longer considered as active LTS version. + '7.0.0': new Date(1912, 5, 23).toISOString(), + '6.0.0': new Date(1912, 5, 23).toISOString(), + }, + }); + + // Note: This accesses a private method, so we need to use an element access to satisfy + // TypeScript. It is acceptable to access the member for fine-grained unit testing due to + // complexity with inquirer we want to avoid. It is not easy to test prompts. + const {active, inactive} = await fetchLongTermSupportBranchesFromNpm(releaseConfig); + + expect(active).toEqual([ + {name: '9.2.x', version: matchesVersion('9.2.3'), npmDistTag: 'v9-lts'}, + {name: '8.4.x', version: matchesVersion('8.4.4'), npmDistTag: 'v8-lts'}, + ]); + expect(inactive).toEqual([ + {name: '7.0.x', version: matchesVersion('7.0.1'), npmDistTag: 'v7-lts'}, + {name: '6.0.x', version: matchesVersion('6.0.0'), npmDistTag: 'v6-lts'}, + ]); + }); +}); diff --git a/dev-infra/release/publish/test/cut-new-patch.spec.ts b/dev-infra/release/publish/test/cut-new-patch.spec.ts new file mode 100644 index 0000000000000..9df19191f01cc --- /dev/null +++ b/dev-infra/release/publish/test/cut-new-patch.spec.ts @@ -0,0 +1,52 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {ReleaseTrain} from '../../versioning/release-trains'; +import {CutNewPatchAction} from '../actions/cut-new-patch'; + +import {expectStagingAndPublishWithCherryPick, parse, setupReleaseActionForTesting} from './test-utils'; + +describe('cut new patch action', () => { + it('should be active', async () => { + expect(await CutNewPatchAction.isActive({ + releaseCandidate: null, + next: new ReleaseTrain('master', parse('10.1.0-next.3')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + })).toBe(true); + }); + + it('should compute proper new version and select correct branch', async () => { + const action = setupReleaseActionForTesting(CutNewPatchAction, { + releaseCandidate: null, + next: new ReleaseTrain('master', parse('10.1.0-next.3')), + latest: new ReleaseTrain('10.0.x', parse('10.0.2')), + }); + + await expectStagingAndPublishWithCherryPick(action, '10.0.x', '10.0.3', 'latest'); + }); + + it('should create a proper new version if there is a feature-freeze release-train', async () => { + const action = setupReleaseActionForTesting(CutNewPatchAction, { + releaseCandidate: new ReleaseTrain('10.1.x', parse('10.1.0-next.3')), + next: new ReleaseTrain('master', parse('10.2.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.9')), + }); + + await expectStagingAndPublishWithCherryPick(action, '10.0.x', '10.0.10', 'latest'); + }); + + it('should create a proper new version if there is a release-candidate train', async () => { + const action = setupReleaseActionForTesting(CutNewPatchAction, { + releaseCandidate: new ReleaseTrain('10.1.x', parse('10.1.0-rc.0')), + next: new ReleaseTrain('master', parse('10.2.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.9')), + }); + + await expectStagingAndPublishWithCherryPick(action, '10.0.x', '10.0.10', 'latest'); + }); +}); diff --git a/dev-infra/release/publish/test/cut-next-prerelease.spec.ts b/dev-infra/release/publish/test/cut-next-prerelease.spec.ts new file mode 100644 index 0000000000000..ab37350788b82 --- /dev/null +++ b/dev-infra/release/publish/test/cut-next-prerelease.spec.ts @@ -0,0 +1,79 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {readFileSync} from 'fs'; +import {join} from 'path'; + +import {ReleaseTrain} from '../../versioning/release-trains'; +import {CutNextPrereleaseAction} from '../actions/cut-next-prerelease'; +import {packageJsonPath} from '../constants'; + +import {expectStagingAndPublishWithCherryPick, expectStagingAndPublishWithoutCherryPick, parse, setupReleaseActionForTesting} from './test-utils'; + +describe('cut next pre-release action', () => { + it('should always be active regardless of release-trains', async () => { + expect(await CutNextPrereleaseAction.isActive()).toBe(true); + }); + + it('should cut a pre-release for the next branch if there is no FF/RC branch', async () => { + const action = setupReleaseActionForTesting(CutNextPrereleaseAction, { + releaseCandidate: null, + next: new ReleaseTrain('master', parse('10.2.0-next.0')), + latest: new ReleaseTrain('10.1.x', parse('10.1.2')), + }); + + await expectStagingAndPublishWithoutCherryPick(action, 'master', '10.2.0-next.1', 'next'); + }); + + // This is test for a special case in the release tooling. Whenever we branch off for + // feature-freeze, we immediately bump the version in the `next` branch but do not publish + // it. This is because there are no new changes in the next branch that wouldn't be part of + // the branched-off feature-freeze release-train. Also while a FF/RC is active, we cannot + // publish versions to the NPM dist tag. This means that the version is later published, but + // still needs all the staging work (e.g. changelog). We special-case this by not incrementing + // the version if the version in the next branch has not been published yet. + it('should not bump version if current next version has not been published', async () => { + const action = setupReleaseActionForTesting( + CutNextPrereleaseAction, { + releaseCandidate: null, + next: new ReleaseTrain('master', parse('10.2.0-next.0')), + latest: new ReleaseTrain('10.1.x', parse('10.1.0')), + }, + /* isNextPublishedToNpm */ false); + + await expectStagingAndPublishWithoutCherryPick(action, 'master', '10.2.0-next.0', 'next'); + + const pkgJsonContents = readFileSync(join(action.testTmpDir, packageJsonPath), 'utf8'); + const pkgJson = JSON.parse(pkgJsonContents); + expect(pkgJson.version).toBe('10.2.0-next.0', 'Expected version to not have changed.'); + }); + + describe('with active feature-freeze', () => { + it('should create a proper new version and select correct branch', async () => { + const action = setupReleaseActionForTesting(CutNextPrereleaseAction, { + releaseCandidate: new ReleaseTrain('10.1.x', parse('10.1.0-next.4')), + next: new ReleaseTrain('master', parse('10.2.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.2')), + }); + + await expectStagingAndPublishWithCherryPick(action, '10.1.x', '10.1.0-next.5', 'next'); + }); + }); + + describe('with active release-candidate', () => { + it('should create a proper new version and select correct branch', async () => { + const action = setupReleaseActionForTesting(CutNextPrereleaseAction, { + releaseCandidate: new ReleaseTrain('10.1.x', parse('10.1.0-rc.0')), + next: new ReleaseTrain('master', parse('10.2.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.2')), + }); + + await expectStagingAndPublishWithCherryPick(action, '10.1.x', '10.1.0-rc.1', 'next'); + }); + }); +}); diff --git a/dev-infra/release/publish/test/cut-release-candidate.spec.ts b/dev-infra/release/publish/test/cut-release-candidate.spec.ts new file mode 100644 index 0000000000000..589efa1df0f97 --- /dev/null +++ b/dev-infra/release/publish/test/cut-release-candidate.spec.ts @@ -0,0 +1,49 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {ReleaseTrain} from '../../versioning/release-trains'; +import {CutReleaseCandidateAction} from '../actions/cut-release-candidate'; + +import {expectStagingAndPublishWithCherryPick, parse, setupReleaseActionForTesting} from './test-utils'; + +describe('cut release candidate action', () => { + it('should activate if a feature-freeze release-train is active', async () => { + expect(await CutReleaseCandidateAction.isActive({ + releaseCandidate: new ReleaseTrain('10.1.x', parse('10.1.0-next.1')), + next: new ReleaseTrain('master', parse('10.2.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + })).toBe(true); + }); + + it('should not activate if release-candidate release-train is active', async () => { + expect(await CutReleaseCandidateAction.isActive({ + // No longer in feature-freeze but in release-candidate phase. + releaseCandidate: new ReleaseTrain('10.1.x', parse('10.1.0-rc.0')), + next: new ReleaseTrain('master', parse('10.2.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + })).toBe(false); + }); + + it('should not activate if no FF/RC release-train is active', async () => { + expect(await CutReleaseCandidateAction.isActive({ + releaseCandidate: null, + next: new ReleaseTrain('master', parse('10.1.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + })).toBe(false); + }); + + it('should create a proper new version and select correct branch', async () => { + const action = setupReleaseActionForTesting(CutReleaseCandidateAction, { + releaseCandidate: new ReleaseTrain('10.1.x', parse('10.1.0-next.1')), + next: new ReleaseTrain('master', parse('10.2.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + }); + + await expectStagingAndPublishWithCherryPick(action, '10.1.x', '10.1.0-rc.0', 'next'); + }); +}); diff --git a/dev-infra/release/publish/test/cut-stable.spec.ts b/dev-infra/release/publish/test/cut-stable.spec.ts new file mode 100644 index 0000000000000..5383b8f30093b --- /dev/null +++ b/dev-infra/release/publish/test/cut-stable.spec.ts @@ -0,0 +1,78 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {matchesVersion} from '../../../utils/testing/semver-matchers'; +import {ReleaseTrain} from '../../versioning/release-trains'; +import {CutStableAction} from '../actions/cut-stable'; +import * as externalCommands from '../external-commands'; + +import {expectStagingAndPublishWithCherryPick, parse, setupReleaseActionForTesting} from './test-utils'; + +describe('cut stable action', () => { + it('should not activate if a feature-freeze release-train is active', async () => { + expect(await CutStableAction.isActive({ + releaseCandidate: new ReleaseTrain('10.1.x', parse('10.1.0-next.1')), + next: new ReleaseTrain('master', parse('10.2.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + })).toBe(false); + }); + + it('should activate if release-candidate release-train is active', async () => { + expect(await CutStableAction.isActive({ + // No longer in feature-freeze but in release-candidate phase. + releaseCandidate: new ReleaseTrain('10.1.x', parse('10.1.0-rc.0')), + next: new ReleaseTrain('master', parse('10.2.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + })).toBe(true); + }); + + it('should not activate if no FF/RC release-train is active', async () => { + expect(await CutStableAction.isActive({ + releaseCandidate: null, + next: new ReleaseTrain('master', parse('10.1.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + })).toBe(false); + }); + + it('should create a proper new version and select correct branch', async () => { + const action = setupReleaseActionForTesting(CutStableAction, { + // No longer in feature-freeze but in release-candidate phase. + releaseCandidate: new ReleaseTrain('10.1.x', parse('10.1.0-rc.0')), + next: new ReleaseTrain('master', parse('10.2.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + }); + + await expectStagingAndPublishWithCherryPick(action, '10.1.x', '10.1.0', 'latest'); + }); + + it('should not tag the previous latest release-train if a minor has been cut', async () => { + const action = setupReleaseActionForTesting(CutStableAction, { + // No longer in feature-freeze but in release-candidate phase. + releaseCandidate: new ReleaseTrain('10.1.x', parse('10.1.0-rc.0')), + next: new ReleaseTrain('master', parse('10.2.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + }); + + await expectStagingAndPublishWithCherryPick(action, '10.1.x', '10.1.0', 'latest'); + expect(externalCommands.invokeSetNpmDistCommand).toHaveBeenCalledTimes(0); + }); + + it('should tag the previous latest release-train if a major has been cut', async () => { + const action = setupReleaseActionForTesting(CutStableAction, { + // No longer in feature-freeze but in release-candidate phase. + releaseCandidate: new ReleaseTrain('11.0.x', parse('11.0.0-rc.0')), + next: new ReleaseTrain('master', parse('10.2.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + }); + + await expectStagingAndPublishWithCherryPick(action, '11.0.x', '11.0.0', 'latest'); + expect(externalCommands.invokeSetNpmDistCommand).toHaveBeenCalledTimes(1); + expect(externalCommands.invokeSetNpmDistCommand) + .toHaveBeenCalledWith('v10-lts', matchesVersion('10.0.3')); + }); +}); diff --git a/dev-infra/release/publish/test/github-api-testing.ts b/dev-infra/release/publish/test/github-api-testing.ts new file mode 100644 index 0000000000000..e12ef6da37c86 --- /dev/null +++ b/dev-infra/release/publish/test/github-api-testing.ts @@ -0,0 +1,88 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as nock from 'nock'; + +/** + * Class that represents a Github repository in testing. The class can be + * used to intercept and except Github API requests for release actions. + */ +export class GithubTestingRepo { + /** Github API endpoint. */ + private apiEndpoint = `https://api.github.com`; + + /** Github API url for the given repository. */ + private repoApiUrl = `${this.apiEndpoint}/repos/${this.owner}/${this.name}`; + + constructor(public owner: string, public name: string) {} + + expectPullRequestToBeCreated( + baseBranch: string, fork: GithubTestingRepo, forkBranch: string, prNumber: number): this { + const expectedHead = `${fork.owner}:${forkBranch}`; + nock(this.repoApiUrl) + .post('/pulls', ({base, head}) => base === baseBranch && head === expectedHead) + .reply(200, {number: prNumber}); + return this; + } + + expectBranchRequest(branchName: string, sha: string|null): this { + nock(this.repoApiUrl) + .get(`/branches/${branchName}`) + .reply(sha ? 200 : 404, sha ? {commit: {sha}} : undefined); + return this; + } + + expectFindForkRequest(fork: GithubTestingRepo): this { + nock(this.apiEndpoint) + .post( + '/graphql', + ({variables}) => variables.owner === this.owner && variables.name === this.name) + .reply(200, { + data: {repository: {forks: {nodes: [{owner: {login: fork.owner}, name: fork.name}]}}} + }); + return this; + } + + expectCommitStatusCheck(sha: string, state: 'success'|'pending'|'failure'): this { + nock(this.repoApiUrl).get(`/commits/${sha}/status`).reply(200, {state}).activeMocks(); + return this; + } + + expectPullRequestWait(prNumber: number): this { + // The pull request state could be queried multiple times, so we persist + // this mock request. By default, nock only mocks requests once. + nock(this.repoApiUrl).get(`/pulls/${prNumber}`).reply(200, {merged: true}).persist(); + return this; + } + + expectChangelogFetch(branch: string, content: string): this { + nock(this.repoApiUrl).get(`/contents//CHANGELOG.md`).query(p => p.ref === branch).reply(200, { + content: new Buffer(content).toString('base64') + }); + return this; + } + + expectCommitRequest(sha: string, message: string): this { + nock(this.repoApiUrl).get(`/commits/${sha}`).reply(200, {commit: {message}}); + return this; + } + + expectTagToBeCreated(tagName: string, sha: string): this { + nock(this.repoApiUrl) + .post(`/git/refs`, b => b.ref === `refs/tags/${tagName}` && b.sha === sha) + .reply(200, {}); + return this; + } + + expectReleaseToBeCreated(name: string, tagName: string): this { + nock(this.repoApiUrl) + .post('/releases', b => b.name === name && b['tag_name'] === tagName) + .reply(200, {}); + return this; + } +} diff --git a/dev-infra/release/publish/test/move-next-into-feature-freeze.spec.ts b/dev-infra/release/publish/test/move-next-into-feature-freeze.spec.ts new file mode 100644 index 0000000000000..11a64ca4867de --- /dev/null +++ b/dev-infra/release/publish/test/move-next-into-feature-freeze.spec.ts @@ -0,0 +1,148 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {getBranchPushMatcher} from '../../../utils/testing'; +import {ActiveReleaseTrains} from '../../versioning/active-release-trains'; +import * as npm from '../../versioning/npm-publish'; +import {ReleaseTrain} from '../../versioning/release-trains'; +import {MoveNextIntoFeatureFreezeAction} from '../actions/move-next-into-feature-freeze'; +import * as externalCommands from '../external-commands'; + +import {getChangelogForVersion, parse, setupReleaseActionForTesting, testTmpDir} from './test-utils'; + +describe('move next into feature-freeze action', () => { + it('should not activate if a feature-freeze release-train is active', async () => { + expect(await MoveNextIntoFeatureFreezeAction.isActive({ + releaseCandidate: new ReleaseTrain('10.1.x', parse('10.1.0-next.1')), + next: new ReleaseTrain('master', parse('10.2.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + })).toBe(false); + }); + + it('should not activate if release-candidate release-train is active', async () => { + expect(await MoveNextIntoFeatureFreezeAction.isActive({ + // No longer in feature-freeze but in release-candidate phase. + releaseCandidate: new ReleaseTrain('10.1.x', parse('10.1.0-rc.0')), + next: new ReleaseTrain('master', parse('10.2.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + })).toBe(false); + }); + + it('should activate if no FF/RC release-train is active', async () => { + expect(await MoveNextIntoFeatureFreezeAction.isActive({ + releaseCandidate: null, + next: new ReleaseTrain('master', parse('10.1.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + })).toBe(true); + }); + + it('should create pull requests and feature-freeze branch', async () => { + await expectVersionAndBranchToBeCreated( + { + releaseCandidate: null, + next: new ReleaseTrain('master', parse('10.2.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + }, + /* isNextPublishedToNpm */ true, '10.3.0-next.0', '10.2.0-next.1', '10.2.x'); + }); + + it('should not increment the version if "next" version is not yet published', async () => { + await expectVersionAndBranchToBeCreated( + { + releaseCandidate: null, + next: new ReleaseTrain('master', parse('10.2.0-next.0')), + latest: new ReleaseTrain('10.0.x', parse('10.0.3')), + }, + /* isNextPublishedToNpm */ false, '10.3.0-next.0', '10.2.0-next.0', '10.2.x'); + }); + + /** Performs the action and expects versions and branches to be determined properly. */ + async function expectVersionAndBranchToBeCreated( + active: ActiveReleaseTrains, isNextPublishedToNpm: boolean, expectedNextVersion: string, + expectedVersion: string, expectedNewBranch: string) { + const {repo, fork, instance, gitClient, releaseConfig} = + setupReleaseActionForTesting(MoveNextIntoFeatureFreezeAction, active, isNextPublishedToNpm); + + const expectedNextUpdateBranch = `next-release-train-${expectedNextVersion}`; + const expectedStagingForkBranch = `release-stage-${expectedVersion}`; + const expectedTagName = expectedVersion; + + // We first mock the commit status check for the next branch, then expect two pull + // requests from a fork that are targeting next and the new feature-freeze branch. + repo.expectBranchRequest('master', 'MASTER_COMMIT_SHA') + .expectCommitStatusCheck('MASTER_COMMIT_SHA', 'success') + .expectFindForkRequest(fork) + .expectPullRequestToBeCreated(expectedNewBranch, fork, expectedStagingForkBranch, 200) + .expectPullRequestWait(200) + .expectBranchRequest(expectedNewBranch, 'STAGING_COMMIT_SHA') + .expectCommitRequest( + 'STAGING_COMMIT_SHA', `release: cut the v${expectedVersion} release\n\nPR Close #200.`) + .expectTagToBeCreated(expectedTagName, 'STAGING_COMMIT_SHA') + .expectReleaseToBeCreated(`v${expectedVersion}`, expectedTagName) + .expectChangelogFetch(expectedNewBranch, getChangelogForVersion(expectedVersion)) + .expectPullRequestToBeCreated('master', fork, expectedNextUpdateBranch, 100); + + // In the fork, we make the following branches appear as non-existent, + // so that the PRs can be created properly without collisions. + fork.expectBranchRequest(expectedStagingForkBranch, null) + .expectBranchRequest(expectedNextUpdateBranch, null); + + await instance.perform(); + + expect(gitClient.pushed.length).toBe(3); + expect(gitClient.pushed[0]) + .toEqual( + getBranchPushMatcher({ + baseRepo: repo, + baseBranch: 'master', + targetRepo: repo, + targetBranch: expectedNewBranch, + expectedCommits: [], + }), + 'Expected feature-freeze branch to be created upstream and based on "master".'); + expect(gitClient.pushed[1]) + .toEqual( + getBranchPushMatcher({ + baseBranch: 'master', + baseRepo: repo, + targetBranch: expectedStagingForkBranch, + targetRepo: fork, + expectedCommits: [{ + message: `release: cut the v${expectedVersion} release`, + files: ['package.json', 'CHANGELOG.md'], + }], + }), + 'Expected release staging branch to be created in fork.'); + + expect(gitClient.pushed[2]) + .toEqual( + getBranchPushMatcher({ + baseBranch: 'master', + baseRepo: repo, + targetBranch: expectedNextUpdateBranch, + targetRepo: fork, + expectedCommits: [ + { + message: `release: bump the next branch to v${expectedNextVersion}`, + files: ['package.json'] + }, + { + message: `docs: release notes for the v${expectedVersion} release`, + files: ['CHANGELOG.md'] + }, + ], + }), + 'Expected next release-train update branch be created in fork.'); + + expect(externalCommands.invokeReleaseBuildCommand).toHaveBeenCalledTimes(1); + expect(releaseConfig.generateReleaseNotesForHead).toHaveBeenCalledTimes(1); + expect(npm.runNpmPublish).toHaveBeenCalledTimes(2); + expect(npm.runNpmPublish).toHaveBeenCalledWith(`${testTmpDir}/dist/pkg1`, 'next', undefined); + expect(npm.runNpmPublish).toHaveBeenCalledWith(`${testTmpDir}/dist/pkg2`, 'next', undefined); + } +}); diff --git a/dev-infra/release/publish/test/test-utils.ts b/dev-infra/release/publish/test/test-utils.ts new file mode 100644 index 0000000000000..0f4ac54445423 --- /dev/null +++ b/dev-infra/release/publish/test/test-utils.ts @@ -0,0 +1,244 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {writeFileSync} from 'fs'; +import * as nock from 'nock'; +import {join} from 'path'; +import * as semver from 'semver'; + +import {GithubConfig} from '../../../utils/config'; +import * as console from '../../../utils/console'; +import {getBranchPushMatcher, VirtualGitClient} from '../../../utils/testing'; +import {ReleaseConfig} from '../../config/index'; +import {ActiveReleaseTrains} from '../../versioning/active-release-trains'; +import * as npm from '../../versioning/npm-publish'; +import {_npmPackageInfoCache, NpmPackageInfo} from '../../versioning/npm-registry'; +import {ReleaseAction, ReleaseActionConstructor} from '../actions'; +import * as constants from '../constants'; +import * as externalCommands from '../external-commands'; + +import {GithubTestingRepo} from './github-api-testing'; + +/** + * Temporary directory which will be used as project directory in tests. Note that + * this environment variable is automatically set by Bazel for tests. + */ +export const testTmpDir: string = process.env['TEST_TMPDIR']!; + +/** Interface describing a test release action. */ +export interface TestReleaseAction { + instance: T; + gitClient: VirtualGitClient; + repo: GithubTestingRepo; + fork: GithubTestingRepo; + testTmpDir: string; + githubConfig: GithubConfig; + releaseConfig: ReleaseConfig; +} + +/** Gets necessary test mocks for running a release action. */ +export function getTestingMocksForReleaseAction() { + const githubConfig = {owner: 'angular', name: 'dev-infra-test'}; + const gitClient = new VirtualGitClient(undefined, {github: githubConfig}, testTmpDir); + const releaseConfig: ReleaseConfig = { + npmPackages: [ + '@angular/pkg1', + '@angular/pkg2', + ], + generateReleaseNotesForHead: jasmine.createSpy('generateReleaseNotesForHead').and.resolveTo(), + buildPackages: () => { + throw Error('Not implemented'); + }, + }; + return {githubConfig, gitClient, releaseConfig}; +} + +/** + * Sets up the given release action for testing. + * @param actionCtor Type of release action to be tested. + * @param active Fake active release trains for the action, + * @param isNextPublishedToNpm Whether the next version is published to NPM. True by default. + */ +export function setupReleaseActionForTesting( + actionCtor: ReleaseActionConstructor, active: ActiveReleaseTrains, + isNextPublishedToNpm = true): TestReleaseAction { + // Reset existing HTTP interceptors. + nock.cleanAll(); + + const {gitClient, githubConfig, releaseConfig} = getTestingMocksForReleaseAction(); + const repo = new GithubTestingRepo(githubConfig.owner, githubConfig.name); + const fork = new GithubTestingRepo('some-user', 'fork'); + + // The version for the release-train in the next phase does not necessarily need to be + // published to NPM. We mock the NPM package request and fake the state of the next + // version based on the `isNextPublishedToNpm` testing parameter. More details on the + // special case for the next release train can be found in the next pre-release action. + fakeNpmPackageQueryRequest( + releaseConfig.npmPackages[0], + {versions: {[active.next.version.format()]: isNextPublishedToNpm ? {} : undefined}}); + + const action = new actionCtor(active, gitClient, releaseConfig, testTmpDir); + + // Fake confirm any prompts. We do not want to make any changelog edits and + // just proceed with the release action. + spyOn(console, 'promptConfirm').and.resolveTo(true); + + // Fake all external commands for the release tool. + spyOn(npm, 'runNpmPublish').and.resolveTo(true); + spyOn(externalCommands, 'invokeSetNpmDistCommand').and.resolveTo(); + spyOn(externalCommands, 'invokeYarnInstallCommand').and.resolveTo(); + spyOn(externalCommands, 'invokeReleaseBuildCommand').and.resolveTo([ + {name: '@angular/pkg1', outputPath: `${testTmpDir}/dist/pkg1`}, + {name: '@angular/pkg2', outputPath: `${testTmpDir}/dist/pkg2`} + ]); + + // Create an empty changelog and a `package.json` file so that file system + // interactions with the project directory do not cause exceptions. + writeFileSync(join(testTmpDir, 'CHANGELOG.md'), 'Existing changelog'); + writeFileSync(join(testTmpDir, 'package.json'), JSON.stringify({version: 'unknown'})); + + // Override the default pull request wait interval to a number of milliseconds that can be + // awaited in Jasmine tests. The default interval of 10sec is too large and causes a timeout. + Object.defineProperty(constants, 'waitForPullRequestInterval', {value: 50}); + + return {instance: action, repo, fork, testTmpDir, githubConfig, releaseConfig, gitClient}; +} + +/** Parses the specified version into Semver. */ +export function parse(version: string): semver.SemVer { + return semver.parse(version)!; +} + +/** Gets a changelog for the specified version. */ +export function getChangelogForVersion(version: string): string { + return `Changelog\n\n`; +} + +export async function expectStagingAndPublishWithoutCherryPick( + action: TestReleaseAction, expectedBranch: string, expectedVersion: string, + expectedNpmDistTag: string) { + const {repo, fork, gitClient, releaseConfig} = action; + const expectedStagingForkBranch = `release-stage-${expectedVersion}`; + const expectedTagName = expectedVersion; + + // We first mock the commit status check for the next branch, then expect two pull + // requests from a fork that are targeting next and the new feature-freeze branch. + repo.expectBranchRequest(expectedBranch, 'MASTER_COMMIT_SHA') + .expectCommitStatusCheck('MASTER_COMMIT_SHA', 'success') + .expectFindForkRequest(fork) + .expectPullRequestToBeCreated(expectedBranch, fork, expectedStagingForkBranch, 200) + .expectPullRequestWait(200) + .expectBranchRequest(expectedBranch, 'STAGING_COMMIT_SHA') + .expectCommitRequest( + 'STAGING_COMMIT_SHA', `release: cut the v${expectedVersion} release\n\nPR Close #200.`) + .expectTagToBeCreated(expectedTagName, 'STAGING_COMMIT_SHA') + .expectReleaseToBeCreated(`v${expectedVersion}`, expectedTagName); + + // In the fork, we make the staging branch appear as non-existent, + // so that the PR can be created properly without collisions. + fork.expectBranchRequest(expectedStagingForkBranch, null); + + await action.instance.perform(); + + expect(gitClient.pushed.length).toBe(1); + expect(gitClient.pushed[0]) + .toEqual( + getBranchPushMatcher({ + baseBranch: expectedBranch, + baseRepo: repo, + targetBranch: expectedStagingForkBranch, + targetRepo: fork, + expectedCommits: [{ + message: `release: cut the v${expectedVersion} release`, + files: ['package.json', 'CHANGELOG.md'], + }], + }), + 'Expected release staging branch to be created in fork.'); + + expect(externalCommands.invokeReleaseBuildCommand).toHaveBeenCalledTimes(1); + expect(releaseConfig.generateReleaseNotesForHead).toHaveBeenCalledTimes(1); + expect(npm.runNpmPublish).toHaveBeenCalledTimes(2); + expect(npm.runNpmPublish) + .toHaveBeenCalledWith(`${testTmpDir}/dist/pkg1`, expectedNpmDistTag, undefined); + expect(npm.runNpmPublish) + .toHaveBeenCalledWith(`${testTmpDir}/dist/pkg2`, expectedNpmDistTag, undefined); +} + +export async function expectStagingAndPublishWithCherryPick( + action: TestReleaseAction, expectedBranch: string, expectedVersion: string, + expectedNpmDistTag: string) { + const {repo, fork, gitClient, releaseConfig} = action; + const expectedStagingForkBranch = `release-stage-${expectedVersion}`; + const expectedCherryPickForkBranch = `changelog-cherry-pick-${expectedVersion}`; + const expectedTagName = expectedVersion; + + // We first mock the commit status check for the next branch, then expect two pull + // requests from a fork that are targeting next and the new feature-freeze branch. + repo.expectBranchRequest(expectedBranch, 'MASTER_COMMIT_SHA') + .expectCommitStatusCheck('MASTER_COMMIT_SHA', 'success') + .expectFindForkRequest(fork) + .expectPullRequestToBeCreated(expectedBranch, fork, expectedStagingForkBranch, 200) + .expectPullRequestWait(200) + .expectBranchRequest(expectedBranch, 'STAGING_COMMIT_SHA') + .expectCommitRequest( + 'STAGING_COMMIT_SHA', `release: cut the v${expectedVersion} release\n\nPR Close #200.`) + .expectTagToBeCreated(expectedTagName, 'STAGING_COMMIT_SHA') + .expectReleaseToBeCreated(`v${expectedVersion}`, expectedTagName) + .expectChangelogFetch(expectedBranch, getChangelogForVersion(expectedVersion)) + .expectPullRequestToBeCreated('master', fork, expectedCherryPickForkBranch, 300); + + // In the fork, we make the staging and cherry-pick branches appear as + // non-existent, so that the PRs can be created properly without collisions. + fork.expectBranchRequest(expectedStagingForkBranch, null) + .expectBranchRequest(expectedCherryPickForkBranch, null); + + await action.instance.perform(); + + expect(gitClient.pushed.length).toBe(2); + expect(gitClient.pushed[0]) + .toEqual( + getBranchPushMatcher({ + baseBranch: expectedBranch, + baseRepo: repo, + targetBranch: expectedStagingForkBranch, + targetRepo: fork, + expectedCommits: [{ + message: `release: cut the v${expectedVersion} release`, + files: ['package.json', 'CHANGELOG.md'], + }], + }), + 'Expected release staging branch to be created in fork.'); + + expect(gitClient.pushed[1]) + .toEqual( + getBranchPushMatcher({ + baseBranch: 'master', + baseRepo: repo, + targetBranch: expectedCherryPickForkBranch, + targetRepo: fork, + expectedCommits: [{ + message: `docs: release notes for the v${expectedVersion} release`, + files: ['CHANGELOG.md'], + }], + }), + 'Expected cherry-pick branch to be created in fork.'); + + expect(externalCommands.invokeReleaseBuildCommand).toHaveBeenCalledTimes(1); + expect(releaseConfig.generateReleaseNotesForHead).toHaveBeenCalledTimes(1); + expect(npm.runNpmPublish).toHaveBeenCalledTimes(2); + expect(npm.runNpmPublish) + .toHaveBeenCalledWith(`${testTmpDir}/dist/pkg1`, expectedNpmDistTag, undefined); + expect(npm.runNpmPublish) + .toHaveBeenCalledWith(`${testTmpDir}/dist/pkg2`, expectedNpmDistTag, undefined); +} + +/** Fakes a NPM package query API request for the given package. */ +export function fakeNpmPackageQueryRequest(pkgName: string, data: Partial) { + _npmPackageInfoCache[pkgName] = + Promise.resolve({'dist-tags': {}, versions: {}, time: {}, ...data}); +} diff --git a/dev-infra/release/set-dist-tag/BUILD.bazel b/dev-infra/release/set-dist-tag/BUILD.bazel new file mode 100644 index 0000000000000..24ffebb76d1e7 --- /dev/null +++ b/dev-infra/release/set-dist-tag/BUILD.bazel @@ -0,0 +1,44 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_library") +load("//tools:defaults.bzl", "jasmine_node_test") + +ts_library( + name = "set-dist-tag", + srcs = glob( + [ + "**/*.ts", + ], + exclude = ["*.spec.ts"], + ), + module_name = "@angular/dev-infra-private/release/set-dist-tag", + visibility = ["//dev-infra:__subpackages__"], + deps = [ + "//dev-infra/release/config", + "//dev-infra/release/versioning", + "//dev-infra/utils", + "@npm//@types/node", + "@npm//@types/semver", + "@npm//@types/yargs", + "@npm//ora", + "@npm//semver", + ], +) + +ts_library( + name = "test_lib", + srcs = glob([ + "*.spec.ts", + ]), + deps = [ + ":set-dist-tag", + "//dev-infra/release/config", + "//dev-infra/release/versioning", + "//dev-infra/utils/testing", + "@npm//@types/jasmine", + "@npm//@types/node", + ], +) + +jasmine_node_test( + name = "test", + deps = [":test_lib"], +) diff --git a/dev-infra/release/set-dist-tag/cli.ts b/dev-infra/release/set-dist-tag/cli.ts new file mode 100644 index 0000000000000..29cc0f2dd263a --- /dev/null +++ b/dev-infra/release/set-dist-tag/cli.ts @@ -0,0 +1,78 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as ora from 'ora'; +import * as semver from 'semver'; +import {Arguments, Argv, CommandModule} from 'yargs'; + +import {bold, debug, error, green, info, red} from '../../utils/console'; +import {getReleaseConfig} from '../config/index'; +import {setNpmTagForPackage} from '../versioning/npm-publish'; + + +/** Command line options for setting an NPM dist tag. */ +export interface ReleaseSetDistTagOptions { + tagName: string; + targetVersion: string; +} + +function builder(args: Argv): Argv { + return args + .positional('tagName', { + type: 'string', + demandOption: true, + description: 'Name of the NPM dist tag.', + }) + .positional('targetVersion', { + type: 'string', + demandOption: true, + description: 'Version to which the dist tag should be set.' + }); +} + +/** Yargs command handler for building a release. */ +async function handler(args: Arguments) { + const {targetVersion: rawVersion, tagName} = args; + const {npmPackages, publishRegistry} = getReleaseConfig(); + const version = semver.parse(rawVersion); + + if (version === null) { + error(red(`Invalid version specified (${rawVersion}). Unable to set NPM dist tag.`)); + process.exit(1); + } + + const spinner = ora().start(); + debug(`Setting "${tagName}" NPM dist tag for release packages to v${version}.`); + + for (const pkgName of npmPackages) { + spinner.text = `Setting NPM dist tag for "${pkgName}"`; + spinner.render(); + + try { + await setNpmTagForPackage(pkgName, tagName, version!, publishRegistry); + debug(`Successfully set "${tagName}" NPM dist tag for "${pkgName}".`); + } catch (e) { + spinner.stop(); + error(e); + error(red(` ✘ An error occurred while setting the NPM dist tag for "${pkgName}".`)); + process.exit(1); + } + } + + spinner.stop(); + info(green(` ✓ Set NPM dist tag for all release packages.`)); + info(green(` ${bold(tagName)} will now point to ${bold(`v${version}`)}.`)); +} + +/** CLI command module for setting an NPM dist tag. */ +export const ReleaseSetDistTagCommand: CommandModule<{}, ReleaseSetDistTagOptions> = { + builder, + handler, + command: 'set-dist-tag ', + describe: 'Sets a given NPM dist tag for all release packages.', +}; diff --git a/dev-infra/release/set-dist-tag/set-dist-tag.spec.ts b/dev-infra/release/set-dist-tag/set-dist-tag.spec.ts new file mode 100644 index 0000000000000..f7c02b98536b3 --- /dev/null +++ b/dev-infra/release/set-dist-tag/set-dist-tag.spec.ts @@ -0,0 +1,73 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {matchesVersion} from '../../utils/testing/semver-matchers'; +import * as releaseConfig from '../config/index'; +import * as npm from '../versioning/npm-publish'; + +import {ReleaseSetDistTagCommand} from './cli'; + +describe('ng-dev release set-dist-tag', () => { + let npmPackages: string[]; + let publishRegistry: string|undefined; + + beforeEach(() => { + npmPackages = ['@angular/pkg1', '@angular/pkg2']; + publishRegistry = undefined; + + spyOn(npm, 'setNpmTagForPackage'); + // We need to stub out the `process.exit` function during tests as the + // CLI handler calls those in case of failures. + spyOn(process, 'exit'); + }); + + /** Invokes the `set-dist-tag` command handler. */ + async function invokeCommand(tagName: string, targetVersion: string) { + spyOn(releaseConfig, 'getReleaseConfig').and.returnValue({ + npmPackages, + publishRegistry, + buildPackages: async () => [], + generateReleaseNotesForHead: async () => {} + }); + await ReleaseSetDistTagCommand.handler({tagName, targetVersion, $0: '', _: []}); + } + + it('should invoke "npm dist-tag" command for all configured packages', async () => { + await invokeCommand('latest', '10.0.0'); + expect(npm.setNpmTagForPackage).toHaveBeenCalledTimes(2); + expect(npm.setNpmTagForPackage) + .toHaveBeenCalledWith('@angular/pkg1', 'latest', matchesVersion('10.0.0'), undefined); + expect(npm.setNpmTagForPackage) + .toHaveBeenCalledWith('@angular/pkg2', 'latest', matchesVersion('10.0.0'), undefined); + }); + + it('should support a configured custom NPM registry', async () => { + publishRegistry = 'https://my-custom-registry.angular.io'; + await invokeCommand('latest', '10.0.0'); + + expect(npm.setNpmTagForPackage).toHaveBeenCalledTimes(2); + expect(npm.setNpmTagForPackage) + .toHaveBeenCalledWith( + '@angular/pkg1', 'latest', matchesVersion('10.0.0'), + 'https://my-custom-registry.angular.io'); + expect(npm.setNpmTagForPackage) + .toHaveBeenCalledWith( + '@angular/pkg2', 'latest', matchesVersion('10.0.0'), + 'https://my-custom-registry.angular.io'); + }); + + it('should error if an invalid version has been specified', async () => { + spyOn(console, 'error'); + await invokeCommand('latest', '10.0'); + + expect(console.error) + .toHaveBeenCalledWith('Invalid version specified (10.0). Unable to set NPM dist tag.'); + expect(process.exit).toHaveBeenCalledWith(1); + expect(process.exit).toHaveBeenCalledTimes(1); + }); +}); diff --git a/dev-infra/release/env-stamp.ts b/dev-infra/release/stamping/env-stamp.ts similarity index 97% rename from dev-infra/release/env-stamp.ts rename to dev-infra/release/stamping/env-stamp.ts index b425e5ece0313..184b63d7d6c0a 100644 --- a/dev-infra/release/env-stamp.ts +++ b/dev-infra/release/stamping/env-stamp.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {exec as _exec} from '../utils/shelljs'; +import {exec as _exec} from '../../utils/shelljs'; /** * Log the environment variables expected by bazel for stamping. diff --git a/dev-infra/release/versioning/BUILD.bazel b/dev-infra/release/versioning/BUILD.bazel new file mode 100644 index 0000000000000..94e6011ade990 --- /dev/null +++ b/dev-infra/release/versioning/BUILD.bazel @@ -0,0 +1,18 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_library") + +ts_library( + name = "versioning", + srcs = glob([ + "**/*.ts", + ]), + module_name = "@angular/dev-infra-private/release/versioning", + visibility = ["//dev-infra:__subpackages__"], + deps = [ + "//dev-infra/release/config", + "//dev-infra/utils", + "@npm//@types/node-fetch", + "@npm//@types/semver", + "@npm//node-fetch", + "@npm//semver", + ], +) diff --git a/dev-infra/release/versioning/README.md b/dev-infra/release/versioning/README.md new file mode 100644 index 0000000000000..b428492b7f02e --- /dev/null +++ b/dev-infra/release/versioning/README.md @@ -0,0 +1,5 @@ +## Versioning for the Angular organization + +The folder contains common tooling needed for implementing the versioning as proposed +by [this design document](https://docs.google.com/document/d/197kVillDwx-RZtSVOBtPb4BBIAw0E9RT3q3v6DZkykU). +Primary tooling is the determination of _active_ release trains. diff --git a/dev-infra/release/versioning/active-release-trains.ts b/dev-infra/release/versioning/active-release-trains.ts new file mode 100644 index 0000000000000..4ec1341bf3d1c --- /dev/null +++ b/dev-infra/release/versioning/active-release-trains.ts @@ -0,0 +1,139 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as semver from 'semver'; + +import {ReleaseTrain} from './release-trains'; +import {getBranchesForMajorVersions, getVersionOfBranch, GithubRepoWithApi, VersionBranch} from './version-branches'; + +/** Interface describing determined active release trains for a project. */ +export interface ActiveReleaseTrains { + /** Release-train currently in the "release-candidate" or "feature-freeze" phase. */ + releaseCandidate: ReleaseTrain|null; + /** Release-train currently in the "latest" phase. */ + latest: ReleaseTrain; + /** Release-train in the `next` phase. */ + next: ReleaseTrain; +} + +/** Branch name for the `next` branch. */ +export const nextBranchName = 'master'; + +/** Fetches the active release trains for the configured project. */ +export async function fetchActiveReleaseTrains(repo: GithubRepoWithApi): + Promise { + const nextVersion = await getVersionOfBranch(repo, nextBranchName); + const next = new ReleaseTrain(nextBranchName, nextVersion); + const majorVersionsToConsider: number[] = []; + let expectedReleaseCandidateMajor: number; + + // If the `next` branch (i.e. `master` branch) is for an upcoming major version, we know + // that there is no patch branch or feature-freeze/release-candidate branch for this major + // digit. If the current `next` version is the first minor of a major version, we know that + // the feature-freeze/release-candidate branch can only be the actual major branch. The + // patch branch is based on that, either the actual major branch or the last minor from the + // preceding major version. In all other cases, the patch branch and feature-freeze or + // release-candidate branch are part of the same major version. Consider the following: + // + // CASE 1. next: 11.0.0-next.0: patch and feature-freeze/release-candidate can only be + // most recent `10.<>.x` branches. The FF/RC branch can only be the last-minor of v10. + // CASE 2. next: 11.1.0-next.0: patch can be either `11.0.x` or last-minor in v10 based + // on whether there is a feature-freeze/release-candidate branch (=> `11.0.x`). + // CASE 3. next: 10.6.0-next.0: patch can be either `10.5.x` or `10.4.x` based on whether + // there is a feature-freeze/release-candidate branch (=> `10.5.x`) + if (nextVersion.minor === 0) { + expectedReleaseCandidateMajor = nextVersion.major - 1; + majorVersionsToConsider.push(nextVersion.major - 1); + } else if (nextVersion.minor === 1) { + expectedReleaseCandidateMajor = nextVersion.major; + majorVersionsToConsider.push(nextVersion.major, nextVersion.major - 1); + } else { + expectedReleaseCandidateMajor = nextVersion.major; + majorVersionsToConsider.push(nextVersion.major); + } + + // Collect all version-branches that should be considered for the latest version-branch, + // or the feature-freeze/release-candidate. + const branches = (await getBranchesForMajorVersions(repo, majorVersionsToConsider)); + const {latest, releaseCandidate} = await findActiveReleaseTrainsFromVersionBranches( + repo, nextVersion, branches, expectedReleaseCandidateMajor); + + if (latest === null) { + throw Error( + `Unable to determine the latest release-train. The following branches ` + + `have been considered: [${branches.map(b => b.name).join(', ')}]`); + } + + return {releaseCandidate, latest, next}; +} + +/** Finds the currently active release trains from the specified version branches. */ +export async function findActiveReleaseTrainsFromVersionBranches( + repo: GithubRepoWithApi, nextVersion: semver.SemVer, branches: VersionBranch[], + expectedReleaseCandidateMajor: number): Promise<{ + latest: ReleaseTrain | null, + releaseCandidate: ReleaseTrain | null, +}> { + // Version representing the release-train currently in the next phase. Note that we ignore + // patch and pre-release segments in order to be able to compare the next release train to + // other release trains from version branches (which follow the `N.N.x` pattern). + const nextReleaseTrainVersion = semver.parse(`${nextVersion.major}.${nextVersion.minor}.0`)!; + + let latest: ReleaseTrain|null = null; + let releaseCandidate: ReleaseTrain|null = null; + + // Iterate through the captured branches and find the latest non-prerelease branch and a + // potential release candidate branch. From the collected branches we iterate descending + // order (most recent semantic version-branch first). The first branch is either the latest + // active version branch (i.e. patch) or a feature-freeze/release-candidate branch. A FF/RC + // branch cannot be older than the latest active version-branch, so we stop iterating once + // we found such a branch. Otherwise, if we found a FF/RC branch, we continue looking for the + // next version-branch as that one is supposed to be the latest active version-branch. If it + // is not, then an error will be thrown due to two FF/RC branches existing at the same time. + for (const {name, parsed} of branches) { + // It can happen that version branches have been accidentally created which are more recent + // than the release-train in the next branch (i.e. `master`). We could ignore such branches + // silently, but it might be symptomatic for an outdated version in the `next` branch, or an + // accidentally created branch by the caretaker. In either way we want to raise awareness. + if (semver.gt(parsed, nextReleaseTrainVersion)) { + throw Error( + `Discovered unexpected version-branch "${name}" for a release-train that is ` + + `more recent than the release-train currently in the "${nextBranchName}" branch. ` + + `Please either delete the branch if created by accident, or update the outdated ` + + `version in the next branch (${nextBranchName}).`); + } else if (semver.eq(parsed, nextReleaseTrainVersion)) { + throw Error( + `Discovered unexpected version-branch "${name}" for a release-train that is already ` + + `active in the "${nextBranchName}" branch. Please either delete the branch if ` + + `created by accident, or update the version in the next branch (${nextBranchName}).`); + } + + const version = await getVersionOfBranch(repo, name); + const releaseTrain = new ReleaseTrain(name, version); + const isPrerelease = version.prerelease[0] === 'rc' || version.prerelease[0] === 'next'; + + if (isPrerelease) { + if (releaseCandidate !== null) { + throw Error( + `Unable to determine latest release-train. Found two consecutive ` + + `branches in feature-freeze/release-candidate phase. Did not expect both "${name}" ` + + `and "${releaseCandidate.branchName}" to be in feature-freeze/release-candidate mode.`); + } else if (version.major !== expectedReleaseCandidateMajor) { + throw Error( + `Discovered unexpected old feature-freeze/release-candidate branch. Expected no ` + + `version-branch in feature-freeze/release-candidate mode for v${version.major}.`); + } + releaseCandidate = releaseTrain; + } else { + latest = releaseTrain; + break; + } + } + + return {releaseCandidate, latest}; +} diff --git a/dev-infra/release/versioning/inc-semver.ts b/dev-infra/release/versioning/inc-semver.ts new file mode 100644 index 0000000000000..3ea0e917c6995 --- /dev/null +++ b/dev-infra/release/versioning/inc-semver.ts @@ -0,0 +1,19 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as semver from 'semver'; + +/** + * Increments a specified SemVer version. Compared to the original increment in SemVer, + * the version is cloned to not modify the original version instance. + */ +export function semverInc( + version: semver.SemVer, release: semver.ReleaseType, identifier?: string) { + const clone = new semver.SemVer(version.version); + return clone.inc(release, identifier); +} diff --git a/modules/playground/src/web_workers/input/index.ts b/dev-infra/release/versioning/index.ts similarity index 53% rename from modules/playground/src/web_workers/input/index.ts rename to dev-infra/release/versioning/index.ts index f3791aca9123d..fa834458cd150 100644 --- a/modules/playground/src/web_workers/input/index.ts +++ b/dev-infra/release/versioning/index.ts @@ -6,6 +6,8 @@ * found in the LICENSE file at https://angular.io/license */ -import {bootstrapWorkerUi} from '@angular/platform-webworker'; - -bootstrapWorkerUi('loader.js'); +export * from './active-release-trains'; +export * from './release-trains'; +export * from './long-term-support'; +export * from './version-branches'; +export * from './npm-registry'; diff --git a/dev-infra/release/versioning/long-term-support.ts b/dev-infra/release/versioning/long-term-support.ts new file mode 100644 index 0000000000000..308bd952abb63 --- /dev/null +++ b/dev-infra/release/versioning/long-term-support.ts @@ -0,0 +1,99 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as semver from 'semver'; + +import {ReleaseConfig} from '../config/index'; + +import {fetchProjectNpmPackageInfo} from './npm-registry'; + +/** Interface describing determined LTS branches. */ +export interface LtsBranches { + /** List of active LTS version branches. */ + active: LtsBranch[]; + /** List of inactive LTS version branches. */ + inactive: LtsBranch[]; +} + +/** Interface describing an LTS version branch. */ +export interface LtsBranch { + /** Name of the branch. */ + name: string; + /** Most recent version for the given LTS branch. */ + version: semver.SemVer; + /** NPM dist tag for the LTS version. */ + npmDistTag: string; +} + +/** + * Number of months a major version in Angular is actively supported. See: + * https://angular.io/guide/releases#support-policy-and-schedule. + */ +const majorActiveSupportDuration = 6; + +/** + * Number of months a major version has active long-term support. See: + * https://angular.io/guide/releases#support-policy-and-schedule. + */ +const majorLongTermSupportDuration = 12; + +/** Regular expression that matches LTS NPM dist tags. */ +const ltsNpmDistTagRegex = /^v(\d+)-lts$/; + +/** Finds all long-term support release trains from the specified NPM package. */ +export async function fetchLongTermSupportBranchesFromNpm(config: ReleaseConfig): + Promise { + const {'dist-tags': distTags, time} = await fetchProjectNpmPackageInfo(config); + const today = new Date(); + const active: LtsBranch[] = []; + const inactive: LtsBranch[] = []; + + // Iterate through the NPM package information and determine active/inactive LTS versions with + // their corresponding branches. We assume that an LTS tagged version in NPM belongs to the + // last-minor branch of a given major (i.e. we assume there are no outdated LTS NPM dist tags). + for (const npmDistTag in distTags) { + if (ltsNpmDistTagRegex.test(npmDistTag)) { + const version = semver.parse(distTags[npmDistTag])!; + const branchName = `${version.major}.${version.minor}.x`; + const majorReleaseDate = new Date(time[`${version.major}.0.0`]); + const ltsEndDate = computeLtsEndDateOfMajor(majorReleaseDate); + const ltsBranch: LtsBranch = {name: branchName, version, npmDistTag}; + // Depending on whether the LTS phase is still active, add the branch + // to the list of active or inactive LTS branches. + if (today <= ltsEndDate) { + active.push(ltsBranch); + } else { + inactive.push(ltsBranch); + } + } + } + + // Sort LTS branches in descending order. i.e. most recent ones first. + active.sort((a, b) => semver.rcompare(a.version, b.version)); + inactive.sort((a, b) => semver.rcompare(a.version, b.version)); + + return {active, inactive}; +} + +/** + * Computes the date when long-term support ends for a major released at the + * specified date. + */ +export function computeLtsEndDateOfMajor(majorReleaseDate: Date): Date { + return new Date( + majorReleaseDate.getFullYear(), + majorReleaseDate.getMonth() + majorActiveSupportDuration + majorLongTermSupportDuration, + majorReleaseDate.getDate(), majorReleaseDate.getHours(), majorReleaseDate.getMinutes(), + majorReleaseDate.getSeconds(), majorReleaseDate.getMilliseconds()); +} + +/** Gets the long-term support NPM dist tag for a given major version. */ +export function getLtsNpmDistTagOfMajor(major: number): string { + // LTS versions should be tagged in NPM in the following format: `v{major}-lts`. + return `v${major}-lts`; +} diff --git a/dev-infra/release/versioning/next-prerelease-version.ts b/dev-infra/release/versioning/next-prerelease-version.ts new file mode 100644 index 0000000000000..bc6ed5b08655d --- /dev/null +++ b/dev-infra/release/versioning/next-prerelease-version.ts @@ -0,0 +1,32 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as semver from 'semver'; + +import {ReleaseConfig} from '../config/index'; + +import {ActiveReleaseTrains} from './active-release-trains'; +import {semverInc} from './inc-semver'; +import {isVersionPublishedToNpm} from './npm-registry'; + +/** Computes the new pre-release version for the next release-train. */ +export async function computeNewPrereleaseVersionForNext( + active: ActiveReleaseTrains, config: ReleaseConfig): Promise { + const {version: nextVersion} = active.next; + const isNextPublishedToNpm = await isVersionPublishedToNpm(nextVersion, config); + // Special-case where the version in the `next` release-train is not published yet. This + // happens when we recently branched off for feature-freeze. We already bump the version to + // the next minor or major, but do not publish immediately. Cutting a release immediately would + // be not helpful as there are no other changes than in the feature-freeze branch. If we happen + // to detect this case, we stage the release as usual but do not increment the version. + if (isNextPublishedToNpm) { + return semverInc(nextVersion, 'prerelease'); + } else { + return nextVersion; + } +} diff --git a/dev-infra/release/versioning/npm-publish.ts b/dev-infra/release/versioning/npm-publish.ts new file mode 100644 index 0000000000000..7415c5e84b5d6 --- /dev/null +++ b/dev-infra/release/versioning/npm-publish.ts @@ -0,0 +1,38 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as semver from 'semver'; +import {spawnWithDebugOutput} from '../../utils/child-process'; + +/** + * Runs NPM publish within a specified package directory. + * @throws With the process log output if the publish failed. + */ +export async function runNpmPublish( + packagePath: string, distTag: string, registryUrl: string|undefined) { + const args = ['publish', '--access', 'public', '--tag', distTag]; + // If a custom registry URL has been specified, add the `--registry` flag. + if (registryUrl !== undefined) { + args.push('--registry', registryUrl); + } + await spawnWithDebugOutput('npm', args, {cwd: packagePath, mode: 'silent'}); +} + +/** + * Sets the NPM tag to the specified version for the given package. + * @throws With the process log output if the tagging failed. + */ +export async function setNpmTagForPackage( + packageName: string, distTag: string, version: semver.SemVer, registryUrl: string|undefined) { + const args = ['dist-tag', 'add', `${packageName}@${version}`, distTag]; + // If a custom registry URL has been specified, add the `--registry` flag. + if (registryUrl !== undefined) { + args.push('--registry', registryUrl); + } + await spawnWithDebugOutput('npm', args, {mode: 'silent'}); +} diff --git a/dev-infra/release/versioning/npm-registry.ts b/dev-infra/release/versioning/npm-registry.ts new file mode 100644 index 0000000000000..2e0419ee695a8 --- /dev/null +++ b/dev-infra/release/versioning/npm-registry.ts @@ -0,0 +1,65 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import fetch from 'node-fetch'; +import * as semver from 'semver'; + +import {ReleaseConfig} from '../config/index'; + +/** Type describing an NPM package fetched from the registry. */ +export interface NpmPackageInfo { + /** Maps of versions and their package JSON objects. */ + 'versions': {[name: string]: undefined|object}; + /** Map of NPM dist-tags and their chosen version. */ + 'dist-tags': {[tagName: string]: string|undefined}; + /** Map of versions and their ISO release time. */ + 'time': {[name: string]: string}; +} + +/** + * Cache for requested NPM package information. A cache is desirable as the NPM + * registry requests are usually very large and slow. + */ +export const _npmPackageInfoCache: {[pkgName: string]: Promise} = {}; + +/** + * Fetches the NPM package representing the project. Angular repositories usually contain + * multiple packages in a monorepo scheme, but packages dealt with as part of the release + * tooling are released together with the same versioning and branching. This means that + * a single package can be used as source of truth for NPM package queries. + */ +export async function fetchProjectNpmPackageInfo(config: ReleaseConfig): Promise { + const pkgName = getRepresentativeNpmPackage(config); + return await fetchPackageInfoFromNpmRegistry(pkgName); +} + +/** Gets whether the given version is published to NPM or not */ +export async function isVersionPublishedToNpm( + version: semver.SemVer, config: ReleaseConfig): Promise { + const {versions} = await fetchProjectNpmPackageInfo(config); + return versions[version.format()] !== undefined; +} + +/** + * Gets the representative NPM package for the specified release configuration. Angular + * repositories usually contain multiple packages in a monorepo scheme, but packages dealt with + * as part of the release tooling are released together with the same versioning and branching. + * This means that a single package can be used as source of truth for NPM package queries. + */ +function getRepresentativeNpmPackage(config: ReleaseConfig) { + return config.npmPackages[0]; +} + +/** Fetches the specified NPM package from the NPM registry. */ +async function fetchPackageInfoFromNpmRegistry(pkgName: string): Promise { + if (_npmPackageInfoCache[pkgName] === undefined) { + _npmPackageInfoCache[pkgName] = + fetch(`https://registry.npmjs.org/${pkgName}`).then(r => r.json()); + } + return await _npmPackageInfoCache[pkgName]; +} diff --git a/dev-infra/release/versioning/print-active-trains.ts b/dev-infra/release/versioning/print-active-trains.ts new file mode 100644 index 0000000000000..b4314cea2e5db --- /dev/null +++ b/dev-infra/release/versioning/print-active-trains.ts @@ -0,0 +1,80 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {blue, bold, info} from '../../utils/console'; +import {ReleaseConfig} from '../config/index'; + +import {ActiveReleaseTrains} from './active-release-trains'; +import {fetchLongTermSupportBranchesFromNpm} from './long-term-support'; +import {isVersionPublishedToNpm} from './npm-registry'; + +/** + * Prints the active release trains to the console. + * @params active Active release trains that should be printed. + * @params config Release configuration used for querying NPM on published versions. + */ +export async function printActiveReleaseTrains( + active: ActiveReleaseTrains, config: ReleaseConfig): Promise { + const {releaseCandidate, next, latest} = active; + const isNextPublishedToNpm = await isVersionPublishedToNpm(next.version, config); + const nextTrainType = next.isMajor ? 'major' : 'minor'; + const ltsBranches = await fetchLongTermSupportBranchesFromNpm(config); + + info(); + info(blue('Current version branches in the project:')); + + // Print information for release trains in the feature-freeze/release-candidate phase. + if (releaseCandidate !== null) { + const rcVersion = releaseCandidate.version; + const rcTrainType = releaseCandidate.isMajor ? 'major' : 'minor'; + const rcTrainPhase = + rcVersion.prerelease[0] === 'next' ? 'feature-freeze' : 'release-candidate'; + info( + ` • ${bold(releaseCandidate.branchName)} contains changes for an upcoming ` + + `${rcTrainType} that is currently in ${bold(rcTrainPhase)} phase.`); + info(` Most recent pre-release for this branch is "${bold(`v${rcVersion}`)}".`); + } + + // Print information about the release-train in the latest phase. i.e. the patch branch. + info(` • ${bold(latest.branchName)} contains changes for the most recent patch.`); + info(` Most recent patch version for this branch is "${bold(`v${latest.version}`)}".`); + + // Print information about the release-train in the next phase. + info( + ` • ${bold(next.branchName)} contains changes for a ${nextTrainType} ` + + `currently in active development.`); + // Note that there is a special case for versions in the next release-train. The version in + // the next branch is not always published to NPM. This can happen when we recently branched + // off for a feature-freeze release-train. More details are in the next pre-release action. + if (isNextPublishedToNpm) { + info(` Most recent pre-release version for this branch is "${bold(`v${next.version}`)}".`); + } else { + info( + ` Version is currently set to "${bold(`v${next.version}`)}", but has not been ` + + `published yet.`); + } + + // If no release-train in release-candidate or feature-freeze phase is active, + // we print a message as last bullet point to make this clear. + if (releaseCandidate === null) { + info(' • No release-candidate or feature-freeze branch currently active.'); + } + + info(); + info(blue('Current active LTS version branches:')); + + // Print all active LTS branches (each branch as own bullet point). + if (ltsBranches.active.length !== 0) { + for (const ltsBranch of ltsBranches.active) { + info(` • ${bold(ltsBranch.name)} is currently in active long-term support phase.`); + info(` Most recent patch version for this branch is "${bold(`v${ltsBranch.version}`)}".`); + } + } + + info(); +} diff --git a/dev-infra/release/versioning/release-trains.ts b/dev-infra/release/versioning/release-trains.ts new file mode 100644 index 0000000000000..ee72c603f67c5 --- /dev/null +++ b/dev-infra/release/versioning/release-trains.ts @@ -0,0 +1,21 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as semver from 'semver'; + +/** Class describing a release-train. */ +export class ReleaseTrain { + /** Whether the release train is currently targeting a major. */ + isMajor = this.version.minor === 0 && this.version.patch === 0; + + constructor( + /** Name of the branch for this release-train. */ + public branchName: string, + /** Most recent version for this release train. */ + public version: semver.SemVer) {} +} diff --git a/dev-infra/release/versioning/version-branches.ts b/dev-infra/release/versioning/version-branches.ts new file mode 100644 index 0000000000000..7a934d3a761d3 --- /dev/null +++ b/dev-infra/release/versioning/version-branches.ts @@ -0,0 +1,87 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import * as semver from 'semver'; +import {GithubClient, GithubRepo} from '../../utils/git/github'; + +/** Type describing a Github repository with corresponding API client. */ +export interface GithubRepoWithApi extends GithubRepo { + /** API client that can access the repository. */ + api: GithubClient; +} + +/** Type describing a version-branch. */ +export interface VersionBranch { + /** Name of the branch in Git. e.g. `10.0.x`. */ + name: string; + /** + * Parsed SemVer version for the version-branch. Version branches technically do + * not follow the SemVer format, but we can have representative SemVer versions + * that can be used for comparisons, sorting and other checks. + */ + parsed: semver.SemVer; +} + +/** Regular expression that matches version-branches. */ +const versionBranchNameRegex = /^(\d+)\.(\d+)\.x$/; + +/** Gets the version of a given branch by reading the `package.json` upstream. */ +export async function getVersionOfBranch( + repo: GithubRepoWithApi, branchName: string): Promise { + const {data} = await repo.api.repos.getContents( + {owner: repo.owner, repo: repo.name, path: '/package.json', ref: branchName}); + const {version} = JSON.parse(Buffer.from(data.content, 'base64').toString()); + const parsedVersion = semver.parse(version); + if (parsedVersion === null) { + throw Error(`Invalid version detected in following branch: ${branchName}.`); + } + return parsedVersion; +} + +/** Whether the given branch corresponds to a version branch. */ +export function isVersionBranch(branchName: string): boolean { + return versionBranchNameRegex.test(branchName); +} + +/** + * Converts a given version-branch into a SemVer version that can be used with SemVer + * utilities. e.g. to determine semantic order, extract major digit, compare. + * + * For example `10.0.x` will become `10.0.0` in SemVer. The patch digit is not + * relevant but needed for parsing. SemVer does not allow `x` as patch digit. + */ +export function getVersionForVersionBranch(branchName: string): semver.SemVer|null { + return semver.parse(branchName.replace(versionBranchNameRegex, '$1.$2.0')); +} + +/** + * Gets the version branches for the specified major versions in descending + * order. i.e. latest version branches first. + */ +export async function getBranchesForMajorVersions( + repo: GithubRepoWithApi, majorVersions: number[]): Promise { + const {data: branchData} = + await repo.api.repos.listBranches({owner: repo.owner, repo: repo.name, protected: true}); + const branches: VersionBranch[] = []; + + for (const {name} of branchData) { + if (!isVersionBranch(name)) { + continue; + } + // Convert the version-branch into a SemVer version that can be used with the + // SemVer utilities. e.g. to determine semantic order, compare versions. + const parsed = getVersionForVersionBranch(name); + // Collect all version-branches that match the specified major versions. + if (parsed !== null && majorVersions.includes(parsed.major)) { + branches.push({name, parsed}); + } + } + + // Sort captured version-branches in descending order. + return branches.sort((a, b) => semver.rcompare(a.parsed, b.parsed)); +} diff --git a/dev-infra/tmpl-package.json b/dev-infra/tmpl-package.json index 0b3048a6651ad..350f316044027 100644 --- a/dev-infra/tmpl-package.json +++ b/dev-infra/tmpl-package.json @@ -9,26 +9,27 @@ "ts-circular-deps": "./ts-circular-dependencies/index.js" }, "dependencies": { - "@angular/benchpress": "0.2.0", + "@angular/benchpress": "0.2.1", "@octokit/graphql": "", "@octokit/types": "", + "@octokit/rest": "", "brotli": "", "chalk": "", "cli-progress": "", "glob": "", "inquirer": "", + "inquirer-autocomplete-prompt": "", "minimatch": "", "multimatch": "", "node-fetch": "", "node-uuid": "", + "ora": "", "semver": "", "shelljs": "", "tslib": "", "typed-graphqlify": "", "yaml": "", - "yargs": "" - }, - "peerDependencies": { + "yargs": "", "@bazel/buildifier": "", "clang-format": "", "protractor": "", diff --git a/dev-infra/ts-circular-dependencies/BUILD.bazel b/dev-infra/ts-circular-dependencies/BUILD.bazel index e084b268ba88f..ff8b0ae5506ea 100644 --- a/dev-infra/ts-circular-dependencies/BUILD.bazel +++ b/dev-infra/ts-circular-dependencies/BUILD.bazel @@ -1,4 +1,4 @@ -load("@npm_bazel_typescript//:index.bzl", "ts_library") +load("@npm//@bazel/typescript:index.bzl", "ts_library") ts_library( name = "ts-circular-dependencies", diff --git a/dev-infra/ts-circular-dependencies/index.ts b/dev-infra/ts-circular-dependencies/index.ts index df597bf6e2bb9..e76ad4d7e133b 100644 --- a/dev-infra/ts-circular-dependencies/index.ts +++ b/dev-infra/ts-circular-dependencies/index.ts @@ -30,20 +30,19 @@ export function tsCircularDependenciesBuilder(localYargs: yargs.Argv) { {type: 'string', demandOption: true, description: 'Path to the configuration file.'}) .option('warnings', {type: 'boolean', description: 'Prints all warnings.'}) .command( - 'check', 'Checks if the circular dependencies have changed.', {}, - (argv: yargs.Arguments) => { + 'check', 'Checks if the circular dependencies have changed.', args => args, + argv => { const {config: configArg, warnings} = argv; const configPath = isAbsolute(configArg) ? configArg : resolve(configArg); const config = loadTestConfig(configPath); - process.exit(main(false, config, warnings)); + process.exit(main(false, config, !!warnings)); }) - .command( - 'approve', 'Approves the current circular dependencies.', {}, (argv: yargs.Arguments) => { - const {config: configArg, warnings} = argv; - const configPath = isAbsolute(configArg) ? configArg : resolve(configArg); - const config = loadTestConfig(configPath); - process.exit(main(true, config, warnings)); - }); + .command('approve', 'Approves the current circular dependencies.', args => args, argv => { + const {config: configArg, warnings} = argv; + const configPath = isAbsolute(configArg) ? configArg : resolve(configArg); + const config = loadTestConfig(configPath); + process.exit(main(true, config, !!warnings)); + }); } /** @@ -113,7 +112,8 @@ export function main( if (fixedCircularDeps.length !== 0) { error(yellow(` Fixed circular dependencies that need to be removed from the golden:`)); fixedCircularDeps.forEach(c => error(` • ${convertReferenceChainToString(c)}`)); - error(); + info(yellow(`\n Total: ${newCircularDeps.length} new cycle(s), ${ + fixedCircularDeps.length} fixed cycle(s). \n`)); if (approveCommand) { info(yellow(` Please approve the new golden with: ${approveCommand}`)); } else { diff --git a/dev-infra/tsconfig.json b/dev-infra/tsconfig.json new file mode 100644 index 0000000000000..aee0ec940fcde --- /dev/null +++ b/dev-infra/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "strict": true + } +} diff --git a/dev-infra/utils/BUILD.bazel b/dev-infra/utils/BUILD.bazel index 248aaddacfcaa..24dc637c6d64e 100644 --- a/dev-infra/utils/BUILD.bazel +++ b/dev-infra/utils/BUILD.bazel @@ -1,4 +1,4 @@ -load("@npm_bazel_typescript//:index.bzl", "ts_library") +load("@npm//@bazel/typescript:index.bzl", "ts_library") ts_library( name = "utils", @@ -15,10 +15,13 @@ ts_library( "@npm//@types/inquirer", "@npm//@types/node", "@npm//@types/shelljs", + "@npm//@types/yargs", "@npm//chalk", "@npm//inquirer", + "@npm//inquirer-autocomplete-prompt", "@npm//shelljs", "@npm//tslib", "@npm//typed-graphqlify", + "@npm//yargs", ], ) diff --git a/dev-infra/utils/child-process.ts b/dev-infra/utils/child-process.ts new file mode 100644 index 0000000000000..b2a4c21df7358 --- /dev/null +++ b/dev-infra/utils/child-process.ts @@ -0,0 +1,82 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {spawn, SpawnOptions} from 'child_process'; +import {debug, error} from './console'; + +/** Interface describing the options for spawning a process. */ +export interface SpawnedProcessOptions extends Omit { + /** Console output mode. Defaults to "enabled". */ + mode?: 'enabled'|'silent'|'on-error'; +} + +/** Interface describing the result of a spawned process. */ +export interface SpawnedProcessResult { + /** Captured stdout in string format. */ + stdout: string; +} + +/** + * Spawns a given command with the specified arguments inside a shell. All process stdout + * output is captured and returned as resolution on completion. Depending on the chosen + * output mode, stdout/stderr output is also printed to the console, or only on error. + * + * @returns a Promise resolving with captured stdout on success. The promise + * rejects on command failure. + */ +export function spawnWithDebugOutput( + command: string, args: string[], + options: SpawnedProcessOptions = {}): Promise { + return new Promise((resolve, reject) => { + const commandText = `${command} ${args.join(' ')}`; + const outputMode = options.mode; + + debug(`Executing command: ${commandText}`); + + const childProcess = + spawn(command, args, {...options, shell: true, stdio: ['inherit', 'pipe', 'pipe']}); + let logOutput = ''; + let stdout = ''; + + // Capture the stdout separately so that it can be passed as resolve value. + // This is useful if commands return parsable stdout. + childProcess.stderr.on('data', message => { + logOutput += message; + // If console output is enabled, print the message directly to the stderr. Note that + // we intentionally print all output to stderr as stdout should not be polluted. + if (outputMode === undefined || outputMode === 'enabled') { + process.stderr.write(message); + } + }); + childProcess.stdout.on('data', message => { + stdout += message; + logOutput += message; + // If console output is enabled, print the message directly to the stderr. Note that + // we intentionally print all output to stderr as stdout should not be polluted. + if (outputMode === undefined || outputMode === 'enabled') { + process.stderr.write(message); + } + }); + + childProcess.on('exit', (status, signal) => { + const exitDescription = status !== null ? `exit code "${status}"` : `signal "${signal}"`; + const printFn = outputMode === 'on-error' ? error : debug; + + printFn(`Command "${commandText}" completed with ${exitDescription}.`); + printFn(`Process output: \n${logOutput}`); + + // On success, resolve the promise. Otherwise reject with the captured stderr + // and stdout log output if the output mode was set to `silent`. + if (status === 0) { + resolve({stdout}); + } else { + reject(outputMode === 'silent' ? logOutput : undefined); + } + }); + }); +} diff --git a/dev-infra/utils/config.ts b/dev-infra/utils/config.ts index bd08ee68e44e1..358c02d7665aa 100644 --- a/dev-infra/utils/config.ts +++ b/dev-infra/utils/config.ts @@ -9,7 +9,7 @@ import {existsSync} from 'fs'; import {dirname, join} from 'path'; -import {error} from './console'; +import {debug, error} from './console'; import {exec} from './shelljs'; import {isTsNodeAvailable} from './ts-node'; @@ -49,7 +49,16 @@ export type NgDevConfig = CommonConfig&T; const CONFIG_FILE_PATH = '.ng-dev/config'; /** The configuration for ng-dev. */ -let CONFIG: {}|null = null; +let cachedConfig: NgDevConfig|null = null; + +/** + * The filename expected for local user config, without the file extension to allow a typescript, + * javascript or json file to be used. + */ +const USER_CONFIG_FILE_PATH = '.ng-dev.user'; + +/** The local user configuration for ng-dev. */ +let userConfig: {[key: string]: any}|null = null; /** * Get the configuration from the file system, returning the already loaded @@ -57,15 +66,15 @@ let CONFIG: {}|null = null; */ export function getConfig(): NgDevConfig { // If the global config is not defined, load it from the file system. - if (CONFIG === null) { + if (cachedConfig === null) { // The full path to the configuration file. const configPath = join(getRepoBaseDir(), CONFIG_FILE_PATH); - // Set the global config object. - CONFIG = readConfigFile(configPath); + // Read the configuration and validate it before caching it for the future. + cachedConfig = validateCommonConfig(readConfigFile(configPath)); } - // Return a clone of the global config to ensure that a new instance of the config is returned - // each time, preventing unexpected effects of modifications to the config object. - return validateCommonConfig({...CONFIG}); + // Return a clone of the cached global config to ensure that a new instance of the config + // is returned each time, preventing unexpected effects of modifications to the config object. + return {...cachedConfig}; } /** Validate the common configuration has been met for the ng-dev command. */ @@ -86,8 +95,11 @@ function validateCommonConfig(config: Partial) { return config as NgDevConfig; } -/** Resolves and reads the specified configuration file. */ -function readConfigFile(configPath: string): object { +/** + * Resolves and reads the specified configuration file, optionally returning an empty object if the + * configuration file cannot be read. + */ +function readConfigFile(configPath: string, returnEmptyObjectOnError = false): object { // If the the `.ts` extension has not been set up already, and a TypeScript based // version of the given configuration seems to exist, set up `ts-node` if available. if (require.extensions['.ts'] === undefined && existsSync(`${configPath}.ts`) && @@ -103,7 +115,12 @@ function readConfigFile(configPath: string): object { try { return require(configPath); } catch (e) { - error('Could not read configuration file.'); + if (returnEmptyObjectOnError) { + debug(`Could not read configuration file at ${configPath}, returning empty object instead.`); + debug(e); + return {}; + } + error(`Could not read configuration file at ${configPath}.`); error(e); process.exit(1); } @@ -135,3 +152,23 @@ export function getRepoBaseDir() { } return baseRepoDir.trim(); } + +/** + * Get the local user configuration from the file system, returning the already loaded copy if it is + * defined. + * + * @returns The user configuration object, or an empty object if no user configuration file is + * present. The object is an untyped object as there are no required user configurations. + */ +export function getUserConfig() { + // If the global config is not defined, load it from the file system. + if (userConfig === null) { + // The full path to the configuration file. + const configPath = join(getRepoBaseDir(), USER_CONFIG_FILE_PATH); + // Set the global config object. + userConfig = readConfigFile(configPath, true); + } + // Return a clone of the user config to ensure that a new instance of the config is returned + // each time, preventing unexpected effects of modifications to the config object. + return {...userConfig}; +} diff --git a/dev-infra/utils/console.ts b/dev-infra/utils/console.ts index 63830a5e76a82..41d2c8a3a5139 100644 --- a/dev-infra/utils/console.ts +++ b/dev-infra/utils/console.ts @@ -7,13 +7,20 @@ */ import chalk from 'chalk'; -import {prompt} from 'inquirer'; +import {writeFileSync} from 'fs'; +import {createPromptModule, ListChoiceOptions, prompt} from 'inquirer'; +import * as inquirerAutocomplete from 'inquirer-autocomplete-prompt'; +import {join} from 'path'; +import {Arguments} from 'yargs'; +import {getRepoBaseDir} from './config'; /** Reexport of chalk colors for convenient access. */ export const red: typeof chalk = chalk.red; export const green: typeof chalk = chalk.green; export const yellow: typeof chalk = chalk.yellow; +export const bold: typeof chalk = chalk.bold; +export const blue: typeof chalk = chalk.blue; /** Prompts the user with a confirmation question and a specified message. */ export async function promptConfirm(message: string, defaultValue = false): Promise { @@ -26,6 +33,52 @@ export async function promptConfirm(message: string, defaultValue = false): Prom .result; } +/** Prompts the user to select an option from a filterable autocomplete list. */ +export async function promptAutocomplete( + message: string, choices: (string|ListChoiceOptions)[]): Promise; +/** + * Prompts the user to select an option from a filterable autocomplete list, with an option to + * choose no value. + */ +export async function promptAutocomplete( + message: string, choices: (string|ListChoiceOptions)[], + noChoiceText?: string): Promise; +export async function promptAutocomplete( + message: string, choices: (string|ListChoiceOptions)[], + noChoiceText?: string): Promise { + // Creates a local prompt module with an autocomplete prompt type. + const prompt = createPromptModule({}).registerPrompt('autocomplete', inquirerAutocomplete); + if (noChoiceText) { + choices = [noChoiceText, ...choices]; + } + // `prompt` must be cast as `any` as the autocomplete typings are not available. + const result = (await (prompt as any)({ + type: 'autocomplete', + name: 'result', + message, + source: (_: any, input: string) => { + if (!input) { + return Promise.resolve(choices); + } + return Promise.resolve(choices.filter(choice => { + if (typeof choice === 'string') { + return choice.includes(input); + } + return choice.name!.includes(input); + })); + } + })).result; + if (result === noChoiceText) { + return false; + } + return result; +} + +/** Prompts the user for one line of input. */ +export async function promptInput(message: string): Promise { + return (await prompt<{result: string}>({type: 'input', name: 'result', message})).result; +} + /** * Supported levels for logging functions. * @@ -93,6 +146,7 @@ function runConsoleCommand(loadCommand: () => Function, logLevel: LOG_LEVELS, .. if (getLogLevel() >= logLevel) { loadCommand()(...text); } + printToLogFile(logLevel, ...text); } /** @@ -108,3 +162,59 @@ function getLogLevel() { } return logLevel; } + +/** All text to write to the log file. */ +let LOGGED_TEXT = ''; +/** Whether file logging as been enabled. */ +let FILE_LOGGING_ENABLED = false; +/** + * The number of columns used in the prepended log level information on each line of the logging + * output file. + */ +const LOG_LEVEL_COLUMNS = 7; + +/** + * Enable writing the logged outputs to the log file on process exit, sets initial lines from the + * command execution, containing information about the timing and command parameters. + * + * This is expected to be called only once during a command run, and should be called by the + * middleware of yargs to enable the file logging before the rest of the command parsing and + * response is executed. + */ +export function captureLogOutputForCommand(argv: Arguments) { + if (FILE_LOGGING_ENABLED) { + throw Error('`captureLogOutputForCommand` cannot be called multiple times'); + } + /** The date time used for timestamping when the command was invoked. */ + const now = new Date(); + /** Header line to separate command runs in log files. */ + const headerLine = Array(100).fill('#').join(''); + LOGGED_TEXT += `${headerLine}\nCommand: ${argv.$0} ${argv._.join(' ')}\nRan at: ${now}\n`; + + // On process exit, write the logged output to the appropriate log files + process.on('exit', (code: number) => { + LOGGED_TEXT += `Command ran in ${new Date().getTime() - now.getTime()}ms`; + /** Path to the log file location. */ + const logFilePath = join(getRepoBaseDir(), '.ng-dev.log'); + + // Strip ANSI escape codes from log outputs. + LOGGED_TEXT = LOGGED_TEXT.replace(/\x1B\[([0-9]{1,3}(;[0-9]{1,2})?)?[mGK]/g, ''); + + writeFileSync(logFilePath, LOGGED_TEXT); + + // For failure codes greater than 1, the new logged lines should be written to a specific log + // file for the command run failure. + if (code > 1) { + writeFileSync(join(getRepoBaseDir(), `.ng-dev.err-${now.getTime()}.log`), LOGGED_TEXT); + } + }); + + // Mark file logging as enabled to prevent the function from executing multiple times. + FILE_LOGGING_ENABLED = true; +} + +/** Write the provided text to the log file, prepending each line with the log level. */ +function printToLogFile(logLevel: LOG_LEVELS, ...text: string[]) { + const logLevelText = `${LOG_LEVELS[logLevel]}:`.padEnd(LOG_LEVEL_COLUMNS); + LOGGED_TEXT += text.join(' ').split('\n').map(l => `${logLevelText} ${l}\n`).join(''); +} diff --git a/dev-infra/utils/git/github-urls.ts b/dev-infra/utils/git/github-urls.ts new file mode 100644 index 0000000000000..ff4e04810f671 --- /dev/null +++ b/dev-infra/utils/git/github-urls.ts @@ -0,0 +1,42 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + + +import {URL} from 'url'; +import {GithubConfig} from '../config'; +import {GitClient} from './index'; + +/** URL to the Github page where personal access tokens can be managed. */ +export const GITHUB_TOKEN_SETTINGS_URL = 'https://github.com/settings/tokens'; + +/** URL to the Github page where personal access tokens can be generated. */ +export const GITHUB_TOKEN_GENERATE_URL = 'https://github.com/settings/tokens/new'; + +/** Adds the provided token to the given Github HTTPs remote url. */ +export function addTokenToGitHttpsUrl(githubHttpsUrl: string, token: string) { + const url = new URL(githubHttpsUrl); + url.username = token; + return url.href; +} + +/** Gets the repository Git URL for the given github config. */ +export function getRepositoryGitUrl(config: GithubConfig, githubToken?: string): string { + if (config.useSsh) { + return `git@github.com:${config.owner}/${config.name}.git`; + } + const baseHttpUrl = `https://github.com/${config.owner}/${config.name}.git`; + if (githubToken !== undefined) { + return addTokenToGitHttpsUrl(baseHttpUrl, githubToken); + } + return baseHttpUrl; +} + +/** Gets a Github URL that refers to a list of recent commits within a specified branch. */ +export function getListCommitsInBranchUrl({remoteParams}: GitClient, branchName: string) { + return `https://github.com/${remoteParams.owner}/${remoteParams.repo}/commits/${branchName}`; +} diff --git a/dev-infra/utils/git/github-yargs.ts b/dev-infra/utils/git/github-yargs.ts new file mode 100644 index 0000000000000..ecd615d57e400 --- /dev/null +++ b/dev-infra/utils/git/github-yargs.ts @@ -0,0 +1,36 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {Argv} from 'yargs'; +import {error, red, yellow} from '../console'; +import {GITHUB_TOKEN_GENERATE_URL} from './github-urls'; + +export type ArgvWithGithubToken = Argv<{githubToken: string}>; + +/** Sets up the `github-token` command option for the given Yargs instance. */ +export function addGithubTokenOption(yargs: Argv): ArgvWithGithubToken { + return yargs + // 'github-token' is casted to 'githubToken' to properly set up typings to reflect the key in + // the Argv object being camelCase rather than kebob case due to the `camel-case-expansion` + // config: https://github.com/yargs/yargs-parser#camel-case-expansion + .option('github-token' as 'githubToken', { + type: 'string', + description: 'Github token. If not set, token is retrieved from the environment variables.', + coerce: (token: string) => { + const githubToken = token || process.env.GITHUB_TOKEN || process.env.TOKEN; + if (!githubToken) { + error(red('No Github token set. Please set the `GITHUB_TOKEN` environment variable.')); + error(red('Alternatively, pass the `--github-token` command line flag.')); + error(yellow(`You can generate a token here: ${GITHUB_TOKEN_GENERATE_URL}`)); + process.exit(1); + } + return githubToken; + }, + }) + .default('github-token' as 'githubToken', '', ''); +} diff --git a/dev-infra/utils/git/github.ts b/dev-infra/utils/git/github.ts index 85d061435868f..1d368bb9f03d3 100644 --- a/dev-infra/utils/git/github.ts +++ b/dev-infra/utils/git/github.ts @@ -11,6 +11,14 @@ import * as Octokit from '@octokit/rest'; import {RequestParameters} from '@octokit/types'; import {query, types} from 'typed-graphqlify'; +/** Interface describing a Github repository. */ +export interface GithubRepo { + /** Owner login of the repository. */ + owner: string; + /** Name of the repository. */ + name: string; +} + /** Error for failed Github API requests. */ export class GithubApiRequestError extends Error { constructor(public status: number, message: string) { @@ -26,7 +34,7 @@ export class GithubApiRequestError extends Error { **/ export class GithubClient extends Octokit { /** The Github GraphQL (v4) API. */ - graqhql: GithubGraphqlClient; + graphql: GithubGraphqlClient; /** The current user based on checking against the Github API. */ private _currentUser: string|null = null; @@ -42,7 +50,7 @@ export class GithubClient extends Octokit { }); // Create authenticated graphql client. - this.graqhql = new GithubGraphqlClient(token); + this.graphql = new GithubGraphqlClient(token); } /** Retrieve the login of the current user from Github. */ @@ -51,7 +59,7 @@ export class GithubClient extends Octokit { if (this._currentUser !== null) { return this._currentUser; } - const result = await this.graqhql.query({ + const result = await this.graphql.query({ viewer: { login: types.string, } @@ -61,18 +69,13 @@ export class GithubClient extends Octokit { } /** - * An object representation of a GraphQL Query to be used as a response type and to generate - * a GraphQL query string. + * An object representation of a GraphQL Query to be used as a response type and + * to generate a GraphQL query string. */ -type GraphQLQueryObject = Parameters[1]; +export type GraphQLQueryObject = Parameters[1]; -/** - * A client for interacting with Github's GraphQL API. - * - * This class is intentionally not exported as it should always be access/used via a - * _GithubClient instance. - */ -class GithubGraphqlClient { +/** A client for interacting with Github's GraphQL API. */ +export class GithubGraphqlClient { /** The Github GraphQL (v4) API. */ private graqhql = graphql; @@ -80,11 +83,10 @@ class GithubGraphqlClient { // Set the default headers to include authorization with the provided token for all // graphQL calls. if (token) { - this.graqhql.defaults({headers: {authorization: `token ${token}`}}); + this.graqhql = this.graqhql.defaults({headers: {authorization: `token ${token}`}}); } } - /** Perform a query using Github's GraphQL API. */ async query(queryObject: T, params: RequestParameters = {}) { const queryString = query(queryObject); diff --git a/dev-infra/utils/git/index.ts b/dev-infra/utils/git/index.ts index 030a25c4cada6..8a51ffc63f7dc 100644 --- a/dev-infra/utils/git/index.ts +++ b/dev-infra/utils/git/index.ts @@ -10,8 +10,9 @@ import * as Octokit from '@octokit/rest'; import {spawnSync, SpawnSyncOptions, SpawnSyncReturns} from 'child_process'; import {getConfig, getRepoBaseDir, NgDevConfig} from '../config'; -import {info, yellow} from '../console'; +import {debug, info, yellow} from '../console'; import {GithubClient} from './github'; +import {getRepositoryGitUrl, GITHUB_TOKEN_GENERATE_URL, GITHUB_TOKEN_SETTINGS_URL} from './github-urls'; /** Github response type extended to include the `x-oauth-scopes` headers presence. */ type RateLimitResponseWithOAuthScopeHeader = Octokit.Response&{ @@ -32,29 +33,26 @@ export class GitCommandError extends Error { } /** - * Common client for performing Git interactions. + * Common client for performing Git interactions with a given remote. * - * Takes in two optional arguements: - * _githubToken: the token used for authentifation in github interactions, by default empty + * Takes in two optional arguments: + * `githubToken`: the token used for authentication in Github interactions, by default empty * allowing readonly actions. - * _config: The dev-infra configuration containing GitClientConfig information, by default - * loads the config from the default location. + * `config`: The dev-infra configuration containing information about the remote. By default + * the dev-infra configuration is loaded with its Github configuration. **/ export class GitClient { - /** Short-hand for accessing the remote configuration. */ + /** Short-hand for accessing the default remote configuration. */ remoteConfig = this._config.github; /** Octokit request parameters object for targeting the configured remote. */ remoteParams = {owner: this.remoteConfig.owner, repo: this.remoteConfig.name}; - /** URL that resolves to the configured repository. */ - repoGitUrl = this.remoteConfig.useSsh ? - `git@github.com:${this.remoteConfig.owner}/${this.remoteConfig.name}.git` : - `https://${this._githubToken}@github.com/${this.remoteConfig.owner}/${ - this.remoteConfig.name}.git`; + /** Git URL that resolves to the configured repository. */ + repoGitUrl = getRepositoryGitUrl(this.remoteConfig, this.githubToken); /** Instance of the authenticated Github octokit API. */ - github = new GithubClient(this._githubToken); + github = new GithubClient(this.githubToken); /** The OAuth scopes available for the provided Github token. */ - private _oauthScopes: Promise|null = null; + private _cachedOauthScopes: Promise|null = null; /** * Regular expression that matches the provided Github token. Used for * sanitizing the token from Git child process output. @@ -62,13 +60,13 @@ export class GitClient { private _githubTokenRegex: RegExp|null = null; constructor( - private _githubToken?: string, private _config: Pick = getConfig(), + public githubToken?: string, private _config: Pick = getConfig(), private _projectRoot = getRepoBaseDir()) { // If a token has been specified (and is not empty), pass it to the Octokit API and // also create a regular expression that can be used for sanitizing Git command output // so that it does not print the token accidentally. - if (_githubToken != null) { - this._githubTokenRegex = new RegExp(_githubToken, 'g'); + if (githubToken != null) { + this._githubTokenRegex = new RegExp(githubToken, 'g'); } } @@ -86,13 +84,17 @@ export class GitClient { /** * Spawns a given Git command process. Does not throw if the command fails. Additionally, * if there is any stderr output, the output will be printed. This makes it easier to - * debug failed commands. + * info failed commands. */ runGraceful(args: string[], options: SpawnSyncOptions = {}): SpawnSyncReturns { - // To improve the debugging experience in case something fails, we print all executed - // Git commands. Note that we do not want to print the token if is contained in the - // command. It's common to share errors with others if the tool failed. - info('Executing: git', this.omitGithubTokenFromMessage(args.join(' '))); + // To improve the debugging experience in case something fails, we print all executed Git + // commands unless the `stdio` is explicitly set to `ignore` (which is equivalent to silent). + // Note that we do not want to print the token if it is contained in the command. It's common + // to share errors with others if the tool failed, and we do not want to leak tokens. + // TODO: Add support for configuring this on a per-client basis. Some tools do not want + // to print the Git command messages to the console at all (e.g. to maintain clean output). + const printFn = options.stdio !== 'ignore' ? info : debug; + printFn('Executing: git', this.omitGithubTokenFromMessage(args.join(' '))); const result = spawnSync('git', args, { cwd: this._projectRoot, @@ -150,6 +152,25 @@ export class GitClient { return value.replace(this._githubTokenRegex, ''); } + /** + * Checks out a requested branch or revision, optionally cleaning the state of the repository + * before attempting the checking. Returns a boolean indicating whether the branch or revision + * was cleanly checked out. + */ + checkout(branchOrRevision: string, cleanState: boolean): boolean { + if (cleanState) { + // Abort any outstanding ams. + this.runGraceful(['am', '--abort'], {stdio: 'ignore'}); + // Abort any outstanding cherry-picks. + this.runGraceful(['cherry-pick', '--abort'], {stdio: 'ignore'}); + // Abort any outstanding rebases. + this.runGraceful(['rebase', '--abort'], {stdio: 'ignore'}); + // Clear any changes in the current repo. + this.runGraceful(['reset', '--hard'], {stdio: 'ignore'}); + } + return this.runGraceful(['checkout', branchOrRevision], {stdio: 'ignore'}).status === 0; + } + /** * Assert the GitClient instance is using a token with permissions for the all of the * provided OAuth scopes. @@ -172,8 +193,8 @@ export class GitClient { `The provided does not have required permissions due to missing scope(s): ` + `${yellow(missingScopes.join(', '))}\n\n` + `Update the token in use at:\n` + - ` https://github.com/settings/tokens\n\n` + - `Alternatively, a new token can be created at: https://github.com/settings/tokens/new\n`; + ` ${GITHUB_TOKEN_SETTINGS_URL}\n\n` + + `Alternatively, a new token can be created at: ${GITHUB_TOKEN_GENERATE_URL}\n`; return {error}; } @@ -181,14 +202,14 @@ export class GitClient { /** * Retrieve the OAuth scopes for the loaded Github token. **/ - private async getAuthScopesForToken() { + private getAuthScopesForToken() { // If the OAuth scopes have already been loaded, return the Promise containing them. - if (this._oauthScopes !== null) { - return this._oauthScopes; + if (this._cachedOauthScopes !== null) { + return this._cachedOauthScopes; } // OAuth scopes are loaded via the /rate_limit endpoint to prevent // usage of a request against that rate_limit for this lookup. - return this._oauthScopes = this.github.rateLimit.get().then(_response => { + return this._cachedOauthScopes = this.github.rateLimit.get().then(_response => { const response = _response as RateLimitResponseWithOAuthScopeHeader; const scopes: string = response.headers['x-oauth-scopes'] || ''; return scopes.split(',').map(scope => scope.trim()); diff --git a/dev-infra/utils/github.ts b/dev-infra/utils/github.ts index 04cd93ed97e2e..7e187a24a4d93 100644 --- a/dev-infra/utils/github.ts +++ b/dev-infra/utils/github.ts @@ -6,29 +6,15 @@ * found in the LICENSE file at https://angular.io/license */ -import {graphql as unauthenticatedGraphql} from '@octokit/graphql'; +import {params, types} from 'typed-graphqlify'; -import {params, query as graphqlQuery, types} from 'typed-graphqlify'; -import {NgDevConfig} from './config'; - -/** The configuration required for github interactions. */ -type GithubConfig = NgDevConfig['github']; - -/** - * Authenticated instance of Github GraphQl API service, relies on a - * personal access token being available in the TOKEN environment variable. - */ -const graphql = unauthenticatedGraphql.defaults({ - headers: { - // TODO(josephperrott): Remove reference to TOKEN environment variable as part of larger - // effort to migrate to expecting tokens via GITHUB_ACCESS_TOKEN environment variables. - authorization: `token ${process.env.TOKEN || process.env.GITHUB_ACCESS_TOKEN}`, - } -}); +import {GitClient} from './git'; /** Get a PR from github */ -export async function getPr( - prSchema: PrSchema, prNumber: number, {owner, name}: GithubConfig) { +export async function getPr(prSchema: PrSchema, prNumber: number, git: GitClient) { + /** The owner and name of the repository */ + const {owner, name} = git.remoteConfig; + /** The GraphQL query object to get a the PR */ const PR_QUERY = params( { $number: 'Int!', // The PR number @@ -41,14 +27,15 @@ export async function getPr( }) }); - const result = - await graphql(graphqlQuery(PR_QUERY), {number: prNumber, owner, name}) as typeof PR_QUERY; + const result = (await git.github.graphql.query(PR_QUERY, {number: prNumber, owner, name})); return result.repository.pullRequest; } /** Get all pending PRs from github */ -export async function getPendingPrs(prSchema: PrSchema, {owner, name}: GithubConfig) { - // The GraphQL query object to get a page of pending PRs +export async function getPendingPrs(prSchema: PrSchema, git: GitClient) { + /** The owner and name of the repository */ + const {owner, name} = git.remoteConfig; + /** The GraphQL query object to get a page of pending PRs */ const PRS_QUERY = params( { $first: 'Int', // How many entries to get with each request @@ -73,36 +60,22 @@ export async function getPendingPrs(prSchema: PrSchema, {owner, name}: }), }) }); - const query = graphqlQuery('members', PRS_QUERY); - - /** - * Gets the query and queryParams for a specific page of entries. - */ - const queryBuilder = (count: number, cursor?: string) => { - return { - query, - params: { - after: cursor || null, - first: count, - owner, - name, - }, - }; - }; - - // The current cursor + /** The current cursor */ let cursor: string|undefined; - // If an additional page of members is expected + /** If an additional page of members is expected */ let hasNextPage = true; - // Array of pending PRs + /** Array of pending PRs */ const prs: Array = []; - // For each page of the response, get the page and add it to the - // list of PRs + // For each page of the response, get the page and add it to the list of PRs while (hasNextPage) { - const {query, params} = queryBuilder(100, cursor); - const results = await graphql(query, params) as typeof PRS_QUERY; - + const params = { + after: cursor || null, + first: 100, + owner, + name, + }; + const results = await git.github.graphql.query(PRS_QUERY, params) as typeof PRS_QUERY; prs.push(...results.repository.pullRequests.nodes); hasNextPage = results.repository.pullRequests.pageInfo.hasNextPage; cursor = results.repository.pullRequests.pageInfo.endCursor; diff --git a/dev-infra/utils/inquirer-autocomplete-typings.d.ts b/dev-infra/utils/inquirer-autocomplete-typings.d.ts new file mode 100644 index 0000000000000..bddf9e2e1a20c --- /dev/null +++ b/dev-infra/utils/inquirer-autocomplete-typings.d.ts @@ -0,0 +1,17 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +// inquirer-autocomplete-prompt doesn't provide types and no types are made available via +// DefinitelyTyped. +declare module "inquirer-autocomplete-prompt" { + + import {registerPrompt} from 'inquirer'; + + let AutocompletePrompt: Parameters[1]; + export = AutocompletePrompt; +} diff --git a/dev-infra/utils/repo-files.ts b/dev-infra/utils/repo-files.ts index 7cfbc09ec4f52..b509e90fc0b57 100644 --- a/dev-infra/utils/repo-files.ts +++ b/dev-infra/utils/repo-files.ts @@ -27,6 +27,18 @@ export function allChangedFilesSince(sha = 'HEAD') { return Array.from(new Set([...diffFiles, ...untrackedFiles])); } +/** + * A list of all staged files which have been modified. + * + * Only added, created and modified files are listed as others (deleted, renamed, etc) aren't + * changed or available as content to act upon. + */ +export function allStagedFiles() { + return gitOutputAsArray(`git diff --staged --name-only --diff-filter=ACM`); +} + + + export function allFiles() { return gitOutputAsArray(`git ls-files`); } diff --git a/dev-infra/utils/testing/BUILD.bazel b/dev-infra/utils/testing/BUILD.bazel new file mode 100644 index 0000000000000..734fbc215356e --- /dev/null +++ b/dev-infra/utils/testing/BUILD.bazel @@ -0,0 +1,15 @@ +load("@npm//@bazel/typescript:index.bzl", "ts_library") + +ts_library( + name = "testing", + srcs = glob(["*.ts"]), + module_name = "@angular/dev-infra-private/utils/testing", + visibility = ["//dev-infra:__subpackages__"], + deps = [ + "//dev-infra/utils", + "@npm//@types/jasmine", + "@npm//@types/minimist", + "@npm//@types/node", + "@npm//minimist", + ], +) diff --git a/modules/playground/src/web_workers/images/index.ts b/dev-infra/utils/testing/index.ts similarity index 64% rename from modules/playground/src/web_workers/images/index.ts rename to dev-infra/utils/testing/index.ts index f3791aca9123d..30052d6e230d4 100644 --- a/modules/playground/src/web_workers/images/index.ts +++ b/dev-infra/utils/testing/index.ts @@ -6,6 +6,6 @@ * found in the LICENSE file at https://angular.io/license */ -import {bootstrapWorkerUi} from '@angular/platform-webworker'; - -bootstrapWorkerUi('loader.js'); +export * from './semver-matchers'; +export * from './virtual-git-client'; +export * from './virtual-git-matchers'; diff --git a/dev-infra/utils/testing/semver-matchers.ts b/dev-infra/utils/testing/semver-matchers.ts new file mode 100644 index 0000000000000..fa38e6af12bc4 --- /dev/null +++ b/dev-infra/utils/testing/semver-matchers.ts @@ -0,0 +1,12 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +/** Gets a jasmine asymmetric matcher for matching a given SemVer version. */ +export function matchesVersion(versionName: string) { + return jasmine.objectContaining({raw: versionName, version: versionName}); +} diff --git a/dev-infra/utils/testing/virtual-git-client.ts b/dev-infra/utils/testing/virtual-git-client.ts new file mode 100644 index 0000000000000..05d7f7d708db1 --- /dev/null +++ b/dev-infra/utils/testing/virtual-git-client.ts @@ -0,0 +1,173 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {SpawnSyncOptions, SpawnSyncReturns} from 'child_process'; +import * as parseArgs from 'minimist'; + +import {GitClient} from '../git/index'; + +/** Type describing a Git head. */ +interface GitHead { + /** Name of the head. Not defined in a detached state. */ + branch?: string; + /** Ref associated with this head. i.e. the remote base of this head. */ + ref?: RemoteRef; + /** List of commits added to this head (on top of the ref's base). */ + newCommits: Commit[]; +} + +/** Type describing a remote Git ref. */ +export interface RemoteRef { + /** Name of the reference. */ + name: string; + /** Repository containing this ref. */ + repoUrl: string; +} + +/** Type describing a Git commit. */ +export interface Commit { + /** Commit message. */ + message: string; + /** List of files included in this commit. */ + files: string[]; +} + +/** + * Virtual git client that mocks Git commands and keeps track of the repository state + * in memory. This allows for convenient test assertions with Git interactions. + */ +export class VirtualGitClient extends GitClient { + /** Current Git HEAD that has been previously fetched. */ + fetchHeadRef: RemoteRef|null = null; + /** List of known branches in the repository. */ + branches: {[branchName: string]: GitHead} = {master: {branch: 'master', newCommits: []}}; + /** Current checked out HEAD in the repository. */ + head: GitHead = this.branches['master']; + /** List of pushed heads to a given remote ref. */ + pushed: {remote: RemoteRef, head: GitHead}[] = []; + + /** Override for the actual Git client command execution. */ + runGraceful(args: string[], options: SpawnSyncOptions = {}): SpawnSyncReturns { + const [command, ...rawArgs] = args; + switch (command) { + case 'push': + this._push(rawArgs); + break; + case 'fetch': + this._fetch(rawArgs); + break; + case 'checkout': + this._checkout(rawArgs); + break; + case 'commit': + this._commit(rawArgs); + break; + } + + // Return a fake spawn sync return value. We error non-gracefully if any command fails + // in the tests, so we always return success and stub out the `SpawnSyncReturns` type. + return {status: 0, stderr: '', output: [], pid: -1, signal: null, stdout: ''}; + } + + /** Handler for the `git push` command. */ + private _push(args: string[]) { + const [repoUrl, refspec] = parseArgs(args)._; + const ref = this._unwrapRefspec(refspec); + const name = ref.destination || ref.source; + const existingPush = + this.pushed.find(({remote}) => remote.repoUrl === repoUrl && remote.name === name); + const pushedHead = this._cloneHead(this.head); + + // Either, update a previously pushed branch, or keep track of a newly + // performed branch push. We don't respect the `--force` flag. + if (existingPush !== undefined) { + existingPush.head = pushedHead; + } else { + this.pushed.push({remote: {repoUrl, name}, head: pushedHead}); + } + } + + /** Handler for the `git commit` command. */ + private _commit(rawArgs: string[]) { + const args = parseArgs(rawArgs, {string: ['m', 'message']}); + const message = args['m'] || args['message']; + const files = args._; + if (!message) { + throw Error('No commit message has been specified.'); + } + this.head.newCommits.push({message, files}); + } + + /** Handler for the `git fetch` command. */ + private _fetch(rawArgs: string[]) { + const args = parseArgs(rawArgs, {boolean: ['f', 'force']}); + const [repoUrl, refspec] = args._; + const force = args['f'] || args['force']; + const ref = this._unwrapRefspec(refspec); + + // Keep track of the fetch head, so that it can be checked out + // later in a detached state. + this.fetchHeadRef = {name: ref.source, repoUrl}; + + // If a destination has been specified in the ref spec, add it to the + // list of available local branches. + if (ref.destination) { + if (this.branches[ref.destination] && !force) { + throw Error('Cannot override existing local branch when fetching.'); + } + this.branches[ref.destination] = { + branch: ref.destination, + ref: this.fetchHeadRef, + newCommits: [], + }; + } + } + + /** Handler for the `git checkout` command. */ + private _checkout(rawArgs: string[]) { + const args = parseArgs(rawArgs, {boolean: ['detach', 'B']}); + const createBranch = args['B']; + const detached = args['detach']; + const [target] = args._; + + if (target === 'FETCH_HEAD') { + if (this.fetchHeadRef === null) { + throw Error('Unexpectedly trying to check out "FETCH_HEAD". Not fetch head set.'); + } + this.head = {ref: this.fetchHeadRef, newCommits: []}; + } else if (this.branches[target]) { + this.head = this._cloneHead(this.branches[target], detached); + } else if (createBranch) { + this.head = this.branches[target] = {branch: target, ...this._cloneHead(this.head, detached)}; + } else { + throw Error(`Unexpected branch checked out: ${target}`); + } + } + + /** + * Unwraps a refspec into the base and target ref names. + * https://git-scm.com/docs/git-fetch#Documentation/git-fetch.txt-ltrefspecgt. + */ + private _unwrapRefspec(refspec: string): {source: string, destination?: string} { + const [source, destination] = refspec.split(':'); + if (!destination) { + return {source}; + } else { + return {source, destination}; + } + } + + /** Clones the specified Git head with respect to the detached flag. */ + private _cloneHead(head: GitHead, detached = false): GitHead { + return { + branch: detached ? undefined : head.branch, + ref: head.ref, + newCommits: [...head.newCommits], + }; + } +} diff --git a/dev-infra/utils/testing/virtual-git-matchers.ts b/dev-infra/utils/testing/virtual-git-matchers.ts new file mode 100644 index 0000000000000..41c021aa6fbae --- /dev/null +++ b/dev-infra/utils/testing/virtual-git-matchers.ts @@ -0,0 +1,41 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + +import {GithubRepo} from '../git/github'; + +import {Commit} from './virtual-git-client'; + +/** Interface describing the match parameters for a virtual Git client push. */ +interface BranchPushMatchParameters { + targetRepo: GithubRepo; + targetBranch: string; + baseRepo: GithubRepo; + baseBranch: string; + expectedCommits: Commit[]|jasmine.ArrayContaining; +} + +/** + * Gets a jasmine object matcher for asserting that a virtual Git client push + * matches the specified branch push (through the match parameters). + */ +export function getBranchPushMatcher(options: BranchPushMatchParameters) { + const {targetRepo, targetBranch, baseBranch, baseRepo, expectedCommits} = options; + return jasmine.objectContaining({ + remote: { + repoUrl: `https://github.com/${targetRepo.owner}/${targetRepo.name}.git`, + name: `refs/heads/${targetBranch}` + }, + head: jasmine.objectContaining({ + newCommits: expectedCommits, + ref: { + repoUrl: `https://github.com/${baseRepo.owner}/${baseRepo.name}.git`, + name: baseBranch, + }, + }) + }); +} diff --git a/docs/CARETAKER.md b/docs/CARETAKER.md index 3ea4091b11a94..ac7a005b84dbd 100644 --- a/docs/CARETAKER.md +++ b/docs/CARETAKER.md @@ -4,71 +4,23 @@ Caretaker is responsible for merging PRs into the individual branches and intern ## Responsibilities -- Draining the queue of PRs ready to be merged. (PRs with [`PR action: merge`](https://github.com/angular/angular/pulls?q=is%3Aopen+is%3Apr+label%3A%22PR+action%3A+merge%22) label) +- Draining the queue of PRs ready to be merged. (PRs with [`action: merge`](https://github.com/angular/angular/pulls?q=is%3Aopen+is%3Apr+label%3A%22action%3A+merge%22) label) - Assigning [new issues](https://github.com/angular/angular/issues?q=is%3Aopen+is%3Aissue+no%3Alabel) to individual component authors. ## Merging the PR -A PR needs to have `PR action: merge` and `PR target: *` labels to be considered -ready to merge. Merging is performed by running `merge-pr` with a PR number to merge. +A PR needs to have `action: merge` and `target: *` labels to be considered +ready to merge. Merging is performed by running `ng-dev pr merge` with a PR number to merge. + +The tooling automatically verifies the given PR is ready for merge. If the PR passes the tests, the +tool will automatically merge it based on the applied target label. To merge a PR run: ``` -$ ./scripts/github/merge-pr 1234 +$ yarn ng-dev pr merge ``` -The `merge-pr` script will: -- Ensure that all appropriate labels are on the PR. -- Fetches the latest PR code from the `angular/angular` repo. -- It will `cherry-pick` all of the SHAs from the PR into the current corresponding branches `master` and or `?.?.x` (patch). -- It will rewrite commit history by automatically adding `Close #1234` and `(#1234)` into the commit message. - -NOTE: The `merge-pr` will land the PR on `master` and or `?.?.x` (patch) as described by `PR target: *` label. - ### Recovering from failed `merge-pr` due to conflicts -When running `merge-pr` the script will output the commands which it is about to run. - -``` -$ ./scripts/github/merge-pr 1234 -====================== -GitHub Merge PR Steps -====================== - git cherry-pick angular/pr/1234~1..angular/pr/1234 - git filter-branch -f --msg-filter "/home/misko/angular/scripts/github/utils/github.closes 1234" HEAD~1..HEAD -``` - -If the `cherry-pick` command fails than resolve conflicts and use `git cherry-pick --continue` once ready. After the `cherry-pick` is done cut&paste and run the `filter-branch` command to properly rewrite the messages - -## Cherry-picking PRs into patch branch - -In addition to merging PRs into the master branch, many PRs need to be also merged into a patch branch. -Follow these steps to get patch branch up to date. - -1. Check out the most recent patch branch: `git checkout 4.3.x` -2. Get a list of PRs merged into master: `git log master --oneline -n10` -3. For each PR number in the commit message run: `./scripts/github/merge-pr 1234` - - The PR will only merge if the `PR target:` matches the branch. - -Once all of the PRs are in patch branch, push the all branches and tags to github using `push-upstream` script. - - -## Pushing merged PRs into github - -Use `push-upstream` script to push all of the branch and tags to github. - -``` -$ ./scripts/github/push-upstream -git push git@github.com:angular/angular.git master:master 4.3.x:4.3.x -Counting objects: 25, done. -Delta compression using up to 6 threads. -Compressing objects: 100% (17/17), done. -Writing objects: 100% (25/25), 2.22 KiB | 284.00 KiB/s, done. -Total 25 (delta 22), reused 8 (delta 7) -remote: Resolving deltas: 100% (22/22), completed with 18 local objects. -To github.com:angular/angular.git - 079d884b6..d1c4a94bb master -> master -git push --tags -f git@github.com:angular/angular.git patch_sync:patch_sync -Everything up-to-date -``` +The `ng-dev pr merge` tool will automatically restore to the previous git state when a merge fails. diff --git a/docs/COMMITTER.md b/docs/COMMITTER.md index 77b1dc8e3886f..91abbb4c6608e 100644 --- a/docs/COMMITTER.md +++ b/docs/COMMITTER.md @@ -12,7 +12,7 @@ Change approvals in our monorepo are managed via [PullApprove](https://docs.pull # Merging Once a change has all of the required approvals, either the last approver or the PR author (if PR author has the project collaborator status) -should mark the PR with the `PR action: merge` label and the correct [target label](https://github.com/angular/angular/blob/master/docs/TRIAGE_AND_LABELS.md#pr-target). +should mark the PR with the `action: merge` label and the correct [target label](https://github.com/angular/angular/blob/master/docs/TRIAGE_AND_LABELS.md#pr-target). This signals to the caretaker that the PR should be merged. See [merge instructions](CARETAKER.md). # Who is the Caretaker? diff --git a/docs/DEBUG_COMPONENTS_REPO_IVY.md b/docs/DEBUG_COMPONENTS_REPO_IVY.md index 59feffafb8d86..16bed8268f0bc 100644 --- a/docs/DEBUG_COMPONENTS_REPO_IVY.md +++ b/docs/DEBUG_COMPONENTS_REPO_IVY.md @@ -4,7 +4,7 @@ Currently all changes to Ivy are validated against the test suite of the `angular/components` repository. In order to debug the `components-repo-unit-tests` CI job, the following steps can be used: -1\) Build the Ivy package output by running `node ./scripts/build/build-ivy-npm-packages.js` in +1\) Build the Ivy package output by running `node ./scripts/build/build-packages-dist.js` in the `angular/angular` repo. 2\) Clone the `angular/components` repository if not done yet ([quick link to repo](https://github.com/angular/components)). @@ -13,7 +13,7 @@ the `angular/angular` repo. command in the `angular/angular` repo: ```bash -node ./scripts/ci/update-deps-to-dist-packages.js {COMPONENTS_REPO}/package.json ./dist/packages-dist-ivy-aot +node ./scripts/ci/update-deps-to-dist-packages.js {COMPONENTS_REPO}/package.json ./dist/packages-dist ``` 4\) Switch into the `angular/components` repository and run the tests by using the diff --git a/docs/DEVELOPER.md b/docs/DEVELOPER.md index 0cb401ab7aac7..346fa3f200d48 100644 --- a/docs/DEVELOPER.md +++ b/docs/DEVELOPER.md @@ -154,9 +154,7 @@ available as a long-term distribution mechanism, but they are guaranteed to be a time of the build. You can access the artifacts for a specific CI run by going to the workflow page, clicking on the -`publish_packages_as_artifacts` job and then switching to the "Artifacts" tab. -(If you happen to know the build number of the job, the URL will be something like: -`https://circleci.com/gh/angular/angular/#artifacts`) +`publish_packages_as_artifacts` job and then switching to the "ARTIFACTS" tab. #### Archives for each Package On the "Artifacts" tab, there is a list of links to compressed archives for Angular packages. The diff --git a/docs/FIXUP_COMMITS.md b/docs/FIXUP_COMMITS.md new file mode 100644 index 0000000000000..c32a91ef3d708 --- /dev/null +++ b/docs/FIXUP_COMMITS.md @@ -0,0 +1,95 @@ +# Working with fixup commits + +This document provides information and guidelines for working with fixup commits: +- [What are fixup commits](#about-fixup-commits) +- [Why use fixup commits](#why-fixup-commits) +- [Creating fixup commits](#create-fixup-commits) +- [Squashing fixup commits](#squash-fixup-commits) + +[This blog post](https://thoughtbot.com/blog/autosquashing-git-commits) is also a good resource on the subject. + + +## What are fixup commits + +At their core, fixup commits are just regular commits with a special commit message: +The first line of their commit message starts with "fixup! " (notice the space after "!") followed by the first line of the commit message of an earlier commit (it doesn't have to be the immediately preceding one). + +The purpose of a fixup commit is to modify an earlier commit. +I.e. it allows adding more changes in a new commit, but "marking" them as belonging to an earlier commit. +`Git` provides tools to make it easy to squash fixup commits into the original commit at a later time (see [below](#squash-fixup-commits) for details). + +For example, let's assume you have added the following commits to your branch: + +``` +feat: first commit +fix: second commit +``` + +If you want to add more changes to the first commit, you can create a new commit with the commit message: +`fixup! feat: first commit`: + +``` +feat: first commit +fix: second commit +fixup! feat: first commit +``` + + +## Why use fixup commits + +So, when are fixup commits useful? + +During the life of a Pull Request, a reviewer might request changes. +The Pull Request author can make the requested changes and submit them for another review. +Normally, these changes should be part of one of the original commits of the Pull Request. +However, amending an existing commit with the changes makes it difficult for the reviewer to know exactly what has changed since the last time they reviewed the Pull Request. + +Here is where fixup commits come in handy. +By addressing review feedback in fixup commits, you make it very straight forward for the reviewer to see what are the new changes that need to be reviewed and verify that their earlier feedback has been addressed. +This can save a lot of effort, especially on larger Pull Requests (where having to re-review _all_ the changes is pretty wasteful). + +When the time comes to merge the Pull Request into the repository, the merge script [knows how to automatically squash](../dev-infra/pr/merge/strategies/autosquash-merge.ts) fixup commits with the corresponding regular commits. + + +## Creating fixup commits + +As mentioned [above](#about-fixup-commits), the only thing that differentiates a fixup commit from a regular commit is the commit message. +You can create a fixup commit by specifying an appropriate commit message (i.e. `fixup! `). + +In addition, the `git` command-line tool provides an easy way to create a fixup commit via [git commit --fixup](https://git-scm.com/docs/git-commit#Documentation/git-commit.txt---fixupltcommitgt): + +```sh +# Create a fixup commit to fix up the last commit on the branch: +git commit --fixup HEAD ... + +# Create a fixup commit to fix up commit with SHA : +git commit --fixup ... +``` + + +## Squashing fixup commits + +As mentioned above, the merge script will [automatically squash](../dev-infra/pr/merge/strategies/autosquash-merge.ts) fixup commits. +However, sometimes you might want to manually squash a fixup commit. + + +### Rebasing to squash fixup commits + +The easiest way to re-order and squash any commit is via [rebasing interactively](https://git-scm.com/docs/git-rebase#_interactive_mode). You move a commit right after the one you want to squash it into in the rebase TODO list and change the corresponding action from `pick` to `fixup`. + +`Git` can do all these automatically for you if you pass the `--autosquash` option to `git rebase`. +See the [`git` docs](https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---autosquash) for more details. + + +### Additional options + +You may like to consider some optional configurations: + + +#### Configuring `git` to auto-squash by default + +By default, `git` will not automatically squash fixup commits when interactively rebasing. +If you prefer to not have to pass the `--autosquash` option every time, you can change the default behavior by setting the `rebase.autoSquash` `git` config option to true. +See the [`git` docs](https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt-rebaseautoSquash) for more details. + +If you have `rebase.autoSquash` set to true, you can pass the `--no-autosquash` option to `git rebase` to override and disable this setting. diff --git a/docs/PUBLIC_API.md b/docs/PUBLIC_API.md index dc592c378817e..d4f96a44d0ed9 100644 --- a/docs/PUBLIC_API.md +++ b/docs/PUBLIC_API.md @@ -10,8 +10,6 @@ Our semver, timed-release cycle and deprecation policy currently applies to thes - `@angular/platform-browser` - `@angular/platform-browser-dynamic` - `@angular/platform-server` -- `@angular/platform-webworker` -- `@angular/platform-webworker-dynamic` - `@angular/upgrade` - `@angular/router` - `@angular/service-worker` @@ -79,10 +77,10 @@ INFO: From Testing //packages/core:core_api: ngModule: Type; providers?: Provider[]; } - + -export declare type NgIterable = Array | Iterable; +export declare type NgIterable = Iterable; - + export declare interface NgModule { bootstrap?: Array | any[]>; declarations?: Array | any[]>; diff --git a/docs/TRIAGE_AND_LABELS.md b/docs/TRIAGE_AND_LABELS.md index aa23e674c45fe..c41f469bd2eca 100644 --- a/docs/TRIAGE_AND_LABELS.md +++ b/docs/TRIAGE_AND_LABELS.md @@ -1,8 +1,8 @@ # Triage Process and GitHub Labels for Angular -This document describes how the Angular team uses labels and milestones to triage issues on github. +This document describes how the Angular team uses labels and milestones to triage issues on GitHub. The basic idea of the process is that caretaker only assigns a component (`comp: *`) label. -The owner of the component is then responsible for the secondary / component-level triage. +The owner of the component is then responsible for the detailed / component-level triage. ## Label Types @@ -10,7 +10,8 @@ The owner of the component is then responsible for the secondary / component-lev ### Components The caretaker should be able to determine which component the issue belongs to. -The components have a clear piece of source code associated with it within the `/packages/` folder of this repo. +The components have a clear piece of source code associated with it within the `/packages/` folder +of this repo. * `comp: animations` * `comp: bazel` - @angular/bazel rules @@ -48,109 +49,105 @@ We will treat them as a component even thought no specific source tree is associ * `comp: performance` * `comp: security` -Sometimes, especially in the case of cross-cutting issues or PRs, these PRs or issues belong to multiple components. -In these cases, all applicable component labels should be used to triage the issue or PR. +Sometimes, especially in the case of cross-cutting issues or PRs, these PRs or issues belong to +multiple components. In these cases, all applicable component labels should be used to triage the +issue or PR. +## Caretaker Triage Process (Initial Triage) -### Type +The caretaker assigns `comp: *` labels to new issues as they come in. +Untriaged issues can be found by selecting the issues with no milestone. -What kind of problem is this? +If an issue or PR obviously relates to a release regression, the caretaker must assign an +appropriate priority (`P0` or `P1`) and ensure that someone from the team is actively working to +resolve it. -* `type: RFC / discussion / question` -* `type: bug` -* `type: docs` -* `type: feature` -* `type: performance` -* `type: refactor` -* `type: use-case` -* `type: confusing` +Initial triage should occur daily so that issues can move into detailed triage. +Once the initial triage is done, the ng-bot automatically adds the milestone `needs triage`. -## Caretaker Triage Process (Primary Triage) +## Detailed Triage -It is the caretaker's responsibility to assign `comp: *` to each new issue as they come in. -Issues that haven't been triaged can be found by selecting the issues with no milestone. +Detailed triage can be done by anyone familiar with the issue subject matter. -If it's obvious that the issue or PR is related to a release regression, the caretaker is also responsible for assigning the `severity(5): regression` label to make the issue or PR highly visible. +### Step 1: Does the issue have enough information? -The primary triage should be done on a daily basis so that the issues become available for secondary triage without much of delay. +Gauge whether the issue has enough information to act upon. This typically includes a test case +via StackBlitz or GitHub and steps to reproduce. If the issue may be legitimate but needs more +information, add the "needs clarification" label. These labels can be revisted if the author can +provide further clarification. If the issue does have enough information, move on to step 2. -The reason why we limit the responsibility of the caretaker to this one label is that it is likely that without domain knowledge the caretaker could mislabel issues or lack knowledge of duplicate issues. +### Step 2: Bug, feature, or discussion? -Once the primary triage is done, the ng-bot automatically adds the milestone `needsTriage`. +By default, all issues are considered bugs. Bug reports require only a priority label. +If the issue is a feature request, apply the "feature" label. Use your judgement to determine +whether the feature request is reasonable. If it's clear that the issue requests something +infeasible, close the issue with a comment explaining why. -## Component's owner Triage Process +If the issue is an RFC or discussion, apply the "discussion" label. Use your judgement to determine +whether this discussion belongs on GitHub. Discussions here should pertain to the technical +implementation details of Angular. Redirect requests for debugging help or advice to a more +appropriate channel unless they're capturing a legitimate bug. -The component owner is responsible for assigning one of the labels from each of these categories to the issues that have the milestone `needsTriage`: +### Step 3: Set a Priority -- `type: *` -- `frequency: *` (only required for `type: bug/fix`) -- `severity: *` (only required for `type: bug/fix`) +For bug reports, set a priority label. -We've adopted the issue categorization based on [user pain](http://www.lostgarden.com/2008/05/improving-bug-triage-with-user-pain.html) used by AngularJS. In this system every issue is assigned frequency and severity based on which the total user pain score is calculated. +| Label | Description | +|----|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| P0 | An issue that causes a full outage, breakage, or major function unavailability for everyone, without any known workaround. The issue must be fixed immediately, taking precedence over all other work. Should receive updates at least once per day. | +| P1 | An issue that significantly impacts a large percentage of users; if there is a workaround it is partial or overly painful. The issue should be resolved before the next release. | +| P2 | The issue is important to a large percentage of users, with a workaround. Issues that are significantly ugly or painful (especially first-use or install-time issues). Issues with workarounds that would otherwise be P0 or P1. | +| P3 | An issue that is relevant to core functions, but does not impede progress. Important, but not urgent. | +| P4 | A relatively minor issue that is not relevant to core functions, or relates only to the attractiveness or pleasantness of use of the system. Good to have but not necessary changes/fixes. | +| P5 | The team acknowledges the request but (due to any number of reasons) does not plan to work on or accept contributions for this request. The issue remains open for discussion. | -The issues with type `type: feature`, `type: refactor` and `type: RFC / Discussion / question` do not require a frequency and severity. -Following is the definition of various frequency and severity levels: +Issues marked with "feature" or "discussion" don't require a priority. -1. `freq(score): *` – How often does this issue come up? How many developers does this affect? - * low (1) - obscure issue affecting a handful of developers - * moderate (2) - impacts auxiliary usage patterns, only small number of applications are affected - * high (3) - impacts primary usage patterns, affecting most Angular apps - * critical (4) - impacts all Angular apps -1. `severity(score): *` - How bad is the issue? - * inconvenience (1) - causes ugly/boilerplate code in apps - * confusing (2) - unexpected or inconsistent behavior; hard-to-debug - * broken expected use (3) - it's hard or impossible for a developer using Angular to accomplish something that Angular should be able to do - * memory leak (4) - * regression (5) - functionality that used to work no longer works in a new release due to an unintentional change - * security issue (6) +### Step 4: Apply additional information labels +Many optional labels provide additional context for issues. Consider adding any of the following if +they apply to the issue: -These criteria are then used to calculate a "user pain" score as follows: +* Browser or operating system labels (`windows`, `ie11`, etc.) +* Labels that inform the severity (`regression`, `has workaround`, `no workaround`) +* Labels that categorize the bug (`performance`, `refactoring`, `memory leak`) +* Community engagement labels (`good first issue`) -`pain = severity × frequency` - -This score can then be used to estimate the impact of the issue which helps with prioritization. - -Once the component's owner triage is done, the ng-bot automatically changes the milestone from `needsTriage` to `Backlog`. +Once this triage is done, the ng-bot automatically changes the milestone from `needs triage` to +`Backlog`. ## Triaging PRs -Triaging PRs is the same as triaging issues, except that the labels `frequency: *` and `severity: *` are replaced by: -- `effort*` -- `risk: *` - -PRs also have additional label categories that should be used to signal their state. +PRs labels signal their state. Every triaged PR must have a `action: *` label assigned to it: -Every triaged PR must have a `PR action` label assigned to it: - -* `PR action: discuss`: Discussion is needed, to be led by the author. +* `action: discuss`: Discussion is needed, to be led by the author. * _**Who adds it:** Typically the PR author._ * _**Who removes it:** Whoever added it._ -* `PR action: review` (optional): One or more reviews are pending. The label is optional, since the review status can be derived from GitHub's Reviewers interface. +* `action: review` (optional): One or more reviews are pending. The label is optional, since the review status can be derived from GitHub's Reviewers interface. * _**Who adds it:** Any team member. The caretaker can use it to differentiate PRs pending review from merge-ready PRs._ * _**Who removes it:** Whoever added it or the reviewer adding the last missing review._ -* `PR action: cleanup`: More work is needed from the author. +* `action: cleanup`: More work is needed from the author. * _**Who adds it:** The reviewer requesting changes to the PR._ * _**Who removes it:** Either the author (after implementing the requested changes) or the reviewer (after confirming the requested changes have been implemented)._ -* `PR action: merge`: The PR author is ready for the changes to be merged by the caretaker as soon as the PR is green (or merge-assistance label is applied and caretaker has deemed it acceptable manually). In other words, this label indicates to "auto submit when ready". +* `action: merge`: The PR author is ready for the changes to be merged by the caretaker as soon as the PR is green (or merge-assistance label is applied and caretaker has deemed it acceptable manually). In other words, this label indicates to "auto submit when ready". * _**Who adds it:** Typically the PR author._ * _**Who removes it:** Whoever added it._ In addition, PRs can have the following states: -* `PR state: WIP`: PR is experimental or rapidly changing. Not ready for review or triage. +* `state: WIP`: PR is experimental or rapidly changing. Not ready for review or triage. * _**Who adds it:** The PR author._ * _**Who removes it:** Whoever added it._ -* `PR state: blocked`: PR is blocked on an issue or other PR. Not ready for merge. +* `state: blocked`: PR is blocked on an issue or other PR. Not ready for merge. * _**Who adds it:** Any team member._ * _**Who removes it:** Any team member._ -When a PR is ready for review, a review should be requested using the Reviewers interface in Github. +When a PR is ready for review, a review should be requested using the Reviewers interface in GitHub. ## PR Target @@ -160,15 +157,29 @@ In our git workflow, we merge changes either to the `master` branch, the active The decision about the target must be done by the PR author and/or reviewer. This decision is then honored when the PR is being merged by the caretaker. -To communicate the target we use the following labels: +To communicate the target we use GitHub labels and only one target label may be applied to a PR. + +Targeting an active release train: + +* `target: major`: Any breaking change +* `target: minor`: Any new feature +* `target: patch`: Bug fixes, refactorings, documentation changes, etc. that pose no or very low risk of adversely + affecting existing applications. + +Special Cases: +* `target: rc`: A critical fix for an active release-train while it is in a feature freeze or RC phase +* `target: lts`: A criticial fix for a specific release-train that is still within the long term support phase + + +Notes: + - To land a change only in a patch/RC branch, without landing it in any other active release-train branch (such + as `master`), the patch/RC branch can be targeted in the GitHub UI with the appropriate + `target: patch`/`target: rc` label. + - `target: lts` PRs must target the specific LTS branch they would need to merge into in the GitHub UI, in + cases which a change is desired in multiple LTS branches, individual PRs for each LTS branch must be created -* `PR target: master & patch`: the PR should me merged into the master branch and cherry-picked into the most recent patch branch. All PRs with fixes, docs and refactorings should use this target. -* `PR target: master-only`: the PR should be merged only into the `master` branch. All PRs with new features, API changes or high-risk changes should use this target. -* `PR target: patch-only`: the PR should be merged only into the most recent patch branch (e.g. 5.0.x). This target is useful if a `master & patch` PR can't be cleanly cherry-picked into the stable branch and a new PR is needed. -* `PR target: LTS-only`: the PR should be merged only into the active LTS branch(es). Only security and critical fixes are allowed in these branches. Always send a new PR targeting just the LTS branch and request review approval from @IgorMinar. -* `PR target: TBD`: the target is yet to be determined. -If a PR is missing the `PR target: *` label, or if the label is set to "TBD" when the PR is sent to the caretaker, the caretaker should reject the PR and request the appropriate target label to be applied before the PR is merged. +If a PR is missing the `target:*` label, it will be marked as pending by the angular robot status checks. ## PR Approvals @@ -182,7 +193,7 @@ In any case, the reviewer should actually look through the code and provide feed Note that approved state does not mean a PR is ready to be merged. For example, a reviewer might approve the PR but request a minor tweak that doesn't need further review, e.g., a rebase or small uncontroversial change. -Only the `PR action: merge` label means that the PR is ready for merging. +Only the `action: merge` label means that the PR is ready for merging. ## Special Labels @@ -201,7 +212,7 @@ Only issues with `cla:yes` should be merged into master. Applying this label to a PR makes the angular.io preview available regardless of the author. [More info](../aio/aio-builds-setup/docs/overview--security-model.md) -### `PR action: merge-assistance` +### `action: merge-assistance` * _**Who adds it:** Any team member._ * _**Who removes it:** Any team member._ @@ -211,7 +222,7 @@ The comment should be formatted like this: `merge-assistance: ; export declare class AsyncPipe implements OnDestroy, PipeTransform { constructor(_ref: ChangeDetectorRef); ngOnDestroy(): void; - transform(obj: null): null; - transform(obj: undefined): undefined; - transform(obj: Observable | null | undefined): T | null; - transform(obj: Promise | null | undefined): T | null; + transform(obj: Observable | Promise): T | null; + transform(obj: null | undefined): null; + transform(obj: Observable | Promise | null | undefined): T | null; } export declare class CommonModule { @@ -14,17 +13,23 @@ export declare class CommonModule { export declare class CurrencyPipe implements PipeTransform { constructor(_locale: string, _defaultCurrencyCode?: string); - transform(value: any, currencyCode?: string, display?: 'code' | 'symbol' | 'symbol-narrow' | string | boolean, digitsInfo?: string, locale?: string): string | null; + transform(value: number | string, currencyCode?: string, display?: 'code' | 'symbol' | 'symbol-narrow' | string | boolean, digitsInfo?: string, locale?: string): string | null; + transform(value: null | undefined, currencyCode?: string, display?: 'code' | 'symbol' | 'symbol-narrow' | string | boolean, digitsInfo?: string, locale?: string): null; + transform(value: number | string | null | undefined, currencyCode?: string, display?: 'code' | 'symbol' | 'symbol-narrow' | string | boolean, digitsInfo?: string, locale?: string): string | null; } export declare class DatePipe implements PipeTransform { constructor(locale: string); - transform(value: any, format?: string, timezone?: string, locale?: string): string | null; + transform(value: Date | string | number, format?: string, timezone?: string, locale?: string): string | null; + transform(value: null | undefined, format?: string, timezone?: string, locale?: string): null; + transform(value: Date | string | number | null | undefined, format?: string, timezone?: string, locale?: string): string | null; } export declare class DecimalPipe implements PipeTransform { constructor(_locale: string); - transform(value: any, digitsInfo?: string, locale?: string): string | null; + transform(value: number | string, digitsInfo?: string, locale?: string): string | null; + transform(value: null | undefined, digitsInfo?: string, locale?: string): null; + transform(value: number | string | null | undefined, digitsInfo?: string, locale?: string): string | null; } export declare const DOCUMENT: InjectionToken; @@ -61,13 +66,13 @@ export declare function getLocaleDateFormat(locale: string, width: FormatWidth): export declare function getLocaleDateTimeFormat(locale: string, width: FormatWidth): string; -export declare function getLocaleDayNames(locale: string, formStyle: FormStyle, width: TranslationWidth): string[]; +export declare function getLocaleDayNames(locale: string, formStyle: FormStyle, width: TranslationWidth): ReadonlyArray; -export declare function getLocaleDayPeriods(locale: string, formStyle: FormStyle, width: TranslationWidth): [string, string]; +export declare function getLocaleDayPeriods(locale: string, formStyle: FormStyle, width: TranslationWidth): Readonly<[string, string]>; export declare function getLocaleDirection(locale: string): 'ltr' | 'rtl'; -export declare function getLocaleEraNames(locale: string, width: TranslationWidth): [string, string]; +export declare function getLocaleEraNames(locale: string, width: TranslationWidth): Readonly<[string, string]>; export declare function getLocaleExtraDayPeriodRules(locale: string): (Time | [Time, Time])[]; @@ -77,7 +82,7 @@ export declare function getLocaleFirstDayOfWeek(locale: string): WeekDay; export declare function getLocaleId(locale: string): string; -export declare function getLocaleMonthNames(locale: string, formStyle: FormStyle, width: TranslationWidth): string[]; +export declare function getLocaleMonthNames(locale: string, formStyle: FormStyle, width: TranslationWidth): ReadonlyArray; export declare function getLocaleNumberFormat(locale: string, type: NumberFormatStyle): string; @@ -105,7 +110,7 @@ export declare class HashLocationStrategy extends LocationStrategy { export declare class I18nPluralPipe implements PipeTransform { constructor(_localization: NgLocalization); - transform(value: number, pluralMap: { + transform(value: number | null | undefined, pluralMap: { [count: string]: string; }, locale?: string): string; } @@ -135,21 +140,13 @@ export declare interface KeyValue { export declare class KeyValuePipe implements PipeTransform { constructor(differs: KeyValueDiffers); - transform(input: null, compareFn?: (a: KeyValue, b: KeyValue) => number): null; - transform(input: { - [key: string]: V; - } | ReadonlyMap, compareFn?: (a: KeyValue, b: KeyValue) => number): Array>; - transform(input: { - [key: string]: V; - } | ReadonlyMap | null, compareFn?: (a: KeyValue, b: KeyValue) => number): Array> | null; - transform(input: { - [key: number]: V; - } | ReadonlyMap, compareFn?: (a: KeyValue, b: KeyValue) => number): Array>; - transform(input: { - [key: number]: V; - } | ReadonlyMap | null, compareFn?: (a: KeyValue, b: KeyValue) => number): Array> | null; transform(input: ReadonlyMap, compareFn?: (a: KeyValue, b: KeyValue) => number): Array>; - transform(input: ReadonlyMap | null, compareFn?: (a: KeyValue, b: KeyValue) => number): Array> | null; + transform(input: Record, compareFn?: (a: KeyValue, b: KeyValue) => number): Array>; + transform(input: Record | ReadonlyMap, compareFn?: (a: KeyValue, b: KeyValue) => number): Array>; + transform(input: null | undefined, compareFn?: (a: KeyValue, b: KeyValue) => number): null; + transform(input: ReadonlyMap | null | undefined, compareFn?: (a: KeyValue, b: KeyValue) => number): Array> | null; + transform(input: Record | null | undefined, compareFn?: (a: KeyValue, b: KeyValue) => number): Array> | null; + transform(input: Record | ReadonlyMap | null | undefined, compareFn?: (a: KeyValue, b: KeyValue) => number): Array> | null; } export declare class Location { @@ -194,6 +191,8 @@ export declare abstract class LocationStrategy { export declare class LowerCasePipe implements PipeTransform { transform(value: string): string; + transform(value: null | undefined): null; + transform(value: string | null | undefined): string | null; } export declare class NgClass implements DoCheck { @@ -216,7 +215,7 @@ export declare class NgComponentOutlet implements OnChanges, OnDestroy { } export declare class NgForOf = NgIterable> implements DoCheck { - set ngForOf(ngForOf: (U & NgIterable) | undefined | null); + set ngForOf(ngForOf: U & NgIterable | undefined | null); set ngForTemplate(value: TemplateRef>); set ngForTrackBy(fn: TrackByFunction); get ngForTrackBy(): TrackByFunction; @@ -339,7 +338,9 @@ export declare class PathLocationStrategy extends LocationStrategy { export declare class PercentPipe implements PipeTransform { constructor(_locale: string); - transform(value: any, digitsInfo?: string, locale?: string): string | null; + transform(value: number | string, digitsInfo?: string, locale?: string): string | null; + transform(value: null | undefined, digitsInfo?: string, locale?: string): null; + transform(value: number | string | null | undefined, digitsInfo?: string, locale?: string): string | null; } export declare abstract class PlatformLocation { @@ -380,9 +381,10 @@ export declare function registerLocaleData(data: any, localeId?: string | any, e export declare class SlicePipe implements PipeTransform { transform(value: ReadonlyArray, start: number, end?: number): Array; + transform(value: null | undefined, start: number, end?: number): null; + transform(value: ReadonlyArray | null | undefined, start: number, end?: number): Array | null; transform(value: string, start: number, end?: number): string; - transform(value: null, start: number, end?: number): null; - transform(value: undefined, start: number, end?: number): undefined; + transform(value: string | null | undefined, start: number, end?: number): string | null; } export declare type Time = { @@ -392,6 +394,8 @@ export declare type Time = { export declare class TitleCasePipe implements PipeTransform { transform(value: string): string; + transform(value: null | undefined): null; + transform(value: string | null | undefined): string | null; } export declare enum TranslationWidth { @@ -403,6 +407,8 @@ export declare enum TranslationWidth { export declare class UpperCasePipe implements PipeTransform { transform(value: string): string; + transform(value: null | undefined): null; + transform(value: string | null | undefined): string | null; } export declare const VERSION: Version; diff --git a/goldens/public-api/common/http/http.d.ts b/goldens/public-api/common/http/http.d.ts index dc83116d82988..668d6c76a7b96 100644 --- a/goldens/public-api/common/http/http.d.ts +++ b/goldens/public-api/common/http/http.d.ts @@ -1177,6 +1177,10 @@ export declare class HttpClient { [header: string]: string | string[]; }; observe: 'events'; + params?: HttpParams | { + [param: string]: string | string[]; + }; + reportProgress?: boolean; responseType?: 'json'; withCredentials?: boolean; }): Observable>; diff --git a/goldens/public-api/common/http/testing/testing.d.ts b/goldens/public-api/common/http/testing/testing.d.ts index 6e896345e2e49..8143ffd6a0347 100644 --- a/goldens/public-api/common/http/testing/testing.d.ts +++ b/goldens/public-api/common/http/testing/testing.d.ts @@ -33,7 +33,7 @@ export declare class TestRequest { statusText?: string; }): void; event(event: HttpEvent): void; - flush(body: ArrayBuffer | Blob | string | number | Object | (string | number | Object | null)[] | null, opts?: { + flush(body: ArrayBuffer | Blob | boolean | string | number | Object | (boolean | string | number | Object | null)[] | null, opts?: { headers?: HttpHeaders | { [name: string]: string | string[]; }; diff --git a/goldens/public-api/compiler-cli/compiler_options.d.ts b/goldens/public-api/compiler-cli/compiler_options.d.ts index 92723d30509d5..2c462d513a4ce 100644 --- a/goldens/public-api/compiler-cli/compiler_options.d.ts +++ b/goldens/public-api/compiler-cli/compiler_options.d.ts @@ -35,6 +35,7 @@ export interface StrictTemplateOptions { strictContextGenerics?: boolean; strictDomEventTypes?: boolean; strictDomLocalRefTypes?: boolean; + strictInputAccessModifiers?: boolean; strictInputTypes?: boolean; strictLiteralTypes?: boolean; strictNullInputTypes?: boolean; diff --git a/goldens/public-api/compiler-cli/error_code.d.ts b/goldens/public-api/compiler-cli/error_code.d.ts index 41ad7164771fe..b9ed59e4694ca 100644 --- a/goldens/public-api/compiler-cli/error_code.d.ts +++ b/goldens/public-api/compiler-cli/error_code.d.ts @@ -19,6 +19,7 @@ export declare enum ErrorCode { CONFIG_FLAT_MODULE_NO_INDEX = 4001, CONFIG_STRICT_TEMPLATES_IMPLIES_FULL_TEMPLATE_TYPECHECK = 4002, HOST_BINDING_PARSE_ERROR = 5001, + TEMPLATE_PARSE_ERROR = 5002, NGMODULE_INVALID_DECLARATION = 6001, NGMODULE_INVALID_IMPORT = 6002, NGMODULE_INVALID_EXPORT = 6003, diff --git a/goldens/public-api/core/core.d.ts b/goldens/public-api/core/core.d.ts index 6334c6632a950..0bbed1ad0209c 100644 --- a/goldens/public-api/core/core.d.ts +++ b/goldens/public-api/core/core.d.ts @@ -85,10 +85,6 @@ export declare interface ClassSansProvider { useClass: Type; } -/** @deprecated */ -export declare interface CollectionChangeRecord extends IterableChangeRecord { -} - export declare class Compiler { compileModuleAndAllComponentsAsync: (moduleType: Type) => Promise>; compileModuleAndAllComponentsSync: (moduleType: Type) => ModuleWithComponentFactories; @@ -803,7 +799,7 @@ export declare abstract class Renderer2 { abstract createElement(name: string, namespace?: string | null): any; abstract createText(value: string): any; abstract destroy(): void; - abstract insertBefore(parent: any, newChild: any, refChild: any): void; + abstract insertBefore(parent: any, newChild: any, refChild: any, isMove?: boolean): void; abstract listen(target: 'window' | 'document' | 'body' | any, eventName: string, callback: (event: any) => boolean | void): () => void; abstract nextSibling(node: any): any; abstract parentNode(node: any): any; @@ -1036,7 +1032,6 @@ export declare abstract class ViewContainerRef { export declare enum ViewEncapsulation { Emulated = 0, - Native = 1, None = 2, ShadowDom = 3 } diff --git a/goldens/public-api/elements/elements.d.ts b/goldens/public-api/elements/elements.d.ts index 04f108ca60e4f..baafc1693d888 100644 --- a/goldens/public-api/elements/elements.d.ts +++ b/goldens/public-api/elements/elements.d.ts @@ -2,7 +2,7 @@ export declare function createCustomElement

      (component: Type, config: NgE export declare abstract class NgElement extends HTMLElement { protected ngElementEventsSubscription: Subscription | null; - protected ngElementStrategy: NgElementStrategy; + protected abstract ngElementStrategy: NgElementStrategy; abstract attributeChangedCallback(attrName: string, oldValue: string | null, newValue: string, namespace?: string): void; abstract connectedCallback(): void; abstract disconnectedCallback(): void; diff --git a/goldens/public-api/forms/forms.d.ts b/goldens/public-api/forms/forms.d.ts index 5733623c01fa1..87df5fcc7452d 100644 --- a/goldens/public-api/forms/forms.d.ts +++ b/goldens/public-api/forms/forms.d.ts @@ -6,7 +6,7 @@ export declare abstract class AbstractControl { get enabled(): boolean; readonly errors: ValidationErrors | null; get invalid(): boolean; - get parent(): FormGroup | FormArray; + get parent(): FormGroup | FormArray | null; get pending(): boolean; readonly pristine: boolean; get root(): AbstractControl; @@ -199,7 +199,7 @@ export declare class FormArrayName extends ControlContainer implements OnInit, O name: string | number | null; get path(): string[]; get validator(): ValidatorFn | null; - constructor(parent: ControlContainer, validators: any[], asyncValidators: any[]); + constructor(parent: ControlContainer, validators: (Validator | ValidatorFn)[], asyncValidators: (AsyncValidator | AsyncValidatorFn)[]); ngOnDestroy(): void; ngOnInit(): void; } @@ -246,7 +246,7 @@ export declare class FormControlDirective extends NgControl implements OnChanges /** @deprecated */ update: EventEmitter; get validator(): ValidatorFn | null; viewModel: any; - constructor(validators: Array, asyncValidators: Array, valueAccessors: ControlValueAccessor[], _ngModelWarningConfig: string | null); + constructor(validators: (Validator | ValidatorFn)[], asyncValidators: (AsyncValidator | AsyncValidatorFn)[], valueAccessors: ControlValueAccessor[], _ngModelWarningConfig: string | null); ngOnChanges(changes: SimpleChanges): void; viewToModelUpdate(newValue: any): void; } @@ -261,7 +261,7 @@ export declare class FormControlName extends NgControl implements OnChanges, OnD get path(): string[]; /** @deprecated */ update: EventEmitter; get validator(): ValidatorFn | null; - constructor(parent: ControlContainer, validators: Array, asyncValidators: Array, valueAccessors: ControlValueAccessor[], _ngModelWarningConfig: string | null); + constructor(parent: ControlContainer, validators: (Validator | ValidatorFn)[], asyncValidators: (AsyncValidator | AsyncValidatorFn)[], valueAccessors: ControlValueAccessor[], _ngModelWarningConfig: string | null); ngOnChanges(changes: SimpleChanges): void; ngOnDestroy(): void; viewToModelUpdate(newValue: any): void; @@ -306,7 +306,7 @@ export declare class FormGroupDirective extends ControlContainer implements Form ngSubmit: EventEmitter; get path(): string[]; readonly submitted: boolean; - constructor(_validators: any[], _asyncValidators: any[]); + constructor(_validators: (Validator | ValidatorFn)[], _asyncValidators: (AsyncValidator | AsyncValidatorFn)[]); addControl(dir: FormControlName): FormControl; addFormArray(dir: FormArrayName): void; addFormGroup(dir: FormGroupName): void; @@ -325,7 +325,7 @@ export declare class FormGroupDirective extends ControlContainer implements Form export declare class FormGroupName extends AbstractFormGroupDirective implements OnInit, OnDestroy { name: string | number | null; - constructor(parent: ControlContainer, validators: any[], asyncValidators: any[]); + constructor(parent: ControlContainer, validators: (Validator | ValidatorFn)[], asyncValidators: (AsyncValidator | AsyncValidatorFn)[]); } export declare class FormsModule { @@ -349,7 +349,7 @@ export declare const NG_ASYNC_VALIDATORS: InjectionToken<(Function | Validator)[ export declare const NG_VALIDATORS: InjectionToken<(Function | Validator)[]>; -export declare const NG_VALUE_ACCESSOR: InjectionToken; +export declare const NG_VALUE_ACCESSOR: InjectionToken; export declare abstract class NgControl extends AbstractControlDirective { get asyncValidator(): AsyncValidatorFn | null; @@ -380,7 +380,7 @@ export declare class NgForm extends ControlContainer implements Form, AfterViewI }; get path(): string[]; readonly submitted: boolean; - constructor(validators: any[], asyncValidators: any[]); + constructor(validators: (Validator | ValidatorFn)[], asyncValidators: (AsyncValidator | AsyncValidatorFn)[]); addControl(dir: NgModel): void; addFormGroup(dir: NgModelGroup): void; getControl(dir: NgModel): FormControl; @@ -413,7 +413,7 @@ export declare class NgModel extends NgControl implements OnChanges, OnDestroy { update: EventEmitter; get validator(): ValidatorFn | null; viewModel: any; - constructor(parent: ControlContainer, validators: Array, asyncValidators: Array, valueAccessors: ControlValueAccessor[]); + constructor(parent: ControlContainer, validators: (Validator | ValidatorFn)[], asyncValidators: (AsyncValidator | AsyncValidatorFn)[], valueAccessors: ControlValueAccessor[]); ngOnChanges(changes: SimpleChanges): void; ngOnDestroy(): void; viewToModelUpdate(newValue: any): void; @@ -422,7 +422,7 @@ export declare class NgModel extends NgControl implements OnChanges, OnDestroy { export declare class NgModelGroup extends AbstractFormGroupDirective implements OnInit, OnDestroy { name: string; - constructor(parent: ControlContainer, validators: any[], asyncValidators: any[]); + constructor(parent: ControlContainer, validators: (Validator | ValidatorFn)[], asyncValidators: (AsyncValidator | AsyncValidatorFn)[]); } export declare class NgSelectOption implements OnDestroy { diff --git a/goldens/public-api/platform-server/platform-server.d.ts b/goldens/public-api/platform-server/platform-server.d.ts index 7db0b77e9777f..490599c709a5a 100644 --- a/goldens/public-api/platform-server/platform-server.d.ts +++ b/goldens/public-api/platform-server/platform-server.d.ts @@ -3,6 +3,7 @@ export declare const BEFORE_APP_SERIALIZED: InjectionToken<(() => void | Promise export declare const INITIAL_CONFIG: InjectionToken; export declare interface PlatformConfig { + baseUrl?: string; document?: string; url?: string; useAbsoluteUrl?: boolean; diff --git a/goldens/public-api/router/router.d.ts b/goldens/public-api/router/router.d.ts index 41395ae9bb1de..73cb56deb0ee3 100644 --- a/goldens/public-api/router/router.d.ts +++ b/goldens/public-api/router/router.d.ts @@ -51,6 +51,14 @@ export declare class ActivationStart { toString(): string; } +export declare abstract class BaseRouteReuseStrategy implements RouteReuseStrategy { + retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null; + shouldAttach(route: ActivatedRouteSnapshot): boolean; + shouldDetach(route: ActivatedRouteSnapshot): boolean; + shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean; + store(route: ActivatedRouteSnapshot, detachedTree: DetachedRouteHandle): void; +} + export declare interface CanActivate { canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable | Promise | boolean | UrlTree; } @@ -148,7 +156,7 @@ export declare class GuardsCheckStart extends RouterEvent { toString(): string; } -export declare type InitialNavigation = true | false | 'enabled' | 'disabled' | 'legacy_enabled' | 'legacy_disabled'; +export declare type InitialNavigation = 'disabled' | 'enabled' | 'enabledBlocking' | 'enabledNonBlocking'; export declare type LoadChildren = LoadChildrenCallback | DeprecatedLoadChildren; @@ -164,6 +172,14 @@ export declare type Navigation = { previousNavigation: Navigation | null; }; +export declare interface NavigationBehaviorOptions { + replaceUrl?: boolean; + skipLocationChange?: boolean; + state?: { + [k: string]: any; + }; +} + export declare class NavigationCancel extends RouterEvent { reason: string; constructor( @@ -191,18 +207,7 @@ export declare class NavigationError extends RouterEvent { toString(): string; } -export declare interface NavigationExtras { - fragment?: string; - preserveFragment?: boolean; - /** @deprecated */ preserveQueryParams?: boolean; - queryParams?: Params | null; - queryParamsHandling?: QueryParamsHandling | null; - relativeTo?: ActivatedRoute | null; - replaceUrl?: boolean; - skipLocationChange?: boolean; - state?: { - [k: string]: any; - }; +export declare interface NavigationExtras extends UrlCreationOptions, NavigationBehaviorOptions { } export declare class NavigationStart extends RouterEvent { @@ -336,13 +341,13 @@ export declare class Router { urlHandlingStrategy: UrlHandlingStrategy; urlUpdateStrategy: 'deferred' | 'eager'; constructor(rootComponentType: Type | null, urlSerializer: UrlSerializer, rootContexts: ChildrenOutletContexts, location: Location, injector: Injector, loader: NgModuleFactoryLoader, compiler: Compiler, config: Routes); - createUrlTree(commands: any[], navigationExtras?: NavigationExtras): UrlTree; + createUrlTree(commands: any[], navigationExtras?: UrlCreationOptions): UrlTree; dispose(): void; getCurrentNavigation(): Navigation | null; initialNavigation(): void; isActive(url: string | UrlTree, exact: boolean): boolean; navigate(commands: any[], extras?: NavigationExtras): Promise; - navigateByUrl(url: string | UrlTree, extras?: NavigationExtras): Promise; + navigateByUrl(url: string | UrlTree, extras?: NavigationBehaviorOptions): Promise; ngOnDestroy(): void; parseUrl(url: string): UrlTree; resetConfig(config: Routes): void; @@ -370,14 +375,11 @@ export declare class RouterEvent { url: string); } -export declare class RouterLink { - fragment: string; +export declare class RouterLink implements OnChanges { + fragment?: string; preserveFragment: boolean; - /** @deprecated */ set preserveQueryParams(value: boolean); - queryParams: { - [k: string]: any; - }; - queryParamsHandling: QueryParamsHandling; + queryParams?: Params | null; + queryParamsHandling?: QueryParamsHandling | null; replaceUrl: boolean; set routerLink(commands: any[] | string | null | undefined); skipLocationChange: boolean; @@ -386,6 +388,7 @@ export declare class RouterLink { }; get urlTree(): UrlTree; constructor(router: Router, route: ActivatedRoute, tabIndex: string, renderer: Renderer2, el: ElementRef); + ngOnChanges(changes: SimpleChanges): void; onClick(): boolean; } @@ -404,14 +407,11 @@ export declare class RouterLinkActive implements OnChanges, OnDestroy, AfterCont } export declare class RouterLinkWithHref implements OnChanges, OnDestroy { - fragment: string; + fragment?: string; href: string; preserveFragment: boolean; - /** @deprecated */ set preserveQueryParams(value: boolean); - queryParams: { - [k: string]: any; - }; - queryParamsHandling: QueryParamsHandling; + queryParams?: Params | null; + queryParamsHandling?: QueryParamsHandling | null; replaceUrl: boolean; set routerLink(commands: any[] | string | null | undefined); skipLocationChange: boolean; @@ -421,9 +421,9 @@ export declare class RouterLinkWithHref implements OnChanges, OnDestroy { target: string; get urlTree(): UrlTree; constructor(router: Router, route: ActivatedRoute, locationStrategy: LocationStrategy); - ngOnChanges(changes: {}): any; + ngOnChanges(changes: SimpleChanges): any; ngOnDestroy(): any; - onClick(button: number, ctrlKey: boolean, metaKey: boolean, shiftKey: boolean): boolean; + onClick(button: number, ctrlKey: boolean, shiftKey: boolean, altKey: boolean, metaKey: boolean): boolean; } export declare class RouterModule { @@ -493,6 +493,14 @@ export declare class Scroll { toString(): string; } +export declare interface UrlCreationOptions { + fragment?: string; + preserveFragment?: boolean; + queryParams?: Params | null; + queryParamsHandling?: QueryParamsHandling | null; + relativeTo?: ActivatedRoute | null; +} + export declare abstract class UrlHandlingStrategy { abstract extract(url: UrlTree): UrlTree; abstract merge(newUrlPart: UrlTree, rawUrl: UrlTree): UrlTree; diff --git a/goldens/public-api/service-worker/config/config.d.ts b/goldens/public-api/service-worker/config/config.d.ts index 575115c56e46a..75a007d98b505 100644 --- a/goldens/public-api/service-worker/config/config.d.ts +++ b/goldens/public-api/service-worker/config/config.d.ts @@ -14,6 +14,7 @@ export declare interface Config { assetGroups?: AssetGroup[]; dataGroups?: DataGroup[]; index: string; + navigationRequestStrategy?: 'freshness' | 'performance'; navigationUrls?: string[]; } diff --git a/goldens/public-api/service-worker/service-worker.d.ts b/goldens/public-api/service-worker/service-worker.d.ts index 097cbe2339efb..946a370fdd4ed 100644 --- a/goldens/public-api/service-worker/service-worker.d.ts +++ b/goldens/public-api/service-worker/service-worker.d.ts @@ -29,11 +29,17 @@ export declare class SwUpdate { readonly activated: Observable; readonly available: Observable; get isEnabled(): boolean; + readonly unrecoverable: Observable; constructor(sw: ɵangular_packages_service_worker_service_worker_a); activateUpdate(): Promise; checkForUpdate(): Promise; } +export declare interface UnrecoverableStateEvent { + reason: string; + type: 'UNRECOVERABLE_STATE'; +} + export declare interface UpdateActivatedEvent { current: { hash: string; diff --git a/goldens/size-tracking/aio-payloads.json b/goldens/size-tracking/aio-payloads.json index 8ebdb7da2442a..48c80297490c4 100755 --- a/goldens/size-tracking/aio-payloads.json +++ b/goldens/size-tracking/aio-payloads.json @@ -2,8 +2,8 @@ "aio": { "master": { "uncompressed": { - "runtime-es2015": 2987, - "main-es2015": 450880, + "runtime-es2015": 3037, + "main-es2015": 448243, "polyfills-es2015": 52685 } } @@ -11,18 +11,18 @@ "aio-local": { "master": { "uncompressed": { - "runtime-es2015": 2987, - "main-es2015": 448419, - "polyfills-es2015": 52630 + "runtime-es2015": 3037, + "main-es2015": 448676, + "polyfills-es2015": 52415 } } }, "aio-local-viewengine": { "master": { "uncompressed": { - "runtime-es2015": 3097, - "main-es2015": 430239, - "polyfills-es2015": 52195 + "runtime-es2015": 3157, + "main-es2015": 431750, + "polyfills-es2015": 52415 } } } diff --git a/goldens/size-tracking/integration-payloads.json b/goldens/size-tracking/integration-payloads.json index 9a036944cf2a8..e9db1e512f051 100644 --- a/goldens/size-tracking/integration-payloads.json +++ b/goldens/size-tracking/integration-payloads.json @@ -3,7 +3,7 @@ "master": { "uncompressed": { "runtime-es2015": 1485, - "main-es2015": 141151, + "main-es2015": 140899, "polyfills-es2015": 36571 } } @@ -12,7 +12,7 @@ "master": { "uncompressed": { "runtime-es2015": 1485, - "main-es2015": 17362, + "main-es2015": 17092, "polyfills-es2015": 36657 } } @@ -21,7 +21,7 @@ "master": { "uncompressed": { "runtime-es2015": 1485, - "main-es2015": 147573, + "main-es2015": 146698, "polyfills-es2015": 36571 } } @@ -30,7 +30,7 @@ "master": { "uncompressed": { "runtime-es2015": 1485, - "main-es2015": 136168, + "main-es2015": 136096, "polyfills-es2015": 37248 } } @@ -39,7 +39,7 @@ "master": { "uncompressed": { "runtime-es2015": 2289, - "main-es2015": 245351, + "main-es2015": 242460, "polyfills-es2015": 36938, "5-es2015": 751 } @@ -49,7 +49,7 @@ "master": { "uncompressed": { "runtime-es2015": 2289, - "main-es2015": 221939, + "main-es2015": 218527, "polyfills-es2015": 36723, "5-es2015": 781 } @@ -62,7 +62,7 @@ "bundle": "TODO(i): we should define ngDevMode to false in Closure, but --define only works in the global scope.", "bundle": "TODO(i): (FW-2164) TS 3.9 new class shape seems to have broken Closure in big ways. The size went from 169991 to 252338", "bundle": "TODO(i): after removal of tsickle from ngc-wrapped / ng_package, we had to switch to SIMPLE optimizations which increased the size from 252338 to 1198917, see PR#37221 and PR#37317 for more info", - "bundle": 1213130 + "bundle": 1214857 } } } diff --git a/gulpfile.js b/gulpfile.js index 0b281c445baf1..5853cf68b989f 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -32,4 +32,5 @@ gulp.task('changelog', loadTask('changelog')); gulp.task('changelog:zonejs', loadTask('changelog-zonejs')); gulp.task('check-env', () => {/* this is a noop because the env test ran already above */}); gulp.task('cldr:extract', loadTask('cldr', 'extract')); +gulp.task('cldr:download', loadTask('cldr', 'download')); gulp.task('cldr:gen-closure-locale', loadTask('cldr', 'closure')); diff --git a/integration/BUILD.bazel b/integration/BUILD.bazel index b352583c40817..a58be0c1d56fb 100644 --- a/integration/BUILD.bazel +++ b/integration/BUILD.bazel @@ -53,7 +53,10 @@ INTEGRATION_TESTS = { }, "dynamic-compiler": {"tags": ["no-ivy-aot"]}, "hello_world__closure": { - "commands": "payload_size_tracking", + # TODO: Re-enable the payload_size_tracking command: + # We should define ngDevMode to false in Closure, but --define only works in the global scope. + # With ngDevMode not being set to false, this size tracking test provides little value but a lot of + # headache to continue updating the size. "tags": ["no-ivy-aot"], }, "hello_world__systemjs_umd": { @@ -82,6 +85,12 @@ INTEGRATION_TESTS = { # root @npm//typescript package. "pinned_npm_packages": ["typescript"], }, + "typings_test_ts40": { + # Special case for `typings_test_ts40` test as we want to pin + # `typescript` at version 4.0.x for that test and not link to the + # root @npm//typescript package. + "pinned_npm_packages": ["typescript"], + }, } [ diff --git a/integration/angular_integration_test.bzl b/integration/angular_integration_test.bzl index b331062191907..1335d42c47b9d 100644 --- a/integration/angular_integration_test.bzl +++ b/integration/angular_integration_test.bzl @@ -50,8 +50,6 @@ GENERATED_NPM_PACKAGES = [ "@angular/platform-browser", "@angular/platform-browser-dynamic", "@angular/platform-server", - "@angular/platform-webworker", - "@angular/platform-webworker-dynamic", "@angular/router", "@angular/service-worker", "@angular/upgrade", diff --git a/integration/bazel/.bazelignore b/integration/bazel/.bazelignore index 3c3629e647f5d..1afd721e88d33 100644 --- a/integration/bazel/.bazelignore +++ b/integration/bazel/.bazelignore @@ -1 +1,2 @@ node_modules +.yarn_local_cache diff --git a/integration/bazel/WORKSPACE b/integration/bazel/WORKSPACE index ff35bd1440419..92f347350a241 100644 --- a/integration/bazel/WORKSPACE +++ b/integration/bazel/WORKSPACE @@ -5,8 +5,8 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # Fetch rules_nodejs so we can install our npm dependencies http_archive( name = "build_bazel_rules_nodejs", - sha256 = "84abf7ac4234a70924628baa9a73a5a5cbad944c4358cf9abdb4aab29c9a5b77", - urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/1.7.0/rules_nodejs-1.7.0.tar.gz"], + sha256 = "4952ef879704ab4ad6729a29007e7094aef213ea79e9f2e94cbe1c9a753e63ef", + urls = ["https://github.com/bazelbuild/rules_nodejs/releases/download/2.2.0/rules_nodejs-2.2.0.tar.gz"], ) # Fetch sass rules for compiling sass files @@ -48,18 +48,13 @@ yarn_install( yarn_lock = "//:yarn.lock", ) -# Install all bazel dependencies of our npm packages -load("@npm//:install_bazel_dependencies.bzl", "install_bazel_dependencies") - -install_bazel_dependencies() - # Load protractor dependencies -load("@npm_bazel_protractor//:package.bzl", "npm_bazel_protractor_dependencies") +load("@npm//@bazel/protractor:package.bzl", "npm_bazel_protractor_dependencies") npm_bazel_protractor_dependencies() # Load karma dependencies -load("@npm_bazel_karma//:package.bzl", "npm_bazel_karma_dependencies") +load("@npm//@bazel/karma:package.bzl", "npm_bazel_karma_dependencies") npm_bazel_karma_dependencies() @@ -75,11 +70,6 @@ browser_repositories( firefox = True, ) -# Setup the rules_typescript tooolchain -load("@npm_bazel_typescript//:index.bzl", "ts_setup_workspace") - -ts_setup_workspace() - # Setup the rules_sass toolchain load("@io_bazel_rules_sass//sass:sass_repositories.bzl", "sass_repositories") diff --git a/integration/bazel/package.json b/integration/bazel/package.json index b87ab109d0ee2..c7347b3814fba 100644 --- a/integration/bazel/package.json +++ b/integration/bazel/package.json @@ -16,18 +16,18 @@ "reflect-metadata": "0.1.12", "rxjs": "file:../../node_modules/rxjs", "tslib": "file:../../node_modules/tslib", - "zone.js": "file:../../dist/zone.js-dist" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" }, "devDependencies": { "@angular/bazel": "file:../../dist/packages-dist/bazel", "@angular/compiler": "file:../../dist/packages-dist/compiler", "@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli", "@bazel/bazelisk": "file:../../node_modules/@bazel/bazelisk", - "@bazel/karma": "1.7.0", - "@bazel/protractor": "1.7.0", - "@bazel/rollup": "1.7.0", - "@bazel/terser": "1.7.0", - "@bazel/typescript": "1.7.0", + "@bazel/karma": "2.2.0", + "@bazel/protractor": "2.2.0", + "@bazel/rollup": "2.2.0", + "@bazel/terser": "2.2.0", + "@bazel/typescript": "2.2.0", "@types/jasmine": "2.8.8", "http-server": "0.12.0", "karma": "4.4.1", @@ -43,7 +43,7 @@ "rollup-plugin-node-resolve": "5.2.0", "rollup-plugin-sourcemaps": "0.4.2", "terser": "4.4.0", - "typescript": "3.8.3" + "typescript": "file:../../node_modules/typescript" }, "scripts": { "test": "bazelisk build ... --noshow_progress && bazelisk test ...", diff --git a/integration/bazel/src/BUILD.bazel b/integration/bazel/src/BUILD.bazel index 2968f24a0dd31..a61abdb73f48a 100644 --- a/integration/bazel/src/BUILD.bazel +++ b/integration/bazel/src/BUILD.bazel @@ -2,10 +2,10 @@ package(default_visibility = ["//visibility:public"]) load("@build_bazel_rules_nodejs//:index.bzl", "pkg_web") load("@npm//http-server:index.bzl", "http_server") -load("@npm_angular_bazel//:index.bzl", "ng_module") -load("@npm_bazel_rollup//:index.bzl", "rollup_bundle") -load("@npm_bazel_terser//:index.bzl", "terser_minified") -load("@npm_bazel_typescript//:index.bzl", "ts_devserver") +load("@npm//@angular/bazel:index.bzl", "ng_module") +load("@npm//@bazel/rollup:index.bzl", "rollup_bundle") +load("@npm//@bazel/terser:index.bzl", "terser_minified") +load("@npm//@bazel/typescript:index.bzl", "ts_devserver") # Allow targets under sub-packages to reference the tsconfig.json file exports_files(["tsconfig.json"]) diff --git a/integration/bazel/src/app.component.ts b/integration/bazel/src/app.component.ts index 0801972313358..6b0e7cc515204 100644 --- a/integration/bazel/src/app.component.ts +++ b/integration/bazel/src/app.component.ts @@ -15,6 +15,6 @@ export class AppComponent { constructor(private http: HttpClient) {} time$: Observable = - this.http.get('http://worldclockapi.com/api/json/pst/now') - .pipe(map((result: any) => result.currentDateTime), startWith(['...'])); + this.http.get('http://worldtimeapi.org/api/timezone/America/Los_Angeles.json') + .pipe(map((result: any) => result.datetime), startWith(['...'])); } diff --git a/integration/bazel/src/hello-world/BUILD.bazel b/integration/bazel/src/hello-world/BUILD.bazel index 5f72e67774e96..615aab8117e57 100644 --- a/integration/bazel/src/hello-world/BUILD.bazel +++ b/integration/bazel/src/hello-world/BUILD.bazel @@ -1,23 +1,23 @@ package(default_visibility = ["//visibility:public"]) -load("@npm_bazel_karma//:index.bzl", "karma_web_test_suite") -load("@npm_bazel_typescript//:index.bzl", "ts_library") +load("@npm//@bazel/karma:index.bzl", "karma_web_test_suite") +load("@npm//@bazel/typescript:index.bzl", "ts_library") load("@io_bazel_rules_sass//sass:sass.bzl", "sass_binary") -load("@npm_angular_bazel//:index.bzl", "ng_module", "ng_package") +load("@npm//@angular/bazel:index.bzl", "ng_package") +load("//tools:ng_ts_library.bzl", "ng_ts_library") sass_binary( name = "hello-world-styles", src = "hello-world.component.scss", ) -ng_module( +ng_ts_library( name = "hello-world", srcs = glob( ["*.ts"], exclude = ["*.spec.ts"], ), assets = [":hello-world-styles"], - generate_ve_shims = True, deps = [ "@npm//@angular/core", "@npm//@types", diff --git a/integration/bazel/test/e2e/BUILD.bazel b/integration/bazel/test/e2e/BUILD.bazel index 933e7fc1b976f..19440263601bb 100644 --- a/integration/bazel/test/e2e/BUILD.bazel +++ b/integration/bazel/test/e2e/BUILD.bazel @@ -1,5 +1,5 @@ -load("@npm_bazel_protractor//:index.bzl", "protractor_web_test_suite") -load("@npm_bazel_typescript//:index.bzl", "ts_library") +load("@npm//@bazel/protractor:index.bzl", "protractor_web_test_suite") +load("@npm//@bazel/typescript:index.bzl", "ts_library") ts_library( name = "e2e", diff --git a/integration/bazel/tools/BUILD.bazel b/integration/bazel/tools/BUILD.bazel new file mode 100644 index 0000000000000..d2f335e89bf90 --- /dev/null +++ b/integration/bazel/tools/BUILD.bazel @@ -0,0 +1,15 @@ +load("@build_bazel_rules_nodejs//:index.bzl", "nodejs_binary") + +# Custom ts_library compiler that runs tsc_wrapped with angular/compiler-cli statically linked +# This can be used with worker mode because we don't need the linker at runtime to make +# the angular plugin loadable +# Just a clone of @npm//@bazel/typescript/bin:tsc_wrapped with added deps +nodejs_binary( + name = "tsc_wrapped_with_angular", + data = [ + "@npm//@angular/compiler-cli", + "@npm//@bazel/typescript", + ], + entry_point = "@npm//:node_modules/@bazel/typescript/internal/tsc_wrapped/tsc_wrapped.js", + visibility = ["//:__subpackages__"], +) diff --git a/integration/bazel/tools/ng_ts_library.bzl b/integration/bazel/tools/ng_ts_library.bzl new file mode 100644 index 0000000000000..fc36c5bc5fd60 --- /dev/null +++ b/integration/bazel/tools/ng_ts_library.bzl @@ -0,0 +1,13 @@ +"Shows how to enable both worker mode and use_angular_plugin to make a drop-in replacement for ng_module" + +load("@npm//@bazel/typescript:index.bzl", "ts_library") + +def ng_ts_library(**kwargs): + angular_assets = kwargs.pop("assets", []) + kwargs.pop("angular_assets", []) + ts_library( + compiler = "//tools:tsc_wrapped_with_angular", + supports_workers = True, + use_angular_plugin = True, + angular_assets = angular_assets, + **kwargs + ) diff --git a/integration/bazel/yarn.lock b/integration/bazel/yarn.lock index 07d373b800f82..9cf0c6683f2e1 100644 --- a/integration/bazel/yarn.lock +++ b/integration/bazel/yarn.lock @@ -3,12 +3,14 @@ "@angular/animations@file:../../dist/packages-dist/animations": - version "10.0.0-next.5" + version "11.0.0-next.4" + dependencies: + tslib "^2.0.0" "@angular/bazel@file:../../dist/packages-dist/bazel": - version "10.0.0-next.5" + version "11.0.0-next.4" dependencies: - "@microsoft/api-extractor" "^7.3.9" + "@microsoft/api-extractor" "^7.7.13" shelljs "0.8.2" tsickle "^0.38.0" @@ -22,11 +24,15 @@ parse5 "^5.0.0" "@angular/common@file:../../dist/packages-dist/common": - version "10.0.0-next.5" + version "11.0.0-next.4" + dependencies: + tslib "^2.0.0" "@angular/compiler-cli@file:../../dist/packages-dist/compiler-cli": - version "10.0.0-next.5" + version "11.0.0-next.4" dependencies: + "@babel/core" "^7.8.6" + "@babel/types" "^7.8.6" canonical-path "1.0.0" chokidar "^3.0.0" convert-source-map "^1.5.1" @@ -38,16 +44,23 @@ semver "^6.3.0" source-map "^0.6.1" sourcemap-codec "^1.4.8" + tslib "^2.0.0" yargs "15.3.0" "@angular/compiler@file:../../dist/packages-dist/compiler": - version "10.0.0-next.5" + version "11.0.0-next.4" + dependencies: + tslib "^2.0.0" "@angular/core@file:../../dist/packages-dist/core": - version "10.0.0-next.5" + version "11.0.0-next.4" + dependencies: + tslib "^2.0.0" "@angular/forms@file:../../dist/packages-dist/forms": - version "10.0.0-next.5" + version "11.0.0-next.4" + dependencies: + tslib "^2.0.0" "@angular/material@8.0.1": version "8.0.1" @@ -57,98 +70,257 @@ tslib "^1.7.1" "@angular/platform-browser-dynamic@file:../../dist/packages-dist/platform-browser-dynamic": - version "10.0.0-next.5" + version "11.0.0-next.4" + dependencies: + tslib "^2.0.0" "@angular/platform-browser@file:../../dist/packages-dist/platform-browser": - version "10.0.0-next.5" + version "11.0.0-next.4" + dependencies: + tslib "^2.0.0" "@angular/router@file:../../dist/packages-dist/router": - version "10.0.0-next.5" + version "11.0.0-next.4" + dependencies: + tslib "^2.0.0" + +"@babel/code-frame@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" + integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== + dependencies: + "@babel/highlight" "^7.10.4" + +"@babel/core@^7.8.6": + version "7.11.6" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.6.tgz#3a9455dc7387ff1bac45770650bc13ba04a15651" + integrity sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.6" + "@babel/helper-module-transforms" "^7.11.0" + "@babel/helpers" "^7.10.4" + "@babel/parser" "^7.11.5" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.11.5" + "@babel/types" "^7.11.5" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.19" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/generator@^7.11.5", "@babel/generator@^7.11.6": + version "7.11.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.6.tgz#b868900f81b163b4d464ea24545c61cbac4dc620" + integrity sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA== + dependencies: + "@babel/types" "^7.11.5" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/helper-function-name@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" + integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== + dependencies: + "@babel/helper-get-function-arity" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-get-function-arity@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" + integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-member-expression-to-functions@^7.10.4": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df" + integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q== + dependencies: + "@babel/types" "^7.11.0" + +"@babel/helper-module-imports@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" + integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-module-transforms@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359" + integrity sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg== + dependencies: + "@babel/helper-module-imports" "^7.10.4" + "@babel/helper-replace-supers" "^7.10.4" + "@babel/helper-simple-access" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/template" "^7.10.4" + "@babel/types" "^7.11.0" + lodash "^4.17.19" + +"@babel/helper-optimise-call-expression@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" + integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-replace-supers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" + integrity sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-simple-access@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz#0f5ccda2945277a2a7a2d3a821e15395edcf3461" + integrity sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw== + dependencies: + "@babel/template" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-split-export-declaration@^7.11.0": + version "7.11.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" + integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== + dependencies: + "@babel/types" "^7.11.0" + +"@babel/helper-validator-identifier@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" + integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== + +"@babel/helpers@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044" + integrity sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA== + dependencies: + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/highlight@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.10.4", "@babel/parser@^7.11.5": + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037" + integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q== + +"@babel/template@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" + integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/traverse@^7.10.4", "@babel/traverse@^7.11.5": + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.5.tgz#be777b93b518eb6d76ee2e1ea1d143daa11e61c3" + integrity sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.11.5" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/parser" "^7.11.5" + "@babel/types" "^7.11.5" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + +"@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.11.5", "@babel/types@^7.8.6": + version "7.11.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d" + integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" + to-fast-properties "^2.0.0" "@bazel/bazelisk@file:../../node_modules/@bazel/bazelisk": version "1.4.0" -"@bazel/karma@1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@bazel/karma/-/karma-1.6.0.tgz#98950b71114dd9ec169e6778a35d31ae1f578655" - integrity sha512-9cX0E1SiMWwA70ZMFnMzeqSRn3biduGx03bGV77FSUYKocZpyfU2cOEygYGfxAqHnyM7x4cS8nflRv3+ZE0Aqg== +"@bazel/karma@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@bazel/karma/-/karma-2.2.0.tgz#9bf6f6f1aa5f12b25468b1cad5e4404138436600" + integrity sha512-qyVE7vZ/qaibmpmcRdjS0rlorLGR0zZtlUSImVVTcPTSXqt364fp8TWBWe7oOneJ1SOVyUmTOAzyE86ArxZ/AA== dependencies: tmp "0.1.0" -"@bazel/protractor@1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@bazel/protractor/-/protractor-1.6.0.tgz#cf095a1dbc038def7031c513a3b87f4e79bedb00" - integrity sha512-gPiRv0oUJbVPpQ9nrwe5vjkffAc8VsYJhpTGgG+8aPdOaTLWgmBP/sy4BdfijU9O1Z/mNYojQCZgMzQz6kAvdg== +"@bazel/protractor@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@bazel/protractor/-/protractor-2.2.0.tgz#721b06507b84bf6d61d0e843e0af9939c6ad35a4" + integrity sha512-7dvAXxf/rGoi+S4+DWg8HNx3Co9s0kMg1xnBJ4T4nPF5wqSEoItkR6wsjkjQyocA2kIXan+HQcQvw4iIDMhGmg== -"@bazel/rollup@1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@bazel/rollup/-/rollup-1.6.0.tgz#c0bdad0ad0ba5c5b2e21d1634dc2ce48840ca044" - integrity sha512-MLF7laHX3CSAJH+RbIEVWgnQdz3U8dPkdJWJqiX/z9mUSEgC47LNsMBPKlRy1TpOJOpw1j0vLaJv0qN/bgq9NQ== +"@bazel/rollup@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@bazel/rollup/-/rollup-2.2.0.tgz#15651d545114e08db056f10a1eeaa4e76fc4df56" + integrity sha512-N4SyrvFkdAVc24CqFNhDtrR6P3XJTdPGziCuF7QM/BGihnsGlxF6+Dt2n5BTLJnObiB1St8vtRwCtAY8faxYWQ== -"@bazel/terser@1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@bazel/terser/-/terser-1.6.0.tgz#63ccd20dd6c9793e7b3b23fb5ea82b55b3ef6eb2" - integrity sha512-csBrN4XfX/hYTtDVcH/ulVO9K4Ca/IlrCWk5o/l7JBJq/cHoTj5AWIA7PKJ4QgnxXeEjso4CmLFgUMEVKVYV3Q== +"@bazel/terser@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@bazel/terser/-/terser-2.2.0.tgz#e0452f3d20e41d5e63048b3eea3280256172fd30" + integrity sha512-vukKS9ayJsW/eFFX6tG2Blem+NmEWbcYuCXxwgjL/uYiMCL/uowaTpcvVp9B+DsNSXhGyohOYwud0nBreSUFzg== -"@bazel/typescript@1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@bazel/typescript/-/typescript-1.6.0.tgz#8dfd29e71bcf917d5f9cb67f19ac4dcfc9082439" - integrity sha512-vAKuwy1Hgl+t3M3sH/G0oqHRYN35TdENj+0lsCI3x7EbSzyI6cbA3YQrLrlyvdScksqOpZa3PZ3UBGqfJJq2DA== +"@bazel/typescript@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@bazel/typescript/-/typescript-2.2.0.tgz#f2d3dce8715d574fe3146f19fdb8479abcc4d608" + integrity sha512-Thf8pXntBzE3EvJtyiTBNsfIf1QnYmGPQmUSGLcKUuuFoplUVYShMRHaxBoPZmYsnD/x+BFLgUKIzlXiEQpGqQ== dependencies: protobufjs "6.8.8" semver "5.6.0" source-map-support "0.5.9" tsutils "2.27.2" -"@microsoft/api-extractor-model@7.7.7": - version "7.7.7" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.7.7.tgz#1d15eae7a19b72abbfca9053f200fe79b6f9d755" - integrity sha512-822kyHMEx2sl+KnBioEiFoTIXuz/4pYBo94nQ4AMqb9BFvY9I1AZUPtC4HFh2zcXQqpFLpKKC55s/o8UOze2wQ== +"@microsoft/api-extractor-model@7.8.12": + version "7.8.12" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.8.12.tgz#d089193ef29275b8b20802498c6bdfab80dcef59" + integrity sha512-lE9xcNStS2hf5K+ZQy4L9DQ9Xd62bNsMqW+SyPQWXuQ5HJqUBSXJ2yxCWXP/+rcAkFCvZrikbql9M8Z88nKvwQ== dependencies: - "@microsoft/node-core-library" "3.19.3" - "@microsoft/tsdoc" "0.12.14" + "@microsoft/tsdoc" "0.12.19" + "@rushstack/node-core-library" "3.25.0" -"@microsoft/api-extractor@^7.3.9": - version "7.7.8" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.7.8.tgz#19b0bca8a2113d4ded55a270266bc2b802de1a43" - integrity sha512-XNO6Dk6ByfJq24Cn1/j0B0F16ZtwYnEC/sxgB/M0wTphBdBlHjRXZmxofmjirBBj9f7vG4UJ18IOIZRLbhGFPw== +"@microsoft/api-extractor@^7.7.13": + version "7.9.2" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.9.2.tgz#3bb8c93f4280fcb94171e4214d714e1639f4fbd4" + integrity sha512-R4b3zXlYdicoS8bRLXEChTKLPyhUHrG1cb0GDtOX0zdoxlovU1p0JaPt97A/vC7N3Gm2E8gd2qsDWElKU3/wKQ== dependencies: - "@microsoft/api-extractor-model" "7.7.7" - "@microsoft/node-core-library" "3.19.3" - "@microsoft/ts-command-line" "4.3.10" - "@microsoft/tsdoc" "0.12.14" + "@microsoft/api-extractor-model" "7.8.12" + "@microsoft/tsdoc" "0.12.19" + "@rushstack/node-core-library" "3.25.0" + "@rushstack/ts-command-line" "4.4.6" colors "~1.2.1" lodash "~4.17.15" - resolve "1.8.1" + resolve "~1.17.0" + semver "~7.3.0" source-map "~0.6.1" - typescript "~3.7.2" - -"@microsoft/node-core-library@3.19.3": - version "3.19.3" - resolved "https://registry.yarnpkg.com/@microsoft/node-core-library/-/node-core-library-3.19.3.tgz#cf09ddb2905a29b32956d4a88f9d035a00637be9" - integrity sha512-rJ+hT6+XK5AESbhn31YBnHKpZSFKCmqHCRZyK9+jyWwav1HXv0qzuXnFvnyrO0MZyJ6rH0seWOZVWbU5KGv1tg== - dependencies: - "@types/node" "10.17.13" - colors "~1.2.1" - fs-extra "~7.0.1" - jju "~1.4.0" - semver "~5.3.0" - timsort "~0.3.0" - z-schema "~3.18.3" + typescript "~3.9.5" -"@microsoft/ts-command-line@4.3.10": - version "4.3.10" - resolved "https://registry.yarnpkg.com/@microsoft/ts-command-line/-/ts-command-line-4.3.10.tgz#fcb4f5ea43c93d17db6cc810bbee39ea32b2a86d" - integrity sha512-AgxArGqPt0H5WTo3fxNFP3Blm3obkCCopVG9kwIo+/mMdXaj6qMDn6+8Bv8+5Nke3CvvXpKAZtu3IaGY5cV1Hg== - dependencies: - "@types/argparse" "1.0.33" - argparse "~1.0.9" - colors "~1.2.1" - -"@microsoft/tsdoc@0.12.14": - version "0.12.14" - resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.12.14.tgz#0e0810a0a174e50e22dfe8edb30599840712f22d" - integrity sha512-518yewjSga1jLdiLrcmpMFlaba5P+50b0TWNFUpC+SL9Yzf0kMi57qw+bMl+rQ08cGqH1vLx4eg9YFUbZXgZ0Q== +"@microsoft/tsdoc@0.12.19": + version "0.12.19" + resolved "https://registry.yarnpkg.com/@microsoft/tsdoc/-/tsdoc-0.12.19.tgz#2173ccb92469aaf62031fa9499d21b16d07f9b57" + integrity sha512-IpgPxHrNxZiMNUSXqR1l/gePKPkfAmIKoDRP9hp7OwjU29ZR8WCJsOJ8iBKgw0Qk+pFwR+8Y1cy8ImLY6e9m4A== "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" @@ -203,10 +375,32 @@ resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= -"@types/argparse@1.0.33": - version "1.0.33" - resolved "https://registry.yarnpkg.com/@types/argparse/-/argparse-1.0.33.tgz#2728669427cdd74a99e53c9f457ca2866a37c52d" - integrity sha512-VQgHxyPMTj3hIlq9SY1mctqx+Jj8kpQfoLvDlVSDNOyuYs8JYfkuY3OW/4+dO657yPmNhHpePRx0/Tje5ImNVQ== +"@rushstack/node-core-library@3.25.0": + version "3.25.0" + resolved "https://registry.yarnpkg.com/@rushstack/node-core-library/-/node-core-library-3.25.0.tgz#ba40bc1b188ab5d31f5705999cd2b3b56b8a32cf" + integrity sha512-e2NCFtAu/eu14b8nlzRX6ZrE9Sb3J2wVt+pninQmTn/IgfnRLAtM0D4PzUO4+ktZwF9fCnpqrOGokLzw6RSVNw== + dependencies: + "@types/node" "10.17.13" + colors "~1.2.1" + fs-extra "~7.0.1" + jju "~1.4.0" + semver "~7.3.0" + timsort "~0.3.0" + z-schema "~3.18.3" + +"@rushstack/ts-command-line@4.4.6": + version "4.4.6" + resolved "https://registry.yarnpkg.com/@rushstack/ts-command-line/-/ts-command-line-4.4.6.tgz#7818f19e444274e68564a756ef62a2b4e0ced0f8" + integrity sha512-ue3p2m773Yea/s4Ef2Q3gEyLd9T0NDjXCl+PlodGTrJHgxoiRwbROSWHAdYJL/LceGWa6Biqizu9qxUDEWFweQ== + dependencies: + "@types/argparse" "1.0.38" + argparse "~1.0.9" + colors "~1.2.1" + +"@types/argparse@1.0.38": + version "1.0.38" + resolved "https://registry.yarnpkg.com/@types/argparse/-/argparse-1.0.38.tgz#a81fd8606d481f873a3800c6ebae4f1d768a56a9" + integrity sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA== "@types/color-name@^1.1.1": version "1.1.1" @@ -315,6 +509,13 @@ ansi-styles@^2.2.1: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + ansi-styles@^4.0.0: version "4.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" @@ -567,6 +768,15 @@ chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" +chalk@^2.0.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + chokidar@^3.0.0: version "3.3.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" @@ -591,6 +801,13 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -598,6 +815,11 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" @@ -667,6 +889,13 @@ convert-source-map@^1.5.1: dependencies: safe-buffer "~5.1.1" +convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" @@ -713,6 +942,13 @@ debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.6: dependencies: ms "^2.1.1" +debug@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" + integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== + dependencies: + ms "2.1.2" + debug@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" @@ -907,7 +1143,7 @@ escape-html@~1.0.3: resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= -escape-string-regexp@^1.0.2: +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= @@ -1039,6 +1275,11 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +gensync@^1.0.0-beta.1: + version "1.0.0-beta.1" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" + integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== + get-caller-file@^2.0.1: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" @@ -1082,6 +1323,11 @@ glob@^7.0.3, glob@^7.0.6, glob@^7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + globby@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" @@ -1131,6 +1377,11 @@ has-cors@1.1.0: resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk= +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" @@ -1396,11 +1647,21 @@ jju@~1.4.0: resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" integrity sha1-o6vicYryQaKykE+EpiWXDzia4yo= +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -1416,6 +1677,13 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +json5@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" + integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== + dependencies: + minimist "^1.2.5" + jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -1537,6 +1805,11 @@ lodash@^4.17.14, lodash@~4.17.15: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +lodash@^4.17.19: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + log4js@^4.0.0: version "4.5.1" resolved "https://registry.yarnpkg.com/log4js/-/log4js-4.5.1.tgz#e543625e97d9e6f3e6e7c9fc196dd6ab2cae30b5" @@ -1612,6 +1885,11 @@ minimist@^1.1.0, minimist@^1.2.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= +minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" @@ -1629,7 +1907,7 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -ms@^2.1.1: +ms@2.1.2, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== @@ -1772,7 +2050,7 @@ path-is-inside@^1.0.1: resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= -path-parse@^1.0.5, path-parse@^1.0.6: +path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== @@ -2011,13 +2289,6 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" - integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA== - dependencies: - path-parse "^1.0.5" - resolve@^1.1.6, resolve@^1.11.0, resolve@^1.11.1: version "1.12.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" @@ -2025,6 +2296,13 @@ resolve@^1.1.6, resolve@^1.11.0, resolve@^1.11.1: dependencies: path-parse "^1.0.6" +resolve@^1.3.2, resolve@~1.17.0: + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== + dependencies: + path-parse "^1.0.6" + rfdc@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2" @@ -2135,7 +2413,7 @@ semver@5.6.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== -semver@^5.3.0: +semver@^5.3.0, semver@^5.4.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -2145,10 +2423,10 @@ semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@~5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= +semver@~7.3.0: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== set-blocking@^2.0.0: version "2.0.0" @@ -2259,7 +2537,7 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= -source-map@^0.5.6: +source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -2366,6 +2644,13 @@ supports-color@^2.0.0: resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + terser@4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/terser/-/terser-4.4.0.tgz#22c46b4817cf4c9565434bfe6ad47336af259ac3" @@ -2406,6 +2691,11 @@ to-array@0.1.4: resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA= +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -2436,8 +2726,13 @@ tslib@^1.7.1, tslib@^1.8.1, tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== +tslib@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.0.tgz#18d13fc2dce04051e20f074cc8387fd8089ce4f3" + integrity sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g== + "tslib@file:../../node_modules/tslib": - version "1.11.1" + version "2.0.0" tsutils@2.27.2: version "2.27.2" @@ -2466,15 +2761,13 @@ type-is@~1.6.17: media-typer "0.3.0" mime-types "~2.1.24" -typescript@3.8.3: - version "3.8.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061" - integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w== +"typescript@file:../../node_modules/typescript": + version "4.0.2" -typescript@~3.7.2: - version "3.7.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae" - integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw== +typescript@~3.9.5: + version "3.9.6" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.6.tgz#8f3e0198a34c3ae17091b35571d3afd31999365a" + integrity sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw== ultron@~1.1.0: version "1.1.1" @@ -2700,5 +2993,7 @@ z-schema@~3.18.3: optionalDependencies: commander "^2.7.1" -"zone.js@file:../../dist/zone.js-dist": - version "0.0.0" +"zone.js@file:../../dist/zone.js-dist/zone.js": + version "0.11.2" + dependencies: + tslib "^2.0.0" diff --git a/integration/cli-hello-world-ivy-compat/browserslist b/integration/cli-hello-world-ivy-compat/browserslist index 80848532e47d5..92197689d65b0 100644 --- a/integration/cli-hello-world-ivy-compat/browserslist +++ b/integration/cli-hello-world-ivy-compat/browserslist @@ -9,4 +9,4 @@ last 2 versions Firefox ESR not dead -not IE 9-11 # For IE 9-11 support, remove 'not'. \ No newline at end of file +not IE 11 # For IE 11 support, remove 'not'. \ No newline at end of file diff --git a/integration/cli-hello-world-ivy-compat/package.json b/integration/cli-hello-world-ivy-compat/package.json index 52b46ebceb072..d44c1b73d5dde 100644 --- a/integration/cli-hello-world-ivy-compat/package.json +++ b/integration/cli-hello-world-ivy-compat/package.json @@ -24,7 +24,7 @@ "@angular/router": "file:../../dist/packages-dist/router", "rxjs": "file:../../node_modules/rxjs", "tslib": "file:../../node_modules/tslib", - "zone.js": "file:../../dist/zone.js-dist/zone.js" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" }, "devDependencies": { "@angular-devkit/build-angular": "file:../../node_modules/@angular-devkit/build-angular", @@ -37,7 +37,7 @@ "codelyzer": "5.2.0", "jasmine-core": "3.5.0", "jasmine-spec-reporter": "4.2.1", - "karma": "4.3.0", + "karma": "4.4.0", "karma-chrome-launcher": "3.1.0", "karma-coverage-istanbul-reporter": "2.1.0", "karma-jasmine": "2.0.1", diff --git a/integration/cli-hello-world-ivy-compat/src/polyfills.ts b/integration/cli-hello-world-ivy-compat/src/polyfills.ts index aa665d6b87408..f39dafba9caeb 100644 --- a/integration/cli-hello-world-ivy-compat/src/polyfills.ts +++ b/integration/cli-hello-world-ivy-compat/src/polyfills.ts @@ -18,7 +18,7 @@ * BROWSER POLYFILLS */ -/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +/** IE11 requires the following for NgClass support on SVG elements */ // import 'classlist.js'; // Run `npm install --save classlist.js`. /** diff --git a/integration/cli-hello-world-ivy-compat/yarn.lock b/integration/cli-hello-world-ivy-compat/yarn.lock index a9b3ba8f71af9..dc75f51f66501 100644 --- a/integration/cli-hello-world-ivy-compat/yarn.lock +++ b/integration/cli-hello-world-ivy-compat/yarn.lock @@ -5253,10 +5253,10 @@ karma-source-map-support@1.4.0: dependencies: source-map-support "^0.5.5" -karma@4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/karma/-/karma-4.3.0.tgz#e14471ea090a952265a42ebb442b1a3c09832559" - integrity sha512-NSPViHOt+RW38oJklvYxQC4BSQsv737oQlr/r06pCM+slDOr4myuI1ivkRmp+3dVpJDfZt2DmaPJ2wkx+ZZuMQ== +karma@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/karma/-/karma-4.4.0.tgz#10f16117a37b388aa86618a8815b5c9acf1d7d6d" + integrity sha512-+mvzi+gBWHPrlqt1KE0WrrjcKuePX7WWJjTYNaewp6U00inno/DTSk+QHMbc+aV09scErWjhJukxswFyS7u2qw== dependencies: bluebird "^3.3.0" body-parser "^1.16.1" @@ -5264,7 +5264,6 @@ karma@4.3.0: chokidar "^3.0.0" colors "^1.1.0" connect "^3.6.0" - core-js "^3.1.3" di "^0.0.1" dom-serialize "^2.2.0" flatted "^2.0.0" diff --git a/integration/cli-hello-world-ivy-i18n/browserslist b/integration/cli-hello-world-ivy-i18n/browserslist index 80848532e47d5..92197689d65b0 100644 --- a/integration/cli-hello-world-ivy-i18n/browserslist +++ b/integration/cli-hello-world-ivy-i18n/browserslist @@ -9,4 +9,4 @@ last 2 versions Firefox ESR not dead -not IE 9-11 # For IE 9-11 support, remove 'not'. \ No newline at end of file +not IE 11 # For IE 11 support, remove 'not'. \ No newline at end of file diff --git a/integration/cli-hello-world-ivy-i18n/package.json b/integration/cli-hello-world-ivy-i18n/package.json index ed8e39797cb96..450ddec284a98 100644 --- a/integration/cli-hello-world-ivy-i18n/package.json +++ b/integration/cli-hello-world-ivy-i18n/package.json @@ -28,7 +28,7 @@ "core-js": "file:../../node_modules/core-js", "rxjs": "file:../../node_modules/rxjs", "tslib": "file:../../node_modules/tslib", - "zone.js": "file:../../dist/zone.js-dist/zone.js" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" }, "devDependencies": { "@angular-devkit/build-angular": "file:../../node_modules/@angular-devkit/build-angular", @@ -41,7 +41,7 @@ "codelyzer": "5.2.0", "jasmine-core": "3.5.0", "jasmine-spec-reporter": "4.2.1", - "karma": "4.3.0", + "karma": "4.4.0", "karma-chrome-launcher": "3.1.0", "karma-coverage-istanbul-reporter": "2.1.0", "karma-jasmine": "2.0.1", diff --git a/integration/cli-hello-world-ivy-i18n/src/polyfills.ts b/integration/cli-hello-world-ivy-i18n/src/polyfills.ts index dcfb64083540e..ac4cd2caedf15 100644 --- a/integration/cli-hello-world-ivy-i18n/src/polyfills.ts +++ b/integration/cli-hello-world-ivy-i18n/src/polyfills.ts @@ -18,7 +18,7 @@ * BROWSER POLYFILLS */ -/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +/** IE11 requires the following for NgClass support on SVG elements */ // import 'classlist.js'; // Run `npm install --save classlist.js`. /** diff --git a/integration/cli-hello-world-ivy-i18n/yarn.lock b/integration/cli-hello-world-ivy-i18n/yarn.lock index db8afee3a5800..19b5f627799ac 100644 --- a/integration/cli-hello-world-ivy-i18n/yarn.lock +++ b/integration/cli-hello-world-ivy-i18n/yarn.lock @@ -5278,10 +5278,10 @@ karma-source-map-support@1.4.0: dependencies: source-map-support "^0.5.5" -karma@4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/karma/-/karma-4.3.0.tgz#e14471ea090a952265a42ebb442b1a3c09832559" - integrity sha512-NSPViHOt+RW38oJklvYxQC4BSQsv737oQlr/r06pCM+slDOr4myuI1ivkRmp+3dVpJDfZt2DmaPJ2wkx+ZZuMQ== +karma@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/karma/-/karma-4.4.0.tgz#10f16117a37b388aa86618a8815b5c9acf1d7d6d" + integrity sha512-+mvzi+gBWHPrlqt1KE0WrrjcKuePX7WWJjTYNaewp6U00inno/DTSk+QHMbc+aV09scErWjhJukxswFyS7u2qw== dependencies: bluebird "^3.3.0" body-parser "^1.16.1" @@ -5289,7 +5289,6 @@ karma@4.3.0: chokidar "^3.0.0" colors "^1.1.0" connect "^3.6.0" - core-js "^3.1.3" di "^0.0.1" dom-serialize "^2.2.0" flatted "^2.0.0" diff --git a/integration/cli-hello-world-ivy-minimal/browserslist b/integration/cli-hello-world-ivy-minimal/browserslist index 80848532e47d5..92197689d65b0 100644 --- a/integration/cli-hello-world-ivy-minimal/browserslist +++ b/integration/cli-hello-world-ivy-minimal/browserslist @@ -9,4 +9,4 @@ last 2 versions Firefox ESR not dead -not IE 9-11 # For IE 9-11 support, remove 'not'. \ No newline at end of file +not IE 11 # For IE 11 support, remove 'not'. \ No newline at end of file diff --git a/integration/cli-hello-world-ivy-minimal/package.json b/integration/cli-hello-world-ivy-minimal/package.json index 04e1ca0116093..ea176faaa9c80 100644 --- a/integration/cli-hello-world-ivy-minimal/package.json +++ b/integration/cli-hello-world-ivy-minimal/package.json @@ -24,7 +24,7 @@ "@angular/router": "file:../../dist/packages-dist/router", "rxjs": "file:../../node_modules/rxjs", "tslib": "file:../../node_modules/tslib", - "zone.js": "file:../../dist/zone.js-dist/zone.js" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" }, "devDependencies": { "@angular-devkit/build-angular": "file:../../node_modules/@angular-devkit/build-angular", @@ -37,7 +37,7 @@ "codelyzer": "5.2.0", "jasmine-core": "3.5.0", "jasmine-spec-reporter": "4.2.1", - "karma": "4.3.0", + "karma": "4.4.0", "karma-chrome-launcher": "3.1.0", "karma-coverage-istanbul-reporter": "2.1.0", "karma-jasmine": "2.0.1", diff --git a/integration/cli-hello-world-ivy-minimal/src/polyfills.ts b/integration/cli-hello-world-ivy-minimal/src/polyfills.ts index aa665d6b87408..f39dafba9caeb 100644 --- a/integration/cli-hello-world-ivy-minimal/src/polyfills.ts +++ b/integration/cli-hello-world-ivy-minimal/src/polyfills.ts @@ -18,7 +18,7 @@ * BROWSER POLYFILLS */ -/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +/** IE11 requires the following for NgClass support on SVG elements */ // import 'classlist.js'; // Run `npm install --save classlist.js`. /** diff --git a/integration/cli-hello-world-ivy-minimal/yarn.lock b/integration/cli-hello-world-ivy-minimal/yarn.lock index a9b3ba8f71af9..dc75f51f66501 100644 --- a/integration/cli-hello-world-ivy-minimal/yarn.lock +++ b/integration/cli-hello-world-ivy-minimal/yarn.lock @@ -5253,10 +5253,10 @@ karma-source-map-support@1.4.0: dependencies: source-map-support "^0.5.5" -karma@4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/karma/-/karma-4.3.0.tgz#e14471ea090a952265a42ebb442b1a3c09832559" - integrity sha512-NSPViHOt+RW38oJklvYxQC4BSQsv737oQlr/r06pCM+slDOr4myuI1ivkRmp+3dVpJDfZt2DmaPJ2wkx+ZZuMQ== +karma@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/karma/-/karma-4.4.0.tgz#10f16117a37b388aa86618a8815b5c9acf1d7d6d" + integrity sha512-+mvzi+gBWHPrlqt1KE0WrrjcKuePX7WWJjTYNaewp6U00inno/DTSk+QHMbc+aV09scErWjhJukxswFyS7u2qw== dependencies: bluebird "^3.3.0" body-parser "^1.16.1" @@ -5264,7 +5264,6 @@ karma@4.3.0: chokidar "^3.0.0" colors "^1.1.0" connect "^3.6.0" - core-js "^3.1.3" di "^0.0.1" dom-serialize "^2.2.0" flatted "^2.0.0" diff --git a/integration/cli-hello-world-lazy-rollup/browserslist b/integration/cli-hello-world-lazy-rollup/browserslist index 80848532e47d5..92197689d65b0 100644 --- a/integration/cli-hello-world-lazy-rollup/browserslist +++ b/integration/cli-hello-world-lazy-rollup/browserslist @@ -9,4 +9,4 @@ last 2 versions Firefox ESR not dead -not IE 9-11 # For IE 9-11 support, remove 'not'. \ No newline at end of file +not IE 11 # For IE 11 support, remove 'not'. \ No newline at end of file diff --git a/integration/cli-hello-world-lazy-rollup/package.json b/integration/cli-hello-world-lazy-rollup/package.json index bae5154b9cd35..12681d1b94ba2 100644 --- a/integration/cli-hello-world-lazy-rollup/package.json +++ b/integration/cli-hello-world-lazy-rollup/package.json @@ -19,7 +19,7 @@ "@angular/router": "file:../../dist/packages-dist/router", "rxjs": "file:../../node_modules/rxjs", "tslib": "file:../../node_modules/tslib", - "zone.js": "file:../../dist/zone.js-dist/zone.js" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" }, "devDependencies": { "@angular-devkit/build-angular": "file:../../node_modules/@angular-devkit/build-angular", @@ -32,7 +32,7 @@ "codelyzer": "5.1.2", "jasmine-core": "3.5.0", "jasmine-spec-reporter": "4.2.1", - "karma": "4.3.0", + "karma": "4.4.0", "karma-chrome-launcher": "3.1.0", "karma-coverage-istanbul-reporter": "2.1.0", "karma-jasmine": "2.0.1", diff --git a/integration/cli-hello-world-lazy-rollup/src/polyfills.ts b/integration/cli-hello-world-lazy-rollup/src/polyfills.ts index aa665d6b87408..f39dafba9caeb 100644 --- a/integration/cli-hello-world-lazy-rollup/src/polyfills.ts +++ b/integration/cli-hello-world-lazy-rollup/src/polyfills.ts @@ -18,7 +18,7 @@ * BROWSER POLYFILLS */ -/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +/** IE11 requires the following for NgClass support on SVG elements */ // import 'classlist.js'; // Run `npm install --save classlist.js`. /** diff --git a/integration/cli-hello-world-lazy-rollup/yarn.lock b/integration/cli-hello-world-lazy-rollup/yarn.lock index f622c33cac979..7c6b3b721d373 100644 --- a/integration/cli-hello-world-lazy-rollup/yarn.lock +++ b/integration/cli-hello-world-lazy-rollup/yarn.lock @@ -5086,10 +5086,10 @@ karma-source-map-support@1.4.0: dependencies: source-map-support "^0.5.5" -karma@4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/karma/-/karma-4.3.0.tgz#e14471ea090a952265a42ebb442b1a3c09832559" - integrity sha512-NSPViHOt+RW38oJklvYxQC4BSQsv737oQlr/r06pCM+slDOr4myuI1ivkRmp+3dVpJDfZt2DmaPJ2wkx+ZZuMQ== +karma@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/karma/-/karma-4.4.0.tgz#10f16117a37b388aa86618a8815b5c9acf1d7d6d" + integrity sha512-+mvzi+gBWHPrlqt1KE0WrrjcKuePX7WWJjTYNaewp6U00inno/DTSk+QHMbc+aV09scErWjhJukxswFyS7u2qw== dependencies: bluebird "^3.3.0" body-parser "^1.16.1" @@ -5097,7 +5097,6 @@ karma@4.3.0: chokidar "^3.0.0" colors "^1.1.0" connect "^3.6.0" - core-js "^3.1.3" di "^0.0.1" dom-serialize "^2.2.0" flatted "^2.0.0" diff --git a/integration/cli-hello-world-lazy/browserslist b/integration/cli-hello-world-lazy/browserslist index 80848532e47d5..92197689d65b0 100644 --- a/integration/cli-hello-world-lazy/browserslist +++ b/integration/cli-hello-world-lazy/browserslist @@ -9,4 +9,4 @@ last 2 versions Firefox ESR not dead -not IE 9-11 # For IE 9-11 support, remove 'not'. \ No newline at end of file +not IE 11 # For IE 11 support, remove 'not'. \ No newline at end of file diff --git a/integration/cli-hello-world-lazy/package.json b/integration/cli-hello-world-lazy/package.json index f6a9d15506e03..8c2584a5f68d5 100644 --- a/integration/cli-hello-world-lazy/package.json +++ b/integration/cli-hello-world-lazy/package.json @@ -19,7 +19,7 @@ "@angular/router": "file:../../dist/packages-dist/router", "rxjs": "file:../../node_modules/rxjs", "tslib": "file:../../node_modules/tslib", - "zone.js": "file:../../dist/zone.js-dist/zone.js" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" }, "devDependencies": { "@angular-devkit/build-angular": "file:../../node_modules/@angular-devkit/build-angular", @@ -32,7 +32,7 @@ "codelyzer": "5.1.2", "jasmine-core": "3.5.0", "jasmine-spec-reporter": "4.2.1", - "karma": "4.3.0", + "karma": "4.4.0", "karma-chrome-launcher": "3.1.0", "karma-coverage-istanbul-reporter": "2.1.0", "karma-jasmine": "2.0.1", diff --git a/integration/cli-hello-world-lazy/src/polyfills.ts b/integration/cli-hello-world-lazy/src/polyfills.ts index aa665d6b87408..f39dafba9caeb 100644 --- a/integration/cli-hello-world-lazy/src/polyfills.ts +++ b/integration/cli-hello-world-lazy/src/polyfills.ts @@ -18,7 +18,7 @@ * BROWSER POLYFILLS */ -/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +/** IE11 requires the following for NgClass support on SVG elements */ // import 'classlist.js'; // Run `npm install --save classlist.js`. /** diff --git a/integration/cli-hello-world-lazy/yarn.lock b/integration/cli-hello-world-lazy/yarn.lock index f622c33cac979..7c6b3b721d373 100644 --- a/integration/cli-hello-world-lazy/yarn.lock +++ b/integration/cli-hello-world-lazy/yarn.lock @@ -5086,10 +5086,10 @@ karma-source-map-support@1.4.0: dependencies: source-map-support "^0.5.5" -karma@4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/karma/-/karma-4.3.0.tgz#e14471ea090a952265a42ebb442b1a3c09832559" - integrity sha512-NSPViHOt+RW38oJklvYxQC4BSQsv737oQlr/r06pCM+slDOr4myuI1ivkRmp+3dVpJDfZt2DmaPJ2wkx+ZZuMQ== +karma@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/karma/-/karma-4.4.0.tgz#10f16117a37b388aa86618a8815b5c9acf1d7d6d" + integrity sha512-+mvzi+gBWHPrlqt1KE0WrrjcKuePX7WWJjTYNaewp6U00inno/DTSk+QHMbc+aV09scErWjhJukxswFyS7u2qw== dependencies: bluebird "^3.3.0" body-parser "^1.16.1" @@ -5097,7 +5097,6 @@ karma@4.3.0: chokidar "^3.0.0" colors "^1.1.0" connect "^3.6.0" - core-js "^3.1.3" di "^0.0.1" dom-serialize "^2.2.0" flatted "^2.0.0" diff --git a/integration/cli-hello-world/browserslist b/integration/cli-hello-world/browserslist index 80848532e47d5..92197689d65b0 100644 --- a/integration/cli-hello-world/browserslist +++ b/integration/cli-hello-world/browserslist @@ -9,4 +9,4 @@ last 2 versions Firefox ESR not dead -not IE 9-11 # For IE 9-11 support, remove 'not'. \ No newline at end of file +not IE 11 # For IE 11 support, remove 'not'. \ No newline at end of file diff --git a/integration/cli-hello-world/package.json b/integration/cli-hello-world/package.json index 98ec7d4986ce7..44821b4b1dca4 100644 --- a/integration/cli-hello-world/package.json +++ b/integration/cli-hello-world/package.json @@ -23,7 +23,7 @@ "@angular/router": "file:../../dist/packages-dist/router", "rxjs": "file:../../node_modules/rxjs", "tslib": "file:../../node_modules/tslib", - "zone.js": "file:../../dist/zone.js-dist/zone.js" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" }, "devDependencies": { "@angular-devkit/build-angular": "file:../../node_modules/@angular-devkit/build-angular", @@ -36,7 +36,7 @@ "codelyzer": "5.2.0", "jasmine-core": "3.5.0", "jasmine-spec-reporter": "4.2.1", - "karma": "4.3.0", + "karma": "4.4.0", "karma-chrome-launcher": "3.1.0", "karma-coverage-istanbul-reporter": "2.1.0", "karma-jasmine": "2.0.1", diff --git a/integration/cli-hello-world/src/polyfills.ts b/integration/cli-hello-world/src/polyfills.ts index aa665d6b87408..f39dafba9caeb 100644 --- a/integration/cli-hello-world/src/polyfills.ts +++ b/integration/cli-hello-world/src/polyfills.ts @@ -18,7 +18,7 @@ * BROWSER POLYFILLS */ -/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +/** IE11 requires the following for NgClass support on SVG elements */ // import 'classlist.js'; // Run `npm install --save classlist.js`. /** diff --git a/integration/cli-hello-world/yarn.lock b/integration/cli-hello-world/yarn.lock index 5d07c26fe88d8..90bab6cdf6ace 100644 --- a/integration/cli-hello-world/yarn.lock +++ b/integration/cli-hello-world/yarn.lock @@ -5535,10 +5535,10 @@ karma-source-map-support@1.4.0: dependencies: source-map-support "^0.5.5" -karma@4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/karma/-/karma-4.3.0.tgz#e14471ea090a952265a42ebb442b1a3c09832559" - integrity sha512-NSPViHOt+RW38oJklvYxQC4BSQsv737oQlr/r06pCM+slDOr4myuI1ivkRmp+3dVpJDfZt2DmaPJ2wkx+ZZuMQ== +karma@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/karma/-/karma-4.4.0.tgz#10f16117a37b388aa86618a8815b5c9acf1d7d6d" + integrity sha512-+mvzi+gBWHPrlqt1KE0WrrjcKuePX7WWJjTYNaewp6U00inno/DTSk+QHMbc+aV09scErWjhJukxswFyS7u2qw== dependencies: bluebird "^3.3.0" body-parser "^1.16.1" @@ -5546,7 +5546,6 @@ karma@4.3.0: chokidar "^3.0.0" colors "^1.1.0" connect "^3.6.0" - core-js "^3.1.3" di "^0.0.1" dom-serialize "^2.2.0" flatted "^2.0.0" diff --git a/integration/dynamic-compiler/package.json b/integration/dynamic-compiler/package.json index 82fbe67f78002..59cb8d36260bd 100644 --- a/integration/dynamic-compiler/package.json +++ b/integration/dynamic-compiler/package.json @@ -41,7 +41,7 @@ "core-js": "file:../../node_modules/core-js", "rxjs": "file:../../node_modules/rxjs", "systemjs": "file:../../node_modules/systemjs", - "zone.js": "file:../../dist/zone.js-dist/zone.js" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" }, "//resolutions-comment": "Ensure a single version of webdriver-manager which comes from root node_modules that has already run webdriver-manager update", "resolutions": { diff --git a/integration/hello_world__closure/package.json b/integration/hello_world__closure/package.json index 83cf5530dd201..398b4eb08d95e 100644 --- a/integration/hello_world__closure/package.json +++ b/integration/hello_world__closure/package.json @@ -12,7 +12,7 @@ "rxjs": "file:../../node_modules/rxjs", "typescript": "file:../../node_modules/typescript", "tslib": "file:../../node_modules/tslib", - "zone.js": "file:../../dist/zone.js-dist/zone.js" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" }, "devDependencies": { "@types/jasmine": "file:../../node_modules/@types/jasmine", diff --git a/integration/hello_world__systemjs_umd/package.json b/integration/hello_world__systemjs_umd/package.json index 6a8c567b775a8..54d380fcc926e 100644 --- a/integration/hello_world__systemjs_umd/package.json +++ b/integration/hello_world__systemjs_umd/package.json @@ -20,7 +20,7 @@ "rxjs": "file:../../node_modules/rxjs", "systemjs": "0.20.2", "typescript": "file:../../node_modules/typescript", - "zone.js": "file:../../dist/zone.js-dist/zone.js" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" }, "devDependencies": { "@types/jasmine": "file:../../node_modules/@types/jasmine", diff --git a/integration/i18n/package.json b/integration/i18n/package.json index d681893bd5082..ad0c9955d0292 100644 --- a/integration/i18n/package.json +++ b/integration/i18n/package.json @@ -11,7 +11,7 @@ "rxjs": "file:../../node_modules/rxjs", "typescript": "file:../../node_modules/typescript", "tslib": "file:../../node_modules/tslib", - "zone.js": "file:../../dist/zone.js-dist/zone.js" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" }, "devDependencies": { "@types/jasmine": "file:../../node_modules/@types/jasmine", diff --git a/integration/injectable-def/package.json b/integration/injectable-def/package.json index b2fe57ba6dd35..054b482fab565 100644 --- a/integration/injectable-def/package.json +++ b/integration/injectable-def/package.json @@ -14,7 +14,7 @@ "@types/node": "file:../../node_modules/@types/node", "rxjs": "file:../../node_modules/rxjs", "typescript": "file:../../node_modules/typescript", - "zone.js": "file:../../dist/zone.js-dist/zone.js" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" }, "devDependencies": { "@types/jasmine": "file:../../node_modules/@types/jasmine", diff --git a/integration/ivy-i18n/browserslist b/integration/ivy-i18n/browserslist index 80848532e47d5..92197689d65b0 100644 --- a/integration/ivy-i18n/browserslist +++ b/integration/ivy-i18n/browserslist @@ -9,4 +9,4 @@ last 2 versions Firefox ESR not dead -not IE 9-11 # For IE 9-11 support, remove 'not'. \ No newline at end of file +not IE 11 # For IE 11 support, remove 'not'. \ No newline at end of file diff --git a/integration/ivy-i18n/package.json b/integration/ivy-i18n/package.json index 71c2f9e6bf660..e07a6202d5afa 100644 --- a/integration/ivy-i18n/package.json +++ b/integration/ivy-i18n/package.json @@ -56,7 +56,7 @@ "codelyzer": "5.2.0", "jasmine-core": "3.5.0", "jasmine-spec-reporter": "4.2.1", - "karma": "4.3.0", + "karma": "4.4.0", "karma-chrome-launcher": "3.1.0", "karma-coverage-istanbul-reporter": "2.1.0", "karma-jasmine": "2.0.1", diff --git a/integration/ivy-i18n/src/polyfills-runtime.ts b/integration/ivy-i18n/src/polyfills-runtime.ts index 30b721ff77c6c..63ba0f8456500 100644 --- a/integration/ivy-i18n/src/polyfills-runtime.ts +++ b/integration/ivy-i18n/src/polyfills-runtime.ts @@ -18,7 +18,7 @@ * BROWSER POLYFILLS */ -/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +/** IE11 requires the following for NgClass support on SVG elements */ // import 'classlist.js'; // Run `npm install --save classlist.js`. /** diff --git a/integration/ivy-i18n/src/polyfills.ts b/integration/ivy-i18n/src/polyfills.ts index dcfb64083540e..ac4cd2caedf15 100644 --- a/integration/ivy-i18n/src/polyfills.ts +++ b/integration/ivy-i18n/src/polyfills.ts @@ -18,7 +18,7 @@ * BROWSER POLYFILLS */ -/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +/** IE11 requires the following for NgClass support on SVG elements */ // import 'classlist.js'; // Run `npm install --save classlist.js`. /** diff --git a/integration/ivy-i18n/yarn.lock b/integration/ivy-i18n/yarn.lock index f15743a5e4e9d..ba2f3923ae84a 100644 --- a/integration/ivy-i18n/yarn.lock +++ b/integration/ivy-i18n/yarn.lock @@ -5810,10 +5810,10 @@ karma-source-map-support@1.4.0: dependencies: source-map-support "^0.5.5" -karma@4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/karma/-/karma-4.3.0.tgz#e14471ea090a952265a42ebb442b1a3c09832559" - integrity sha512-NSPViHOt+RW38oJklvYxQC4BSQsv737oQlr/r06pCM+slDOr4myuI1ivkRmp+3dVpJDfZt2DmaPJ2wkx+ZZuMQ== +karma@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/karma/-/karma-4.4.0.tgz#10f16117a37b388aa86618a8815b5c9acf1d7d6d" + integrity sha512-+mvzi+gBWHPrlqt1KE0WrrjcKuePX7WWJjTYNaewp6U00inno/DTSk+QHMbc+aV09scErWjhJukxswFyS7u2qw== dependencies: bluebird "^3.3.0" body-parser "^1.16.1" @@ -5821,7 +5821,6 @@ karma@4.3.0: chokidar "^3.0.0" colors "^1.1.0" connect "^3.6.0" - core-js "^3.1.3" di "^0.0.1" dom-serialize "^2.2.0" flatted "^2.0.0" diff --git a/integration/ng_elements/package.json b/integration/ng_elements/package.json index 783f0580f406b..2d99a595e3e65 100644 --- a/integration/ng_elements/package.json +++ b/integration/ng_elements/package.json @@ -12,7 +12,7 @@ "rxjs": "file:../../node_modules/rxjs", "typescript": "file:../../node_modules/typescript", "tslib": "file:../../node_modules/tslib", - "zone.js": "file:../../dist/zone.js-dist/zone.js" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" }, "devDependencies": { "@types/jasmine": "file:../../node_modules/@types/jasmine", diff --git a/integration/ng_update/package.json b/integration/ng_update/package.json index a1f977c81bd2a..2deba2e6059eb 100644 --- a/integration/ng_update/package.json +++ b/integration/ng_update/package.json @@ -17,13 +17,11 @@ "@angular/platform-browser": "file:../../dist/packages-dist/platform-browser", "@angular/platform-browser-dynamic": "file:../../dist/packages-dist/platform-browser-dynamic", "@angular/platform-server": "file:../../dist/packages-dist/platform-server", - "@angular/platform-webworker": "file:../../dist/packages-dist/platform-webworker", - "@angular/platform-webworker-dynamic": "file:../../dist/packages-dist/platform-webworker-dynamic", "@angular/router": "file:../../dist/packages-dist/router", "@angular/service-worker": "file:../../dist/packages-dist/service-worker", "@angular/upgrade": "file:../../dist/packages-dist/upgrade", "rxjs": "file:../../node_modules/rxjs", "typescript": "file:../../node_modules/typescript", - "zone.js": "file:../../dist/zone.js-dist/zone.js" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" } } diff --git a/integration/ng_update_migrations/browserslist b/integration/ng_update_migrations/browserslist index d6ac0551f9ef8..d96c53f232517 100644 --- a/integration/ng_update_migrations/browserslist +++ b/integration/ng_update_migrations/browserslist @@ -9,5 +9,5 @@ last 2 versions Firefox ESR not dead -not IE 9-11 # For IE 9-11 support, remove 'not'. +not IE 11 # For IE 11 support, remove 'not'. not Chrome 41 # For Googlebot support, remove 'not'. \ No newline at end of file diff --git a/integration/ng_update_migrations/package.json b/integration/ng_update_migrations/package.json index 705d624ce9d08..b9190e3993477 100644 --- a/integration/ng_update_migrations/package.json +++ b/integration/ng_update_migrations/package.json @@ -21,7 +21,7 @@ "@angular/router": "file:../../dist/packages-dist/router", "rxjs": "file:../../node_modules/rxjs", "tslib": "file:../../node_modules/tslib", - "zone.js": "file:../../dist/zone.js-dist/zone.js" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" }, "devDependencies": { "@angular-devkit/build-angular": "file:../../node_modules/@angular-devkit/build-angular", @@ -36,7 +36,7 @@ "glob": "7.1.4", "jasmine-core": "3.4.0", "jasmine-spec-reporter": "4.2.1", - "karma": "4.0.1", + "karma": "4.4.0", "karma-chrome-launcher": "2.2.0", "karma-jasmine": "2.0.1", "karma-jasmine-html-reporter": "1.4.2", diff --git a/integration/ng_update_migrations/src/polyfills.ts b/integration/ng_update_migrations/src/polyfills.ts index aa665d6b87408..f39dafba9caeb 100644 --- a/integration/ng_update_migrations/src/polyfills.ts +++ b/integration/ng_update_migrations/src/polyfills.ts @@ -18,7 +18,7 @@ * BROWSER POLYFILLS */ -/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +/** IE11 requires the following for NgClass support on SVG elements */ // import 'classlist.js'; // Run `npm install --save classlist.js`. /** diff --git a/integration/ng_update_migrations/yarn.lock b/integration/ng_update_migrations/yarn.lock index 74b2fe5c60e63..64eb2b38f9fdd 100644 --- a/integration/ng_update_migrations/yarn.lock +++ b/integration/ng_update_migrations/yarn.lock @@ -4816,18 +4816,17 @@ karma-source-map-support@1.4.0: dependencies: source-map-support "^0.5.5" -karma@4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/karma/-/karma-4.0.1.tgz#2581d6caa0d4cd28b65131561b47bad6d5478773" - integrity sha512-ind+4s03BqIXas7ZmraV3/kc5+mnqwCd+VDX1FndS6jxbt03kQKX2vXrWxNLuCjVYmhMwOZosAEKMM0a2q7w7A== +karma@4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/karma/-/karma-4.4.0.tgz#10f16117a37b388aa86618a8815b5c9acf1d7d6d" + integrity sha512-+mvzi+gBWHPrlqt1KE0WrrjcKuePX7WWJjTYNaewp6U00inno/DTSk+QHMbc+aV09scErWjhJukxswFyS7u2qw== dependencies: bluebird "^3.3.0" body-parser "^1.16.1" - braces "^2.3.2" - chokidar "^2.0.3" + braces "^3.0.2" + chokidar "^3.0.0" colors "^1.1.0" connect "^3.6.0" - core-js "^2.2.0" di "^0.0.1" dom-serialize "^2.2.0" flatted "^2.0.0" @@ -4835,7 +4834,7 @@ karma@4.0.1: graceful-fs "^4.1.2" http-proxy "^1.13.0" isbinaryfile "^3.0.0" - lodash "^4.17.11" + lodash "^4.17.14" log4js "^4.0.0" mime "^2.3.1" minimatch "^3.0.2" diff --git a/integration/ngcc/package.json b/integration/ngcc/package.json index 4c19e1cbbf7db..75a47d83ccbf4 100644 --- a/integration/ngcc/package.json +++ b/integration/ngcc/package.json @@ -18,7 +18,7 @@ "@types/node": "file:../../node_modules/@types/node", "rxjs": "file:../../node_modules/rxjs", "typescript": "file:../../node_modules/typescript", - "zone.js": "file:../../dist/zone.js-dist/zone.js" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" }, "devDependencies": { "@types/jasmine": "file:../../node_modules/@types/jasmine", diff --git a/integration/platform-server/package.json b/integration/platform-server/package.json index 002eb5065d65f..a62d727983c4a 100644 --- a/integration/platform-server/package.json +++ b/integration/platform-server/package.json @@ -19,7 +19,7 @@ "express": "4.16.4", "rxjs": "file:../../node_modules/rxjs", "typescript": "file:../../node_modules/typescript", - "zone.js": "file:../../dist/zone.js-dist/zone.js" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" }, "devDependencies": { "@types/jasmine": "file:../../node_modules/@types/jasmine", diff --git a/integration/service-worker-schema/package.json b/integration/service-worker-schema/package.json index 26a08141ffb57..af3986155e2a6 100644 --- a/integration/service-worker-schema/package.json +++ b/integration/service-worker-schema/package.json @@ -11,6 +11,6 @@ "@angular/core": "file:../../dist/packages-dist/core", "@angular/service-worker": "file:../../dist/packages-dist/service-worker", "rxjs": "file:../../node_modules/rxjs", - "zone.js": "file:../../dist/zone.js-dist/zone.js" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" } } diff --git a/integration/terser/package.json b/integration/terser/package.json index e585c2c531f35..7a8769bc7efd1 100644 --- a/integration/terser/package.json +++ b/integration/terser/package.json @@ -12,6 +12,6 @@ "rxjs": "file:../../node_modules/rxjs", "terser": "3.17.0", "typescript": "file:../../node_modules/typescript", - "zone.js": "file:../../dist/zone.js-dist/zone.js" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" } } diff --git a/integration/typings_test_ts39/include-all.ts b/integration/typings_test_ts39/include-all.ts index 81d94b0a01934..7bf19f646cd58 100644 --- a/integration/typings_test_ts39/include-all.ts +++ b/integration/typings_test_ts39/include-all.ts @@ -28,8 +28,6 @@ import * as platformBrowserAnimations from '@angular/platform-browser/animations import * as platformBrowserTesting from '@angular/platform-browser/testing'; import * as platformServer from '@angular/platform-server'; import * as platformServerTesting from '@angular/platform-server/testing'; -import * as platformWebworker from '@angular/platform-webworker'; -import * as platformWebworkerDynamic from '@angular/platform-webworker-dynamic'; import * as router from '@angular/router'; import * as routerTesting from '@angular/router/testing'; import * as routerUpgrade from '@angular/router/upgrade'; @@ -59,8 +57,6 @@ export default { platformBrowserAnimations, platformServer, platformServerTesting, - platformWebworker, - platformWebworkerDynamic, router, routerTesting, routerUpgrade, diff --git a/integration/typings_test_ts39/package.json b/integration/typings_test_ts39/package.json index c3d79ae0435d1..6f375da378866 100644 --- a/integration/typings_test_ts39/package.json +++ b/integration/typings_test_ts39/package.json @@ -14,15 +14,13 @@ "@angular/platform-browser": "file:../../dist/packages-dist/platform-browser", "@angular/platform-browser-dynamic": "file:../../dist/packages-dist/platform-browser-dynamic", "@angular/platform-server": "file:../../dist/packages-dist/platform-server", - "@angular/platform-webworker": "file:../../dist/packages-dist/platform-webworker", - "@angular/platform-webworker-dynamic": "file:../../dist/packages-dist/platform-webworker-dynamic", "@angular/router": "file:../../dist/packages-dist/router", "@angular/service-worker": "file:../../dist/packages-dist/service-worker", "@angular/upgrade": "file:../../dist/packages-dist/upgrade", "@types/jasmine": "file:../../node_modules/@types/jasmine", "rxjs": "file:../../node_modules/rxjs", "typescript": "~3.9.5", - "zone.js": "file:../../dist/zone.js-dist/zone.js" + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" }, "scripts": { "test": "tsc" diff --git a/integration/typings_test_ts40/include-all.ts b/integration/typings_test_ts40/include-all.ts new file mode 100644 index 0000000000000..7bf19f646cd58 --- /dev/null +++ b/integration/typings_test_ts40/include-all.ts @@ -0,0 +1,67 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ + + + +import * as animations from '@angular/animations'; +import * as animationsBrowser from '@angular/animations/browser'; +import * as animationsBrowserTesting from '@angular/animations/browser/testing'; +import * as common from '@angular/common'; +import * as commonHttp from '@angular/common/http'; +import * as commonTesting from '@angular/common/testing'; +import * as commonHttpTesting from '@angular/common/testing'; +import * as compiler from '@angular/compiler'; +import * as compilerTesting from '@angular/compiler/testing'; +import * as core from '@angular/core'; +import * as coreTesting from '@angular/core/testing'; +import * as elements from '@angular/elements'; +import * as forms from '@angular/forms'; +import * as platformBrowser from '@angular/platform-browser'; +import * as platformBrowserDynamic from '@angular/platform-browser-dynamic'; +import * as platformBrowserDynamicTesting from '@angular/platform-browser-dynamic/testing'; +import * as platformBrowserAnimations from '@angular/platform-browser/animations'; +import * as platformBrowserTesting from '@angular/platform-browser/testing'; +import * as platformServer from '@angular/platform-server'; +import * as platformServerTesting from '@angular/platform-server/testing'; +import * as router from '@angular/router'; +import * as routerTesting from '@angular/router/testing'; +import * as routerUpgrade from '@angular/router/upgrade'; +import * as serviceWorker from '@angular/service-worker'; +import * as upgrade from '@angular/upgrade'; +import * as upgradeStatic from '@angular/upgrade/static'; +import * as upgradeTesting from '@angular/upgrade/static/testing'; + +export default { + animations, + animationsBrowser, + animationsBrowserTesting, + common, + commonTesting, + commonHttp, + commonHttpTesting, + compiler, + compilerTesting, + core, + coreTesting, + elements, + forms, + platformBrowser, + platformBrowserTesting, + platformBrowserDynamic, + platformBrowserDynamicTesting, + platformBrowserAnimations, + platformServer, + platformServerTesting, + router, + routerTesting, + routerUpgrade, + serviceWorker, + upgrade, + upgradeStatic, + upgradeTesting, +}; diff --git a/integration/typings_test_ts40/package.json b/integration/typings_test_ts40/package.json new file mode 100644 index 0000000000000..c4a666ee33a54 --- /dev/null +++ b/integration/typings_test_ts40/package.json @@ -0,0 +1,28 @@ +{ + "name": "angular-integration", + "description": "Assert that users with TypeScript 4.0 can type-check an Angular application", + "version": "0.0.0", + "license": "MIT", + "dependencies": { + "@angular/animations": "file:../../dist/packages-dist/animations", + "@angular/common": "file:../../dist/packages-dist/common", + "@angular/compiler": "file:../../dist/packages-dist/compiler", + "@angular/compiler-cli": "file:../../dist/packages-dist/compiler-cli", + "@angular/core": "file:../../dist/packages-dist/core", + "@angular/elements": "file:../../dist/packages-dist/elements", + "@angular/forms": "file:../../dist/packages-dist/forms", + "@angular/platform-browser": "file:../../dist/packages-dist/platform-browser", + "@angular/platform-browser-dynamic": "file:../../dist/packages-dist/platform-browser-dynamic", + "@angular/platform-server": "file:../../dist/packages-dist/platform-server", + "@angular/router": "file:../../dist/packages-dist/router", + "@angular/service-worker": "file:../../dist/packages-dist/service-worker", + "@angular/upgrade": "file:../../dist/packages-dist/upgrade", + "@types/jasmine": "file:../../node_modules/@types/jasmine", + "rxjs": "file:../../node_modules/rxjs", + "typescript": "4.0.2", + "zone.js": "file:../../dist/zone.js-dist/archive/zone.js.tgz" + }, + "scripts": { + "test": "tsc" + } +} diff --git a/integration/typings_test_ts40/tsconfig.json b/integration/typings_test_ts40/tsconfig.json new file mode 100644 index 0000000000000..30e25c2209734 --- /dev/null +++ b/integration/typings_test_ts40/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "experimentalDecorators": true, + "module": "commonjs", + "moduleResolution": "node", + "outDir": "./dist/out-tsc", + "rootDir": ".", + "target": "es5", + "lib": [ + "es5", + "dom", + "es2015.collection", + "es2015.iterable", + "es2015.promise" + ], + "types": [], + }, + "files": [ + "include-all.ts", + "node_modules/@types/jasmine/index.d.ts" + ] +} diff --git a/karma-js.conf.js b/karma-js.conf.js index bdab6ea46359a..6f97a611f84ce 100644 --- a/karma-js.conf.js +++ b/karma-js.conf.js @@ -37,6 +37,9 @@ module.exports = function(config) { 'node_modules/core-js/client/core.js', 'node_modules/jasmine-ajax/lib/mock-ajax.js', + + // Dependencies built by Bazel. See `config.yml` for steps running before + // the legacy Saucelabs tests run. 'dist/bin/packages/zone.js/npm_package/bundles/zone.umd.js', 'dist/bin/packages/zone.js/npm_package/bundles/zone-testing.umd.js', 'dist/bin/packages/zone.js/npm_package/bundles/task-tracking.umd.js', diff --git a/modules/benchmarks/src/expanding_rows/expanding_row.ts b/modules/benchmarks/src/expanding_rows/expanding_row.ts index 9885b1298cca9..4f6a0180f68b4 100644 --- a/modules/benchmarks/src/expanding_rows/expanding_row.ts +++ b/modules/benchmarks/src/expanding_rows/expanding_row.ts @@ -45,10 +45,10 @@ export interface ExpandingRowHostBase { handleRowSummaryClick(row: ExpandingRow): void; /** - * Check if element is blacklisted. Blacklisted elements will not collapse an + * Check if element is collapsible. Elements marked as uncollapsible will not collapse an * open row when clicked. */ - isBlacklisted(element: HTMLElement|null): boolean; + isCollapsible(element: HTMLElement|null): boolean; /** * Handles caption element click on a cfc-expanding-row component. Note @@ -247,16 +247,15 @@ export class ExpandingRow { * notify click on its host element. Note that caption is only shown when * the row is expanded. Hence this will collapse this row and put the focus * on it. - * If a blacklisted element exists in the caption, clicking that element will + * If an uncollapsible element exists in the caption, clicking that element will * not trigger the row collapse. */ handleCaptionClick(event: MouseEvent): void { - if (this.expandingRowHost.isBlacklisted(event.target as {} as HTMLElement)) { - return; + if (this.expandingRowHost.isCollapsible(event.target as {} as HTMLElement)) { + this.expandingRowHost.handleRowCaptionClick(this); + this.collapse(); + this.focus(); } - this.expandingRowHost.handleRowCaptionClick(this); - this.collapse(); - this.focus(); } /** diff --git a/modules/benchmarks/src/expanding_rows/expanding_row_host.ts b/modules/benchmarks/src/expanding_rows/expanding_row_host.ts index 21f86b956efad..dd2b109f77a09 100644 --- a/modules/benchmarks/src/expanding_rows/expanding_row_host.ts +++ b/modules/benchmarks/src/expanding_rows/expanding_row_host.ts @@ -315,18 +315,18 @@ export class ExpandingRowHost implements AfterViewInit, OnDestroy, ExpandingRowH } /** - * Check if element is blacklisted. Blacklisted elements will not collapse an + * Check if element is collapsible. Elements marked as uncollapsible will not collapse an * open row when clicked. */ - isBlacklisted(element: HTMLElement|null): boolean { + isCollapsible(element: HTMLElement|null): boolean { const clickRoot = this.getClickRootElement(); while (element && element !== clickRoot) { - if (element.hasAttribute('cfcexpandingrowblacklist')) { - return true; + if (element.hasAttribute('cfcUncollapsible')) { + return false; } element = element.parentElement; } - return false; + return true; } /** diff --git a/modules/benchmarks/src/expanding_rows/expanding_row_module.ts b/modules/benchmarks/src/expanding_rows/expanding_row_module.ts index f48d76d47d0fe..fa65ae4303358 100644 --- a/modules/benchmarks/src/expanding_rows/expanding_row_module.ts +++ b/modules/benchmarks/src/expanding_rows/expanding_row_module.ts @@ -10,11 +10,11 @@ import {CommonModule} from '@angular/common'; import {NgModule} from '@angular/core'; import {ExpandingRow} from './expanding_row'; -import {ExpandingRowBlacklist} from './expanding_row_blacklist'; import {ExpandingRowDetailsCaption} from './expanding_row_details_caption'; import {ExpandingRowDetailsContent} from './expanding_row_details_content'; import {ExpandingRowHost} from './expanding_row_host'; import {ExpandingRowSummary} from './expanding_row_summary'; +import {ExpandingRowUncollapsible} from './expanding_row_uncollapsible'; /** The main module for the cfc-expanding-row component. */ @NgModule({ @@ -24,7 +24,7 @@ import {ExpandingRowSummary} from './expanding_row_summary'; ExpandingRowDetailsContent, ExpandingRowHost, ExpandingRowSummary, - ExpandingRowBlacklist, + ExpandingRowUncollapsible, ], exports: [ ExpandingRow, @@ -32,7 +32,7 @@ import {ExpandingRowSummary} from './expanding_row_summary'; ExpandingRowDetailsContent, ExpandingRowHost, ExpandingRowSummary, - ExpandingRowBlacklist, + ExpandingRowUncollapsible, ], imports: [ CommonModule, diff --git a/modules/benchmarks/src/expanding_rows/expanding_row_blacklist.ts b/modules/benchmarks/src/expanding_rows/expanding_row_uncollapsible.ts similarity index 82% rename from modules/benchmarks/src/expanding_rows/expanding_row_blacklist.ts rename to modules/benchmarks/src/expanding_rows/expanding_row_uncollapsible.ts index e19bb14e6fbbe..073f391113d75 100644 --- a/modules/benchmarks/src/expanding_rows/expanding_row_blacklist.ts +++ b/modules/benchmarks/src/expanding_rows/expanding_row_uncollapsible.ts @@ -14,7 +14,7 @@ import {Directive} from '@angular/core'; * expanded row */ @Directive({ - selector: '[cfcExpandingRowBlacklist]', + selector: '[cfcUncollapsible]', }) -export class ExpandingRowBlacklist { +export class ExpandingRowUncollapsible { } diff --git a/modules/playground/e2e_test/web_workers/animations/BUILD.bazel b/modules/playground/e2e_test/web_workers/animations/BUILD.bazel deleted file mode 100644 index 2bd6e176d7639..0000000000000 --- a/modules/playground/e2e_test/web_workers/animations/BUILD.bazel +++ /dev/null @@ -1,7 +0,0 @@ -load("//modules/playground/e2e_test:example_test.bzl", "example_test") - -example_test( - name = "animations", - srcs = glob(["**/*.ts"]), - server = "//modules/playground/src/web_workers/animations:devserver", -) diff --git a/modules/playground/e2e_test/web_workers/animations/animations_spec.ts b/modules/playground/e2e_test/web_workers/animations/animations_spec.ts deleted file mode 100644 index e000861711227..0000000000000 --- a/modules/playground/e2e_test/web_workers/animations/animations_spec.ts +++ /dev/null @@ -1,79 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {browser, by, element, protractor} from 'protractor'; - -import {verifyNoBrowserErrors} from '../../../../../dev-infra/benchmark/driver-utilities'; - - -// Disabled because with ViewEngine animations within webworkers is not supported. -// See: https://github.com/angular/angular/issues/18610 -xdescribe('WebWorkers Animations', function() { - afterEach(() => { - verifyNoBrowserErrors(); - browser.ignoreSynchronization = false; - }); - - const selector = 'animation-app'; - const URL = 'all/playground/src/web_workers/animations/index.html'; - - it('should bootstrap', () => { - // This test can't wait for Angular as Testability is not available when using WebWorker - browser.ignoreSynchronization = true; - browser.get(URL); - - waitForBootstrap(); - const elem = element(by.css(selector + ' .box')); - expect(elem.getText()).toEqual('...'); - }); - - it('should animate to open', () => { - // This test can't wait for Angular as Testability is not available when using WebWorker - browser.ignoreSynchronization = true; - browser.get(URL); - - waitForBootstrap(); - element(by.css(selector + ' button')).click(); - - const boxElm = element(by.css(selector + ' .box')); - browser.wait(() => boxElm.getSize().then(sizes => sizes['width'] > 750), 1000); - }); - - it('should cancel the animation midway and continue from where it left off', () => { - browser.ignoreSynchronization = true; - browser.get(URL); - - waitForBootstrap(); - - const elem = element(by.css(selector + ' .box')); - const btn = element(by.css(selector + ' button')); - const getWidth = () => elem.getSize().then((sizes: any) => sizes['width']); - - btn.click(); - - browser.sleep(250); - - btn.click(); - - expect(getWidth()).toBeLessThan(600); - - browser.sleep(500); - - expect(getWidth()).toBeLessThan(50); - }); - - function waitForBootstrap() { - browser.wait(protractor.until.elementLocated(by.css(selector + ' .box')), 5000) - .then(() => {}, () => { - // jasmine will timeout if this gets called too many times - console.error('>> unexpected timeout -> browser.refresh()'); - browser.refresh(); - waitForBootstrap(); - }); - } -}); diff --git a/modules/playground/e2e_test/web_workers/input/BUILD.bazel b/modules/playground/e2e_test/web_workers/input/BUILD.bazel deleted file mode 100644 index ae90a5daa45da..0000000000000 --- a/modules/playground/e2e_test/web_workers/input/BUILD.bazel +++ /dev/null @@ -1,7 +0,0 @@ -load("//modules/playground/e2e_test:example_test.bzl", "example_test") - -example_test( - name = "input", - srcs = glob(["**/*.ts"]), - server = "//modules/playground/src/web_workers/input:devserver", -) diff --git a/modules/playground/e2e_test/web_workers/input/input_spec.ts b/modules/playground/e2e_test/web_workers/input/input_spec.ts deleted file mode 100644 index 541baf99ad137..0000000000000 --- a/modules/playground/e2e_test/web_workers/input/input_spec.ts +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {browser, by, element, ExpectedConditions, protractor} from 'protractor'; - -import {verifyNoBrowserErrors} from '../../../../../dev-infra/benchmark/driver-utilities'; - -describe('WebWorkers Input', function() { - afterEach(() => { - verifyNoBrowserErrors(); - browser.ignoreSynchronization = false; - }); - const selector = 'input-app'; - const URL = '/'; - const VALUE = 'test val'; - - it('should bootstrap', () => { - // This test can't wait for Angular as Testability is not available when using WebWorker - browser.ignoreSynchronization = true; - browser.get(URL); - - waitForBootstrap(); - const elem = element(by.css(selector + ' h2')); - expect(elem.getText()).toEqual('Input App'); - }); - - it('should bind to input value', () => { - // This test can't wait for Angular as Testability is not available when using WebWorker - browser.ignoreSynchronization = true; - browser.get(URL); - - waitForBootstrap(); - const input = element(by.css(selector + ' input')); - input.sendKeys(VALUE); - const displayElem = element(by.css(selector + ' .input-val')); - const expectedVal = `Input val is ${VALUE}.`; - browser.wait(ExpectedConditions.textToBePresentInElement(displayElem, expectedVal), 5000); - expect(displayElem.getText()).toEqual(expectedVal); - }); - - it('should bind to textarea value', () => { - // This test can't wait for Angular as Testability is not available when using WebWorker - browser.ignoreSynchronization = true; - browser.get(URL); - - waitForBootstrap(); - const input = element(by.css(selector + ' textarea')); - input.sendKeys(VALUE); - const displayElem = element(by.css(selector + ' .textarea-val')); - const expectedVal = `Textarea val is ${VALUE}.`; - browser.wait(ExpectedConditions.textToBePresentInElement(displayElem, expectedVal), 5000); - expect(displayElem.getText()).toEqual(expectedVal); - }); - - function waitForBootstrap() { - browser.wait(protractor.until.elementLocated(by.css(selector + ' h2')), 5000) - .then( - () => { - const elem = element(by.css(selector + ' h2')); - browser.wait( - protractor.ExpectedConditions.textToBePresentInElement(elem, 'Input App'), 5000); - }, - () => { - // jasmine will timeout if this gets called too many times - console.error('>> unexpected timeout -> browser.refresh()'); - browser.refresh(); - waitForBootstrap(); - }); - } -}); diff --git a/modules/playground/e2e_test/web_workers/kitchen_sink/BUILD.bazel b/modules/playground/e2e_test/web_workers/kitchen_sink/BUILD.bazel deleted file mode 100644 index a764d7b479c74..0000000000000 --- a/modules/playground/e2e_test/web_workers/kitchen_sink/BUILD.bazel +++ /dev/null @@ -1,7 +0,0 @@ -load("//modules/playground/e2e_test:example_test.bzl", "example_test") - -example_test( - name = "kitchen_sink", - srcs = glob(["**/*.ts"]), - server = "//modules/playground/src/web_workers/kitchen_sink:devserver", -) diff --git a/modules/playground/e2e_test/web_workers/kitchen_sink/kitchen_sink_spec.ts b/modules/playground/e2e_test/web_workers/kitchen_sink/kitchen_sink_spec.ts deleted file mode 100644 index cb019f66974f1..0000000000000 --- a/modules/playground/e2e_test/web_workers/kitchen_sink/kitchen_sink_spec.ts +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {browser, by, element, ExpectedConditions, protractor} from 'protractor'; - -import {verifyNoBrowserErrors} from '../../../../../dev-infra/benchmark/driver-utilities'; - -describe('WebWorkers Kitchen Sink', function() { - afterEach(() => { - verifyNoBrowserErrors(); - browser.ignoreSynchronization = false; - }); - const selector = 'hello-app .greeting'; - const URL = '/'; - - it('should greet', () => { - // This test can't wait for Angular as Testability is not available when using WebWorker - browser.ignoreSynchronization = true; - browser.get(URL); - - browser.wait(protractor.until.elementLocated(by.css(selector)), 15000); - const elem = element(by.css(selector)); - browser.wait(ExpectedConditions.textToBePresentInElement(elem, 'hello world!'), 5000); - expect(elem.getText()).toEqual('hello world!'); - }); - - it('should change greeting', () => { - // This test can't wait for Angular as Testability is not available when using WebWorker - browser.ignoreSynchronization = true; - browser.get(URL); - const changeButtonSelector = 'hello-app .changeButton'; - - browser.wait(protractor.until.elementLocated(by.css(changeButtonSelector)), 15000); - element(by.css(changeButtonSelector)).click(); - const elem = element(by.css(selector)); - browser.wait(ExpectedConditions.textToBePresentInElement(elem, 'howdy world!'), 5000); - expect(elem.getText()).toEqual('howdy world!'); - }); - - it('should display correct key names', () => { - // This test can't wait for Angular as Testability is not available when using WebWorker - browser.ignoreSynchronization = true; - browser.get(URL); - browser.wait(protractor.until.elementLocated(by.css('.sample-area')), 15000); - - const area = element.all(by.css('.sample-area')).first(); - expect(area.getText()).toEqual('(none)'); - - area.sendKeys('u'); - browser.wait(ExpectedConditions.textToBePresentInElement(area, 'U'), 5000); - expect(area.getText()).toEqual('U'); - }); -}); diff --git a/modules/playground/e2e_test/web_workers/message_broker/BUILD.bazel b/modules/playground/e2e_test/web_workers/message_broker/BUILD.bazel deleted file mode 100644 index 74b19d9060523..0000000000000 --- a/modules/playground/e2e_test/web_workers/message_broker/BUILD.bazel +++ /dev/null @@ -1,7 +0,0 @@ -load("//modules/playground/e2e_test:example_test.bzl", "example_test") - -example_test( - name = "message_broker", - srcs = glob(["**/*.ts"]), - server = "//modules/playground/src/web_workers/message_broker:devserver", -) diff --git a/modules/playground/e2e_test/web_workers/message_broker/message_broker_spec.ts b/modules/playground/e2e_test/web_workers/message_broker/message_broker_spec.ts deleted file mode 100644 index 9ab657220848a..0000000000000 --- a/modules/playground/e2e_test/web_workers/message_broker/message_broker_spec.ts +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {browser, by, element, ExpectedConditions, protractor} from 'protractor'; - -import {verifyNoBrowserErrors} from '../../../../../dev-infra/benchmark/driver-utilities'; - -const URL = '/'; - -describe('MessageBroker', function() { - afterEach(() => { - verifyNoBrowserErrors(); - browser.ignoreSynchronization = false; - }); - - it('should bootstrap', () => { - // This test can't wait for Angular as Testability is not available when using WebWorker - browser.ignoreSynchronization = true; - browser.get(URL); - waitForBootstrap(); - expect(element(by.css('app h1')).getText()).toEqual('WebWorker MessageBroker Test'); - }); - - it('should echo messages', () => { - const VALUE = 'Hi There'; - // This test can't wait for Angular as Testability is not available when using WebWorker - browser.ignoreSynchronization = true; - browser.get(URL); - waitForBootstrap(); - - const input = element.all(by.css('#echo_input')).first(); - input.sendKeys(VALUE); - element(by.css('#send_echo')).click(); - const area = element(by.css('#echo_result')); - browser.wait(ExpectedConditions.textToBePresentInElement(area, VALUE), 5000); - expect(area.getText()).toEqual(VALUE); - }); -}); - -function waitForBootstrap(): void { - browser.wait(protractor.until.elementLocated(by.css('app h1')), 15000); -} diff --git a/modules/playground/e2e_test/web_workers/router/BUILD.bazel b/modules/playground/e2e_test/web_workers/router/BUILD.bazel deleted file mode 100644 index e6c55fae25a93..0000000000000 --- a/modules/playground/e2e_test/web_workers/router/BUILD.bazel +++ /dev/null @@ -1,7 +0,0 @@ -load("//modules/playground/e2e_test:example_test.bzl", "example_test") - -example_test( - name = "router", - srcs = glob(["**/*.ts"]), - server = "//modules/playground/src/web_workers/router:devserver", -) diff --git a/modules/playground/e2e_test/web_workers/router/router_spec.ts b/modules/playground/e2e_test/web_workers/router/router_spec.ts deleted file mode 100644 index 01773e947f1c5..0000000000000 --- a/modules/playground/e2e_test/web_workers/router/router_spec.ts +++ /dev/null @@ -1,88 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {browser, by, element, protractor} from 'protractor'; - -import {verifyNoBrowserErrors} from '../../../../../dev-infra/benchmark/driver-utilities'; - -describe('WebWorker Router', () => { - beforeEach(() => { - // This test can't wait for Angular as Testability is not available when using WebWorker - browser.ignoreSynchronization = true; - browser.get('/'); - }); - - afterEach(() => { - verifyNoBrowserErrors(); - browser.ignoreSynchronization = false; - }); - - const contentSelector = 'app main h1'; - const navSelector = 'app nav ul'; - const baseUrl = '/'; - - it('should route on click', () => { - browser.get(baseUrl); - - waitForElement(contentSelector); - let content = element(by.css(contentSelector)); - expect(content.getText()).toEqual('Start'); - - const aboutBtn = element(by.css(navSelector + ' .about')); - aboutBtn.click(); - waitForUrl(/\/about/); - waitForElement(contentSelector); - waitForElementText(contentSelector, 'About'); - content = element(by.css(contentSelector)); - expect(content.getText()).toEqual('About'); - expect(browser.getCurrentUrl()).toMatch(/\/about/); - - const contactBtn = element(by.css(navSelector + ' .contact')); - contactBtn.click(); - waitForUrl(/\/contact/); - waitForElement(contentSelector); - waitForElementText(contentSelector, 'Contact'); - content = element(by.css(contentSelector)); - expect(content.getText()).toEqual('Contact'); - expect(browser.getCurrentUrl()).toMatch(/\/contact/); - }); - - it('should load the correct route from the URL', () => { - browser.get(baseUrl + '#/about'); - - waitForElement(contentSelector); - waitForElementText(contentSelector, 'About'); - const content = element(by.css(contentSelector)); - expect(content.getText()).toEqual('About'); - }); - - function waitForElement(selector: string): void { - browser.wait(protractor.until.elementLocated(by.css(selector)), 15000); - } - - function waitForElementText(contentSelector: string, expected: string): void { - browser.wait(() => { - const deferred = protractor.promise.defer(); - const elem = element(by.css(contentSelector)); - elem.getText().then((text: string) => { - return deferred.fulfill(text === expected); - }); - return deferred.promise; - }, 5000); - } - - function waitForUrl(regex: RegExp): void { - browser.wait(() => { - const deferred = protractor.promise.defer(); - browser.getCurrentUrl().then((url: string) => { - return deferred.fulfill(url.match(regex) !== null); - }); - return deferred.promise; - }, 5000); - } -}); diff --git a/modules/playground/e2e_test/web_workers/todo/BUILD.bazel b/modules/playground/e2e_test/web_workers/todo/BUILD.bazel deleted file mode 100644 index 907933a69974c..0000000000000 --- a/modules/playground/e2e_test/web_workers/todo/BUILD.bazel +++ /dev/null @@ -1,7 +0,0 @@ -load("//modules/playground/e2e_test:example_test.bzl", "example_test") - -example_test( - name = "todo", - srcs = glob(["**/*.ts"]), - server = "//modules/playground/src/web_workers/todo:devserver", -) diff --git a/modules/playground/e2e_test/web_workers/todo/todo_spec.ts b/modules/playground/e2e_test/web_workers/todo/todo_spec.ts deleted file mode 100644 index d8caffdd360af..0000000000000 --- a/modules/playground/e2e_test/web_workers/todo/todo_spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {browser, by, element, protractor} from 'protractor'; - -import {verifyNoBrowserErrors} from '../../../../../dev-infra/benchmark/driver-utilities'; - -describe('WebWorkers Todo', function() { - afterEach(() => { - verifyNoBrowserErrors(); - browser.ignoreSynchronization = false; - }); - - const URL = '/'; - - it('should bootstrap', () => { - // This test can't wait for Angular as Testability is not available when using WebWorker - browser.ignoreSynchronization = true; - browser.get(URL); - - waitForBootstrap(); - expect(element(by.css('#todoapp header')).getText()).toEqual('todos'); - }); -}); - -function waitForBootstrap(): void { - browser.wait(protractor.until.elementLocated(by.css('todo-app #todoapp')), 15000); -} diff --git a/modules/playground/src/web_workers/BUILD.bazel b/modules/playground/src/web_workers/BUILD.bazel deleted file mode 100644 index 101d5649d746f..0000000000000 --- a/modules/playground/src/web_workers/BUILD.bazel +++ /dev/null @@ -1,13 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -filegroup( - name = "worker-config", - srcs = ["worker-configure.js"], - data = [ - "//modules/playground:systemjs-config.js", - "//modules/playground:systemjs-rxjs-operators.js", - "//packages/zone.js/bundles:zone.umd.js", - "@npm//reflect-metadata", - "@npm//systemjs", - ], -) diff --git a/modules/playground/src/web_workers/animations/BUILD.bazel b/modules/playground/src/web_workers/animations/BUILD.bazel deleted file mode 100644 index 9b6cf7012e4bd..0000000000000 --- a/modules/playground/src/web_workers/animations/BUILD.bazel +++ /dev/null @@ -1,31 +0,0 @@ -load("//tools:defaults.bzl", "ng_module", "ts_devserver") - -package(default_visibility = ["//modules/playground:__subpackages__"]) - -ng_module( - name = "animations", - srcs = glob(["**/*.ts"]), - tsconfig = "//modules/playground:tsconfig-build.json", - deps = [ - "//packages/animations", - "//packages/core", - "//packages/platform-webworker", - "//packages/platform-webworker-dynamic", - ], -) - -ts_devserver( - name = "devserver", - entry_module = "angular/modules/playground/src/web_workers/animations/index", - port = 4200, - scripts = ["@npm//:node_modules/tslib/tslib.js"], - static_files = [ - "loader.js", - "//modules/playground/src/web_workers:worker-config", - "@npm//:node_modules/rxjs/bundles/rxjs.umd.js", - "@npm//:node_modules/tslib/tslib.js", - "index.html", - "//packages/zone.js/bundles:zone.umd.js", - ], - deps = [":animations"], -) diff --git a/modules/playground/src/web_workers/animations/background_index.ts b/modules/playground/src/web_workers/animations/background_index.ts deleted file mode 100644 index b73cc3ac27d93..0000000000000 --- a/modules/playground/src/web_workers/animations/background_index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {NgModule} from '@angular/core'; -import {WorkerAppModule} from '@angular/platform-webworker'; -import {platformWorkerAppDynamic} from '@angular/platform-webworker-dynamic'; - -import {AnimationCmp} from './index_common'; - -@NgModule({imports: [WorkerAppModule], bootstrap: [AnimationCmp], declarations: [AnimationCmp]}) -export class ExampleModule { -} - -platformWorkerAppDynamic().bootstrapModule(ExampleModule); diff --git a/modules/playground/src/web_workers/animations/index.html b/modules/playground/src/web_workers/animations/index.html deleted file mode 100644 index c4c0c25eb1dac..0000000000000 --- a/modules/playground/src/web_workers/animations/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - WebWorker Animation Tests - - - - Loading... - - - diff --git a/modules/playground/src/web_workers/animations/index_common.ts b/modules/playground/src/web_workers/animations/index_common.ts deleted file mode 100644 index d38fd32498118..0000000000000 --- a/modules/playground/src/web_workers/animations/index_common.ts +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {animate, state, style, transition, trigger} from '@angular/animations'; -import {Component} from '@angular/core'; - -@Component({ - selector: 'animation-app', - styles: [` - .box { - border:10px solid black; - text-align:center; - overflow:hidden; - background:red; - color:white; - font-size:100px; - line-height:200px; - } - `], - animations: [trigger( - 'animate', - [ - state('off', style({width: '0px'})), state('on', style({width: '750px'})), - transition('off <=> on', animate(500)) - ])], - template: ` - - -

      - ... -
      - ` -}) -export class AnimationCmp { - animate = false; -} diff --git a/modules/playground/src/web_workers/animations/loader.js b/modules/playground/src/web_workers/animations/loader.js deleted file mode 100644 index 9dd1900c0b1c5..0000000000000 --- a/modules/playground/src/web_workers/animations/loader.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -importScripts('angular/modules/playground/src/web_workers/worker-configure.js'); - -System.config({packages: {'angular/modules/playground/src/web_workers': {defaultExtension: 'js'}}}); - -System.import('./background_index.js') - .catch(error => console.error('error loading background', error)); diff --git a/modules/playground/src/web_workers/images/BUILD.bazel b/modules/playground/src/web_workers/images/BUILD.bazel deleted file mode 100644 index e55c51a651a12..0000000000000 --- a/modules/playground/src/web_workers/images/BUILD.bazel +++ /dev/null @@ -1,41 +0,0 @@ -load("//tools:defaults.bzl", "ng_module", "ts_devserver") - -package(default_visibility = ["//modules/playground:__subpackages__"]) - -ng_module( - name = "images", - srcs = glob(["**/*.ts"]), - assets = ["image_demo.html"], - tsconfig = "//modules/playground:tsconfig-build.json", - deps = [ - "//packages/core", - "//packages/platform-webworker", - "//packages/platform-webworker-dynamic", - "@npm//@types/base64-js", - ], -) - -ts_devserver( - name = "devserver", - # Workaround for: https://github.com/bazelbuild/rules_typescript/issues/409 - additional_root_paths = ["angular"], - bootstrap = [ - "//packages/zone.js/bundles:zone.umd.js", - "@npm//:node_modules/jquery/dist/jquery.min.js", - "@npm//:node_modules/materialize-css/dist/js/materialize.min.js", - ], - entry_module = "angular/modules/playground/src/web_workers/images/index", - port = 4200, - scripts = ["@npm//:node_modules/tslib/tslib.js"], - static_files = [ - "@npm//:node_modules/base64-js/base64js.min.js", - "@npm//:node_modules/rxjs/bundles/rxjs.umd.js", - "@npm//:node_modules/tslib/tslib.js", - "@npm//:node_modules/materialize-css/dist/css/materialize.min.css", - "loader.js", - "index.html", - "//modules/playground/src/web_workers:worker-config", - "//third_party/github.com/google/material-design-icons", - ] + glob(["**/*.css"]), - deps = [":images"], -) diff --git a/modules/playground/src/web_workers/images/background_index.ts b/modules/playground/src/web_workers/images/background_index.ts deleted file mode 100644 index 5dc345cfb44bf..0000000000000 --- a/modules/playground/src/web_workers/images/background_index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {NgModule} from '@angular/core'; -import {WorkerAppModule} from '@angular/platform-webworker'; -import {platformWorkerAppDynamic} from '@angular/platform-webworker-dynamic'; - -import {ImageDemo} from './index_common'; - -@NgModule({imports: [WorkerAppModule], bootstrap: [ImageDemo], declarations: [ImageDemo]}) -export class ExampleModule { -} - -platformWorkerAppDynamic().bootstrapModule(ExampleModule); diff --git a/modules/playground/src/web_workers/images/image_demo.css b/modules/playground/src/web_workers/images/image_demo.css deleted file mode 100644 index bf19e97801a69..0000000000000 --- a/modules/playground/src/web_workers/images/image_demo.css +++ /dev/null @@ -1,30 +0,0 @@ -.hidden{ - display: none !important; -} -#images { - width: 600px; - margin: 0 auto; -} -ul li { - list-style-type: none; - float: left; - margin-left: 20px; - width: 200px; -} -#main ul { - width: 700px; -} -.card-image .image-loader{ - position: absolute; - bottom: 0; - margin: auto; -} - -.card-image img.grey { - opacity: 0.4; -} - -.fixed-action-btn.bottom { - bottom: 45px; - right: 24px; -} diff --git a/modules/playground/src/web_workers/images/image_demo.html b/modules/playground/src/web_workers/images/image_demo.html deleted file mode 100644 index e1ae692b98edd..0000000000000 --- a/modules/playground/src/web_workers/images/image_demo.html +++ /dev/null @@ -1,36 +0,0 @@ - -
      -
      -
      -
      -
      - -
      -
      -
      -
      -
      -
      -
      - - -
      -
      - Select Images - -
      -
      - -
      -
      -
      diff --git a/modules/playground/src/web_workers/images/index.html b/modules/playground/src/web_workers/images/index.html deleted file mode 100644 index fde85836fa105..0000000000000 --- a/modules/playground/src/web_workers/images/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/modules/playground/src/web_workers/images/index_common.ts b/modules/playground/src/web_workers/images/index_common.ts deleted file mode 100644 index b17efba38b3f8..0000000000000 --- a/modules/playground/src/web_workers/images/index_common.ts +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {Component} from '@angular/core'; - -import {BitmapService} from './services/bitmap'; - - -@Component({selector: 'image-demo', viewProviders: [BitmapService], templateUrl: 'image_demo.html'}) -export class ImageDemo { - images: {src: string, buffer: ArrayBuffer, filtering: boolean}[] = []; - fileInput: String; - - constructor(private _bitmapService: BitmapService) {} - - uploadFiles(files: FileList) { - for (let i = 0; i < files.length; i++) { - const reader = new FileReader(); - reader.addEventListener('load', this.handleReaderLoad(reader)); - reader.readAsArrayBuffer(files[i]); - } - } - - handleReaderLoad(reader: FileReader): EventListener { - return (e) => { - const buffer = reader.result as ArrayBuffer; - this.images.push({ - src: this._bitmapService.arrayBufferToDataUri(new Uint8Array(buffer)), - buffer: buffer, - filtering: false - }); - }; - } - - applyFilters() { - for (let i = 0; i < this.images.length; i++) { - this.images[i].filtering = true; - - setTimeout(this._filter(i), 0); - } - } - - private _filter(i: number): () => void { - return () => { - let imageData = this._bitmapService.convertToImageData(this.images[i].buffer); - imageData = this._bitmapService.applySepia(imageData); - this.images[i].src = this._bitmapService.toDataUri(imageData); - this.images[i].filtering = false; - }; - } -} diff --git a/modules/playground/src/web_workers/images/loader.css b/modules/playground/src/web_workers/images/loader.css deleted file mode 100644 index 30e38fef8b90a..0000000000000 --- a/modules/playground/src/web_workers/images/loader.css +++ /dev/null @@ -1,71 +0,0 @@ -body { - background: #eaecfa; -} - -.loader { - width: 250px; - height: 50px; - line-height: 50px; - text-align: center; - position: absolute; - top: 50%; - left: 50%; - -webkit-transform: translate(-50%, -50%); - -ms-transform: translate(-50%, -50%); - transform: translate(-50%, -50%); - font-family: helvetica, arial, sans-serif; - text-transform: uppercase; - font-weight: 900; - color: #ce4233; - letter-spacing: 0.2em; -} -.loader::before, .loader::after { - content: ""; - display: block; - width: 15px; - height: 15px; - background: #ce4233; - position: absolute; - -webkit-animation: load .7s infinite alternate ease-in-out; - animation: load .7s infinite alternate ease-in-out; -} -.loader::before { - top: 0; -} -.loader::after { - bottom: 0; -} - -@-webkit-keyframes load { - 0% { - left: 0; - height: 30px; - width: 15px; - } - 50% { - height: 8px; - width: 40px; - } - 100% { - left: 235px; - height: 30px; - width: 15px; - } -} - -@keyframes load { - 0% { - left: 0; - height: 30px; - width: 15px; - } - 50% { - height: 8px; - width: 40px; - } - 100% { - left: 235px; - height: 30px; - width: 15px; - } -} diff --git a/modules/playground/src/web_workers/images/loader.js b/modules/playground/src/web_workers/images/loader.js deleted file mode 100644 index dc68d1ea03cd3..0000000000000 --- a/modules/playground/src/web_workers/images/loader.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -importScripts('angular/modules/playground/src/web_workers/worker-configure.js'); - -System.config({ - map: { - 'base64-js': 'npm/node_modules/base64-js/base64js.min.js', - }, - packages: {'angular/modules/playground/src/web_workers': {defaultExtension: 'js'}} -}); - -System.import('./background_index.js') - .catch(error => console.error('error loading background', error)); diff --git a/modules/playground/src/web_workers/images/services/bitmap.ts b/modules/playground/src/web_workers/images/services/bitmap.ts deleted file mode 100644 index 31c08973930cf..0000000000000 --- a/modules/playground/src/web_workers/images/services/bitmap.ts +++ /dev/null @@ -1,179 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {Injectable} from '@angular/core'; -import {fromByteArray} from 'base64-js'; - -// This class is based on the Bitmap examples at: -// http://www.i-programmer.info/projects/36-web/6234-reading-a-bmp-file-in-javascript.html -// and http://www.worldwidewhat.net/2012/07/how-to-draw-bitmaps-using-javascript/ -@Injectable() -export class BitmapService { - convertToImageData(buffer: ArrayBuffer): ImageData { - const bmp = this._getBMP(buffer); - return this._BMPToImageData(bmp); - } - - applySepia(imageData: ImageData): ImageData { - const buffer = imageData.data; - for (let i = 0; i < buffer.length; i += 4) { - const r = buffer[i]; - const g = buffer[i + 1]; - const b = buffer[i + 2]; - buffer[i] = (r * .393) + (g * .769) + (b * .189); - buffer[i + 1] = (r * .349) + (g * .686) + (b * .168); - buffer[i + 2] = (r * .272) + (g * .534) + (b * .131); - } - return imageData; - } - - toDataUri(imageData: ImageData): string { - const header = this._createBMPHeader(imageData); - imageData = this._imageDataToBMP(imageData); - return 'data:image/bmp;base64,' + btoa(header) + fromByteArray(Uint8Array.from(imageData.data)); - } - - // converts a .bmp file ArrayBuffer to a dataURI - arrayBufferToDataUri(data: Uint8Array): string { - return 'data:image/bmp;base64,' + fromByteArray(data); - } - - // returns a UInt8Array in BMP order (starting from the bottom) - private _imageDataToBMP(imageData: ImageData): ImageData { - const width = imageData.width; - const height = imageData.height; - - const data = imageData.data; - for (let y = 0; y < height / 2; ++y) { - let topIndex = y * width * 4; - let bottomIndex = (height - y) * width * 4; - for (let i = 0; i < width * 4; i++) { - this._swap(data, topIndex, bottomIndex); - topIndex++; - bottomIndex++; - } - } - - return imageData; - } - - private _swap(data: Uint8Array|Uint8ClampedArray|number[], index1: number, index2: number) { - const temp = data[index1]; - data[index1] = data[index2]; - data[index2] = temp; - } - - // Based on example from - // http://www.worldwidewhat.net/2012/07/how-to-draw-bitmaps-using-javascript/ - private _createBMPHeader(imageData: ImageData): string { - const numFileBytes = this._getLittleEndianHex(imageData.width * imageData.height); - const w = this._getLittleEndianHex(imageData.width); - const h = this._getLittleEndianHex(imageData.height); - return 'BM' + // Signature - numFileBytes + // size of the file (bytes)* - '\x00\x00' + // reserved - '\x00\x00' + // reserved - '\x36\x00\x00\x00' + // offset of where BMP data lives (54 bytes) - '\x28\x00\x00\x00' + // number of remaining bytes in header from here (40 bytes) - w + // the width of the bitmap in pixels* - h + // the height of the bitmap in pixels* - '\x01\x00' + // the number of color planes (1) - '\x20\x00' + // 32 bits / pixel - '\x00\x00\x00\x00' + // No compression (0) - '\x00\x00\x00\x00' + // size of the BMP data (bytes)* - '\x13\x0B\x00\x00' + // 2835 pixels/meter - horizontal resolution - '\x13\x0B\x00\x00' + // 2835 pixels/meter - the vertical resolution - '\x00\x00\x00\x00' + // Number of colors in the palette (keep 0 for 32-bit) - '\x00\x00\x00\x00'; // 0 important colors (means all colors are important) - } - - private _BMPToImageData(bmp: BitmapFile): ImageData { - const width = bmp.infoHeader.biWidth; - const height = bmp.infoHeader.biHeight; - const imageData = new ImageData(width, height); - - const data = imageData.data; - const bmpData = bmp.pixels; - const stride = bmp.stride; - - for (let y = 0; y < height; ++y) { - for (let x = 0; x < width; ++x) { - const index1 = (x + width * (height - y)) * 4; - const index2 = x * 3 + stride * y; - data[index1] = bmpData[index2 + 2]; - data[index1 + 1] = bmpData[index2 + 1]; - data[index1 + 2] = bmpData[index2]; - data[index1 + 3] = 255; - } - } - return imageData; - } - - private _getBMP(buffer: ArrayBuffer): BitmapFile { - const datav = new DataView(buffer); - const bitmap: BitmapFile = { - fileHeader: { - bfType: datav.getUint16(0, true), - bfSize: datav.getUint32(2, true), - bfReserved1: datav.getUint16(6, true), - bfReserved2: datav.getUint16(8, true), - bfOffBits: datav.getUint32(10, true), - }, - infoHeader: { - biSize: datav.getUint32(14, true), - biWidth: datav.getUint32(18, true), - biHeight: datav.getUint32(22, true), - biPlanes: datav.getUint16(26, true), - biBitCount: datav.getUint16(28, true), - biCompression: datav.getUint32(30, true), - biSizeImage: datav.getUint32(34, true), - biXPelsPerMeter: datav.getUint32(38, true), - biYPelsPerMeter: datav.getUint32(42, true), - biClrUsed: datav.getUint32(46, true), - biClrImportant: datav.getUint32(50, true) - }, - stride: null, - pixels: null - }; - const start = bitmap.fileHeader.bfOffBits; - bitmap.stride = - Math.floor((bitmap.infoHeader.biBitCount * bitmap.infoHeader.biWidth + 31) / 32) * 4; - bitmap.pixels = new Uint8Array(datav.buffer, start); - return bitmap; - } - - // Based on example from - // http://www.worldwidewhat.net/2012/07/how-to-draw-bitmaps-using-javascript/ - private _getLittleEndianHex(value: number): string { - const result: string[] = []; - - for (let bytes = 4; bytes > 0; bytes--) { - result.push(String.fromCharCode(value & 255)); - value >>= 8; - } - - return result.join(''); - } -} - -interface BitmapFile { - fileHeader: { - bfType: number; bfSize: number; bfReserved1: number; bfReserved2: number; bfOffBits: number; - }; - infoHeader: { - biSize: number; biWidth: number; biHeight: number; biPlanes: number; biBitCount: number; - biCompression: number; - biSizeImage: number; - biXPelsPerMeter: number; - biYPelsPerMeter: number; - biClrUsed: number; - biClrImportant: number - }; - stride: number; - pixels: Uint8Array; -} diff --git a/modules/playground/src/web_workers/images/single_thread.html b/modules/playground/src/web_workers/images/single_thread.html deleted file mode 100644 index ec3da632a54cd..0000000000000 --- a/modules/playground/src/web_workers/images/single_thread.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/modules/playground/src/web_workers/images/single_thread.ts b/modules/playground/src/web_workers/images/single_thread.ts deleted file mode 100644 index 6891b04c1df06..0000000000000 --- a/modules/playground/src/web_workers/images/single_thread.ts +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {NgModule} from '@angular/core'; -import {BrowserModule} from '@angular/platform-browser'; -import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; - -import {ImageDemo} from './index_common'; - -@NgModule({bootstrap: [ImageDemo], imports: [BrowserModule]}) -class ExampleModule { -} - -export function main() { - platformBrowserDynamic().bootstrapModule(ExampleModule); -} diff --git a/modules/playground/src/web_workers/input/BUILD.bazel b/modules/playground/src/web_workers/input/BUILD.bazel deleted file mode 100644 index ab49918324e0f..0000000000000 --- a/modules/playground/src/web_workers/input/BUILD.bazel +++ /dev/null @@ -1,38 +0,0 @@ -load("//tools:defaults.bzl", "ng_module", "ts_devserver") - -package(default_visibility = ["//modules/playground:__subpackages__"]) - -ng_module( - name = "input", - srcs = glob(["**/*.ts"]), - tsconfig = "//modules/playground:tsconfig-build.json", - deps = [ - "//packages/core", - "//packages/platform-webworker", - "//packages/platform-webworker-dynamic", - ], -) - -ts_devserver( - name = "devserver", - bootstrap = [ - "@npm//:node_modules/systemjs/dist/system.js", - "//packages/zone.js/bundles:zone.umd.js", - "//packages/zone.js/bundles:long-stack-trace-zone.umd.js", - "@npm//:node_modules/reflect-metadata/Reflect.js", - ], - entry_module = "angular/modules/playground/src/web_workers/input/index", - port = 4200, - scripts = [ - "@npm//:node_modules/tslib/tslib.js", - "//tools/rxjs:rxjs_umd_modules", - ], - static_files = [ - "index.html", - "loader.js", - "//modules/playground/src/web_workers:worker-config", - "//modules/playground:systemjs-config.js", - "//modules/playground:systemjs-rxjs-operators.js", - ], - deps = [":input"], -) diff --git a/modules/playground/src/web_workers/input/background_index.ts b/modules/playground/src/web_workers/input/background_index.ts deleted file mode 100644 index 3e889dbd957c2..0000000000000 --- a/modules/playground/src/web_workers/input/background_index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {NgModule} from '@angular/core'; -import {WorkerAppModule} from '@angular/platform-webworker'; -import {platformWorkerAppDynamic} from '@angular/platform-webworker-dynamic'; - -import {InputCmp} from './index_common'; - -@NgModule({imports: [WorkerAppModule], bootstrap: [InputCmp], declarations: [InputCmp]}) -export class ExampleModule { -} - -platformWorkerAppDynamic().bootstrapModule(ExampleModule); diff --git a/modules/playground/src/web_workers/input/index.html b/modules/playground/src/web_workers/input/index.html deleted file mode 100644 index 7f026e4e32b2a..0000000000000 --- a/modules/playground/src/web_workers/input/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - WebWorker Input Tests - - - - Loading... - - - - - - diff --git a/modules/playground/src/web_workers/input/index_common.ts b/modules/playground/src/web_workers/input/index_common.ts deleted file mode 100644 index 8be97e9c18f94..0000000000000 --- a/modules/playground/src/web_workers/input/index_common.ts +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {Component} from '@angular/core'; - -@Component({ - selector: 'input-app', - template: ` -

      Input App

      -
      - - -
      Input val is {{inputVal}}.
      -
      Textarea val is {{textareaVal}}.
      -
      -
      -
      - ` -}) -export class InputCmp { - inputVal = ''; - textareaVal = ''; - - inputChanged(e: Event) { - this.inputVal = (e.target as HTMLInputElement).value; - } - - textAreaChanged(e: Event) { - this.textareaVal = (e.target as HTMLTextAreaElement).value; - } -} diff --git a/modules/playground/src/web_workers/input/loader.js b/modules/playground/src/web_workers/input/loader.js deleted file mode 100644 index 9dd1900c0b1c5..0000000000000 --- a/modules/playground/src/web_workers/input/loader.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -importScripts('angular/modules/playground/src/web_workers/worker-configure.js'); - -System.config({packages: {'angular/modules/playground/src/web_workers': {defaultExtension: 'js'}}}); - -System.import('./background_index.js') - .catch(error => console.error('error loading background', error)); diff --git a/modules/playground/src/web_workers/kitchen_sink/BUILD.bazel b/modules/playground/src/web_workers/kitchen_sink/BUILD.bazel deleted file mode 100644 index 686ef0468b12b..0000000000000 --- a/modules/playground/src/web_workers/kitchen_sink/BUILD.bazel +++ /dev/null @@ -1,38 +0,0 @@ -load("//tools:defaults.bzl", "ng_module", "ts_devserver") - -package(default_visibility = ["//modules/playground:__subpackages__"]) - -ng_module( - name = "kitchen_sink", - srcs = glob(["**/*.ts"]), - tsconfig = "//modules/playground:tsconfig-build.json", - deps = [ - "//packages/core", - "//packages/platform-webworker", - "//packages/platform-webworker-dynamic", - ], -) - -ts_devserver( - name = "devserver", - bootstrap = [ - "@npm//:node_modules/systemjs/dist/system.js", - "//packages/zone.js/bundles:zone.umd.js", - "//packages/zone.js/bundles:long-stack-trace-zone.umd.js", - "@npm//:node_modules/reflect-metadata/Reflect.js", - ], - entry_module = "angular/modules/playground/src/web_workers/kitchen_sink/index", - port = 4200, - scripts = [ - "@npm//:node_modules/tslib/tslib.js", - "//tools/rxjs:rxjs_umd_modules", - ], - static_files = [ - "index.html", - "loader.js", - "//modules/playground/src/web_workers:worker-config", - "//modules/playground:systemjs-config.js", - "//modules/playground:systemjs-rxjs-operators.js", - ], - deps = [":kitchen_sink"], -) diff --git a/modules/playground/src/web_workers/kitchen_sink/background_index.ts b/modules/playground/src/web_workers/kitchen_sink/background_index.ts deleted file mode 100644 index dfea4058345a9..0000000000000 --- a/modules/playground/src/web_workers/kitchen_sink/background_index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {NgModule} from '@angular/core'; -import {WorkerAppModule} from '@angular/platform-webworker'; -import {platformWorkerAppDynamic} from '@angular/platform-webworker-dynamic'; - -import {HelloCmp, RedDec} from './index_common'; - -@NgModule({ - imports: [WorkerAppModule], - bootstrap: [HelloCmp], - declarations: [HelloCmp, RedDec], -}) -export class ExampleModule { -} - -platformWorkerAppDynamic().bootstrapModule(ExampleModule); diff --git a/modules/playground/src/web_workers/kitchen_sink/index.html b/modules/playground/src/web_workers/kitchen_sink/index.html deleted file mode 100644 index 72a835e48abf6..0000000000000 --- a/modules/playground/src/web_workers/kitchen_sink/index.html +++ /dev/null @@ -1,27 +0,0 @@ - - - Hello Angular - - - - Loading... - - - - - - diff --git a/modules/playground/src/web_workers/kitchen_sink/index_common.ts b/modules/playground/src/web_workers/kitchen_sink/index_common.ts deleted file mode 100644 index 90939de9ba096..0000000000000 --- a/modules/playground/src/web_workers/kitchen_sink/index_common.ts +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {Component, Directive, ElementRef, Injectable, Renderer2} from '@angular/core'; - -// A service available to the Injector, used by the HelloCmp component. -@Injectable() -export class GreetingService { - greeting: string = 'hello'; -} - -// Directives are light-weight. They don't allow new -// expression contexts (use @Component for those needs). -@Directive({selector: '[red]'}) -export class RedDec { - // ElementRef is always injectable and it wraps the element on which the - // directive was found by the compiler. - constructor(el: ElementRef, renderer: Renderer2) { - renderer.setStyle(el.nativeElement, 'color', 'red'); - } -} - -// Angular supports 2 basic types of directives: -// - Component - the basic building blocks of Angular apps. Backed by -// ShadowDom.(http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom/) -// - Directive - add behavior to existing elements. - -@Component({ - // The Selector prop tells Angular on which elements to instantiate this - // class. The syntax supported is a basic subset of CSS selectors, for example - // 'element', '[attr]', [attr=foo]', etc. - selector: 'hello-app', - // These are services that would be created if a class in the component's - // template tries to inject them. - viewProviders: [GreetingService], - // The template for the component. - // Expressions in the template (like {{greeting}}) are evaluated in the - // context of the HelloCmp class below. - template: `
      {{greeting}} world!
      - -
      {{lastKey}}

      ` -}) -export class HelloCmp { - greeting: string; - lastKey: string = '(none)'; - - constructor(service: GreetingService) { - this.greeting = service.greeting; - } - - changeGreeting(): void { - this.greeting = 'howdy'; - } - - onKeyDown(event: KeyboardEvent): void { - this.lastKey = String.fromCharCode(event.keyCode); - } -} diff --git a/modules/playground/src/web_workers/kitchen_sink/loader.js b/modules/playground/src/web_workers/kitchen_sink/loader.js deleted file mode 100644 index 9dd1900c0b1c5..0000000000000 --- a/modules/playground/src/web_workers/kitchen_sink/loader.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -importScripts('angular/modules/playground/src/web_workers/worker-configure.js'); - -System.config({packages: {'angular/modules/playground/src/web_workers': {defaultExtension: 'js'}}}); - -System.import('./background_index.js') - .catch(error => console.error('error loading background', error)); diff --git a/modules/playground/src/web_workers/message_broker/BUILD.bazel b/modules/playground/src/web_workers/message_broker/BUILD.bazel deleted file mode 100644 index 9dd6417a301e8..0000000000000 --- a/modules/playground/src/web_workers/message_broker/BUILD.bazel +++ /dev/null @@ -1,38 +0,0 @@ -load("//tools:defaults.bzl", "ng_module", "ts_devserver") - -package(default_visibility = ["//modules/playground:__subpackages__"]) - -ng_module( - name = "message_broker", - srcs = glob(["**/*.ts"]), - tsconfig = "//modules/playground:tsconfig-build.json", - deps = [ - "//packages/core", - "//packages/platform-webworker", - "//packages/platform-webworker-dynamic", - ], -) - -ts_devserver( - name = "devserver", - bootstrap = [ - "@npm//:node_modules/systemjs/dist/system.js", - "//packages/zone.js/bundles:zone.umd.js", - "//packages/zone.js/bundles:long-stack-trace-zone.umd.js", - "@npm//:node_modules/reflect-metadata/Reflect.js", - ], - entry_module = "angular/modules/playground/src/web_workers/message_broker/index", - port = 4200, - scripts = [ - "@npm//:node_modules/tslib/tslib.js", - "//tools/rxjs:rxjs_umd_modules", - ], - static_files = [ - "index.html", - "loader.js", - "//modules/playground/src/web_workers:worker-config", - "//modules/playground:systemjs-config.js", - "//modules/playground:systemjs-rxjs-operators.js", - ], - deps = [":message_broker"], -) diff --git a/modules/playground/src/web_workers/message_broker/background_index.ts b/modules/playground/src/web_workers/message_broker/background_index.ts deleted file mode 100644 index f9f8e033c72f5..0000000000000 --- a/modules/playground/src/web_workers/message_broker/background_index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {NgModule} from '@angular/core'; -import {WorkerAppModule} from '@angular/platform-webworker'; -import {platformWorkerAppDynamic} from '@angular/platform-webworker-dynamic'; - -import {App} from './index_common'; - -@NgModule({imports: [WorkerAppModule], bootstrap: [App], declarations: [App]}) -export class ExampleModule { -} - -platformWorkerAppDynamic().bootstrapModule(ExampleModule); diff --git a/modules/playground/src/web_workers/message_broker/index.html b/modules/playground/src/web_workers/message_broker/index.html deleted file mode 100644 index f1aab56501b3b..0000000000000 --- a/modules/playground/src/web_workers/message_broker/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - Message Broker Example - - - - -

      -

      - - - - - diff --git a/modules/playground/src/web_workers/message_broker/index.ts b/modules/playground/src/web_workers/message_broker/index.ts deleted file mode 100644 index 592ff5bd7718f..0000000000000 --- a/modules/playground/src/web_workers/message_broker/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {PlatformRef} from '@angular/core'; -import {bootstrapWorkerUi, ClientMessageBrokerFactory, FnArg, SerializerTypes, UiArguments} from '@angular/platform-webworker'; - -const ECHO_CHANNEL = 'ECHO'; - -function afterBootstrap(ref: PlatformRef) { - const brokerFactory: ClientMessageBrokerFactory = ref.injector.get(ClientMessageBrokerFactory); - const broker = brokerFactory.createMessageBroker(ECHO_CHANNEL, false); - - document.getElementById('send_echo').addEventListener('click', (e) => { - const val = (document.getElementById('echo_input')).value; - // TODO(jteplitz602): Replace default constructors with real constructors - // once they're in the .d.ts file (#3926) - const fnArg = new FnArg(val); - const args = new UiArguments('echo', [fnArg]); - - broker.runOnService(args, SerializerTypes.PRIMITIVE).then((echo_result: string) => { - document.getElementById('echo_result').innerHTML = - `${echo_result}`; - }); - }); -} - -bootstrapWorkerUi('loader.js').then(afterBootstrap); diff --git a/modules/playground/src/web_workers/message_broker/index_common.ts b/modules/playground/src/web_workers/message_broker/index_common.ts deleted file mode 100644 index 193964bdba069..0000000000000 --- a/modules/playground/src/web_workers/message_broker/index_common.ts +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {Component} from '@angular/core'; -import {SerializerTypes, ServiceMessageBrokerFactory} from '@angular/platform-webworker'; - -const ECHO_CHANNEL = 'ECHO'; - -@Component({selector: 'app', template: '

      WebWorker MessageBroker Test

      '}) -export class App { - constructor(private _serviceBrokerFactory: ServiceMessageBrokerFactory) { - const broker = _serviceBrokerFactory.createMessageBroker(ECHO_CHANNEL, false); - broker.registerMethod( - 'echo', [SerializerTypes.PRIMITIVE], this._echo, SerializerTypes.PRIMITIVE); - } - - private _echo(val: string) { - return new Promise((res) => res(val)); - } -} diff --git a/modules/playground/src/web_workers/message_broker/loader.js b/modules/playground/src/web_workers/message_broker/loader.js deleted file mode 100644 index 9dd1900c0b1c5..0000000000000 --- a/modules/playground/src/web_workers/message_broker/loader.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -importScripts('angular/modules/playground/src/web_workers/worker-configure.js'); - -System.config({packages: {'angular/modules/playground/src/web_workers': {defaultExtension: 'js'}}}); - -System.import('./background_index.js') - .catch(error => console.error('error loading background', error)); diff --git a/modules/playground/src/web_workers/router/BUILD.bazel b/modules/playground/src/web_workers/router/BUILD.bazel deleted file mode 100644 index e771007426752..0000000000000 --- a/modules/playground/src/web_workers/router/BUILD.bazel +++ /dev/null @@ -1,41 +0,0 @@ -load("//tools:defaults.bzl", "ng_module", "ts_devserver") - -package(default_visibility = ["//modules/playground:__subpackages__"]) - -ng_module( - name = "router", - srcs = glob(["**/*.ts"]), - assets = ["app.html"], - tsconfig = "//modules/playground:tsconfig-build.json", - deps = [ - "//packages/core", - "//packages/platform-webworker", - "//packages/platform-webworker-dynamic", - "//packages/router", - "@npm//rxjs", - ], -) - -ts_devserver( - name = "devserver", - bootstrap = [ - "@npm//:node_modules/systemjs/dist/system.js", - "//packages/zone.js/bundles:zone.umd.js", - "//packages/zone.js/bundles:long-stack-trace-zone.umd.js", - "@npm//:node_modules/reflect-metadata/Reflect.js", - ], - entry_module = "angular/modules/playground/src/web_workers/router/index", - port = 4200, - scripts = [ - "@npm//:node_modules/tslib/tslib.js", - "//tools/rxjs:rxjs_umd_modules", - ], - static_files = [ - "index.html", - "loader.js", - "//modules/playground/src/web_workers:worker-config", - "//modules/playground:systemjs-config.js", - "//modules/playground:systemjs-rxjs-operators.js", - ], - deps = [":router"], -) diff --git a/modules/playground/src/web_workers/router/app.html b/modules/playground/src/web_workers/router/app.html deleted file mode 100644 index d79243c194f6a..0000000000000 --- a/modules/playground/src/web_workers/router/app.html +++ /dev/null @@ -1,11 +0,0 @@ - -
      - -
      - diff --git a/modules/playground/src/web_workers/router/background_index.ts b/modules/playground/src/web_workers/router/background_index.ts deleted file mode 100644 index d8240a05a162b..0000000000000 --- a/modules/playground/src/web_workers/router/background_index.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {platformWorkerAppDynamic} from '@angular/platform-webworker-dynamic'; -import {AppModule} from './index_common'; - -platformWorkerAppDynamic().bootstrapModule(AppModule); diff --git a/modules/playground/src/web_workers/router/components/about.ts b/modules/playground/src/web_workers/router/components/about.ts deleted file mode 100644 index 272a2404b24c9..0000000000000 --- a/modules/playground/src/web_workers/router/components/about.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {Component} from '@angular/core'; -@Component({selector: 'about', template: '

      About

      '}) -export class About { -} diff --git a/modules/playground/src/web_workers/router/components/contact.ts b/modules/playground/src/web_workers/router/components/contact.ts deleted file mode 100644 index 46ba8e7cdcbd4..0000000000000 --- a/modules/playground/src/web_workers/router/components/contact.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {Component} from '@angular/core'; -@Component({selector: 'contact', template: '

      Contact

      '}) -export class Contact { -} diff --git a/modules/playground/src/web_workers/router/components/start.ts b/modules/playground/src/web_workers/router/components/start.ts deleted file mode 100644 index d80dab161896c..0000000000000 --- a/modules/playground/src/web_workers/router/components/start.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {Component} from '@angular/core'; -@Component({selector: 'start', template: '

      Start

      '}) -export class Start { -} diff --git a/modules/playground/src/web_workers/router/index.html b/modules/playground/src/web_workers/router/index.html deleted file mode 100644 index 90ce028dae9bb..0000000000000 --- a/modules/playground/src/web_workers/router/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - Web Worker Router Example - - - - - - - diff --git a/modules/playground/src/web_workers/router/index.ts b/modules/playground/src/web_workers/router/index.ts deleted file mode 100644 index 72034f8c65c86..0000000000000 --- a/modules/playground/src/web_workers/router/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {bootstrapWorkerUi, WORKER_UI_LOCATION_PROVIDERS} from '@angular/platform-webworker'; - -bootstrapWorkerUi('loader.js', WORKER_UI_LOCATION_PROVIDERS); diff --git a/modules/playground/src/web_workers/router/index_common.ts b/modules/playground/src/web_workers/router/index_common.ts deleted file mode 100644 index 9aa0ce01c0c52..0000000000000 --- a/modules/playground/src/web_workers/router/index_common.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {Component, NgModule} from '@angular/core'; -import {WORKER_APP_LOCATION_PROVIDERS, WorkerAppModule} from '@angular/platform-webworker'; -import {RouterModule} from '@angular/router'; - -import {About} from './components/about'; -import {Contact} from './components/contact'; -import {Start} from './components/start'; - -@Component({selector: 'app', templateUrl: 'app.html'}) -export class App { -} - -export const ROUTES = [ - {path: '', component: Start}, {path: 'contact', component: Contact}, - {path: 'about', component: About} -]; - -@NgModule({ - imports: [WorkerAppModule, RouterModule.forRoot(ROUTES, {useHash: true})], - providers: [ - WORKER_APP_LOCATION_PROVIDERS, - ], - bootstrap: [App], - declarations: [App, Start, Contact, About] -}) -export class AppModule { -} diff --git a/modules/playground/src/web_workers/router/loader.js b/modules/playground/src/web_workers/router/loader.js deleted file mode 100644 index 9dd1900c0b1c5..0000000000000 --- a/modules/playground/src/web_workers/router/loader.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -importScripts('angular/modules/playground/src/web_workers/worker-configure.js'); - -System.config({packages: {'angular/modules/playground/src/web_workers': {defaultExtension: 'js'}}}); - -System.import('./background_index.js') - .catch(error => console.error('error loading background', error)); diff --git a/modules/playground/src/web_workers/todo/BUILD.bazel b/modules/playground/src/web_workers/todo/BUILD.bazel deleted file mode 100644 index ab7d0168863dd..0000000000000 --- a/modules/playground/src/web_workers/todo/BUILD.bazel +++ /dev/null @@ -1,41 +0,0 @@ -load("//tools:defaults.bzl", "ng_module", "ts_devserver") - -package(default_visibility = ["//modules/playground:__subpackages__"]) - -ng_module( - name = "todo", - srcs = glob(["**/*.ts"]), - assets = ["todo.html"], - tsconfig = "//modules/playground:tsconfig-build.json", - deps = [ - "//packages/core", - "//packages/forms", - "//packages/platform-webworker", - "//packages/platform-webworker-dynamic", - ], -) - -ts_devserver( - name = "devserver", - bootstrap = [ - "@npm//:node_modules/systemjs/dist/system.js", - "//packages/zone.js/bundles:zone.umd.js", - "//packages/zone.js/bundles:long-stack-trace-zone.umd.js", - "@npm//:node_modules/reflect-metadata/Reflect.js", - ], - entry_module = "angular/modules/playground/src/web_workers/todo/index", - port = 4200, - scripts = [ - "@npm//:node_modules/tslib/tslib.js", - "//tools/rxjs:rxjs_umd_modules", - ], - static_files = [ - "index.html", - "css/main.css", - "loader.js", - "//modules/playground/src/web_workers:worker-config", - "//modules/playground:systemjs-config.js", - "//modules/playground:systemjs-rxjs-operators.js", - ], - deps = [":todo"], -) diff --git a/modules/playground/src/web_workers/todo/background_index.ts b/modules/playground/src/web_workers/todo/background_index.ts deleted file mode 100644 index f54e747f426e8..0000000000000 --- a/modules/playground/src/web_workers/todo/background_index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {NgModule} from '@angular/core'; -import {FormsModule} from '@angular/forms'; -import {WorkerAppModule} from '@angular/platform-webworker'; -import {platformWorkerAppDynamic} from '@angular/platform-webworker-dynamic'; - -import {TodoApp} from './index_common'; - -@NgModule({imports: [WorkerAppModule, FormsModule], bootstrap: [TodoApp], declarations: [TodoApp]}) -export class ExampleModule { -} - -platformWorkerAppDynamic().bootstrapModule(ExampleModule); diff --git a/modules/playground/src/web_workers/todo/css/bg.png b/modules/playground/src/web_workers/todo/css/bg.png deleted file mode 100644 index b2a7600825ee1..0000000000000 Binary files a/modules/playground/src/web_workers/todo/css/bg.png and /dev/null differ diff --git a/modules/playground/src/web_workers/todo/css/main.css b/modules/playground/src/web_workers/todo/css/main.css deleted file mode 100644 index 2b3220292b06d..0000000000000 --- a/modules/playground/src/web_workers/todo/css/main.css +++ /dev/null @@ -1,386 +0,0 @@ -@charset "utf-8"; - -html, -body { - margin: 0; - padding: 0; -} - -body { - font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; - line-height: 1.4em; - background: #eaeaea; - color: #4d4d4d; - width: 550px; - margin: 0 auto; -} - -button { - margin: 0; - padding: 0; - border: 0; - background: none; - font-size: 100%; - vertical-align: baseline; - font-family: inherit; - font-weight: inherit; - color: inherit; - -webkit-appearance: none; - -ms-appearance: none; - appearance: none; -} - -button, -input[type="checkbox"] { - outline: none; -} - -.hidden { - display: none; -} - -.visible { - display: block !important; -} - -#todoapp { - background: #fff; - margin: 130px 0 40px 0; - position: relative; - box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), - 0 25px 50px 0 rgba(0, 0, 0, 0.1); -} - -#todoapp input::-webkit-input-placeholder { - font-style: italic; - font-weight: 300; - color: #e6e6e6; -} - -#todoapp input::-moz-placeholder { - font-style: italic; - font-weight: 300; - color: #e6e6e6; -} - -#todoapp input::input-placeholder { - font-style: italic; - font-weight: 300; - color: #e6e6e6; -} - -#todoapp h1 { - position: absolute; - top: -155px; - width: 100%; - font-size: 100px; - font-weight: 100; - text-align: center; - color: rgba(175, 47, 47, 0.15); - -webkit-text-rendering: optimizeLegibility; - -moz-text-rendering: optimizeLegibility; - -ms-text-rendering: optimizeLegibility; - text-rendering: optimizeLegibility; -} - -#new-todo, -.edit { - position: relative; - margin: 0; - width: 100%; - font-size: 24px; - font-family: inherit; - font-weight: inherit; - line-height: 1.4em; - border: 0; - outline: none; - color: inherit; - padding: 6px; - border: 1px solid #999; - box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); - -ms-box-sizing: border-box; - box-sizing: border-box; -} - -#new-todo { - padding: 16px 16px 16px 60px; - border: none; - background: rgba(0, 0, 0, 0.003); - box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03); -} - -#main { - position: relative; - z-index: 2; - border-top: 1px solid #e6e6e6; -} - -label[for='toggle-all'] { - display: none; -} - -#toggle-all { - position: absolute; - top: -55px; - left: -12px; - width: 60px; - height: 34px; - text-align: center; - border: none; /* Mobile Safari */ -} - -#toggle-all:before { - content: '❯'; - font-size: 22px; - color: #e6e6e6; - padding: 10px 27px 10px 27px; -} - -#toggle-all:checked:before { - color: #737373; -} - -#todo-list { - margin: 0; - padding: 0; - list-style: none; -} - -#todo-list li { - position: relative; - font-size: 24px; - border-bottom: 1px solid #ededed; -} - -#todo-list li:last-child { - border-bottom: none; -} - -#todo-list li.editing { - border-bottom: none; - padding: 0; -} - -#todo-list li.editing .edit { - display: block; - width: 506px; - padding: 13px 17px 12px 17px; - margin: 0 0 0 43px; -} - -#todo-list li.editing .view { - display: none; -} - -#todo-list li .toggle { - text-align: center; - width: 40px; - /* auto, since non-WebKit browsers doesn't support input styling */ - height: auto; - position: absolute; - top: 0; - bottom: 0; - margin: auto 0; - border: none; /* Mobile Safari */ - -webkit-appearance: none; - -ms-appearance: none; - appearance: none; -} - -#todo-list li .toggle:after { - content: url('data:image/svg+xml;charset=utf8,'); -} - -#todo-list li .toggle:checked:after { - content: url('data:image/svg+xml;charset=utf8,'); -} - -#todo-list li label { - white-space: pre; - word-break: break-word; - padding: 15px 60px 15px 15px; - margin-left: 45px; - display: block; - line-height: 1.2; - transition: color 0.4s; -} - -#todo-list li.completed label { - color: #d9d9d9; - text-decoration: line-through; -} - -#todo-list li .destroy { - display: none; - position: absolute; - top: 0; - right: 10px; - bottom: 0; - width: 40px; - height: 40px; - margin: auto 0; - font-size: 30px; - color: #cc9a9a; - margin-bottom: 11px; - transition: color 0.2s ease-out; -} - -#todo-list li .destroy:hover { - color: #af5b5e; -} - -#todo-list li .destroy:after { - content: '×'; -} - -#todo-list li:hover .destroy { - display: block; -} - -#todo-list li .edit { - display: none; -} - -#todo-list li.editing:last-child { - margin-bottom: -1px; -} - -#footer { - color: #777; - padding: 10px 15px; - height: 20px; - text-align: center; - border-top: 1px solid #e6e6e6; -} - -#footer:before { - content: ''; - position: absolute; - right: 0; - bottom: 0; - left: 0; - height: 50px; - overflow: hidden; - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), - 0 8px 0 -3px #f6f6f6, - 0 9px 1px -3px rgba(0, 0, 0, 0.2), - 0 16px 0 -6px #f6f6f6, - 0 17px 2px -6px rgba(0, 0, 0, 0.2); -} - -#todo-count { - float: left; - text-align: left; -} - -#todo-count strong { - font-weight: 300; -} - -#filters { - margin: 0; - padding: 0; - list-style: none; - position: absolute; - right: 0; - left: 0; -} - -#filters li { - display: inline; -} - -#filters li a { - color: inherit; - margin: 3px; - padding: 3px 7px; - text-decoration: none; - border: 1px solid transparent; - border-radius: 3px; -} - -#filters li a.selected, -#filters li a:hover { - border-color: rgba(175, 47, 47, 0.1); -} - -#filters li a.selected { - border-color: rgba(175, 47, 47, 0.2); -} - -#clear-completed, -html #clear-completed:active { - float: right; - position: relative; - line-height: 20px; - text-decoration: none; - cursor: pointer; - visibility: hidden; - position: relative; -} - -#clear-completed::after { - visibility: visible; - content: 'Clear completed'; - position: absolute; - right: 0; - white-space: nowrap; -} - -#clear-completed:hover::after { - text-decoration: underline; -} - -#info { - margin: 65px auto 0; - color: #bfbfbf; - font-size: 10px; - text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); - text-align: center; -} - -#info p { - line-height: 1; -} - -#info a { - color: inherit; - text-decoration: none; - font-weight: 400; -} - -#info a:hover { - text-decoration: underline; -} - -/* -Hack to remove background from Mobile Safari. -Can't use it globally since it destroys checkboxes in Firefox -*/ -@media screen and (-webkit-min-device-pixel-ratio:0) { - #toggle-all, - #todo-list li .toggle { - background: none; - } - - #todo-list li .toggle { - height: 40px; - } - - #toggle-all { - -webkit-transform: rotate(90deg); - transform: rotate(90deg); - -webkit-appearance: none; - appearance: none; - } -} - -@media (max-width: 430px) { - #footer { - height: 50px; - } - - #filters { - bottom: 10px; - } -} diff --git a/modules/playground/src/web_workers/todo/index.html b/modules/playground/src/web_workers/todo/index.html deleted file mode 100644 index 329bf4c6a03ef..0000000000000 --- a/modules/playground/src/web_workers/todo/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - Todo Angular - WebWorker - - - - Loading... - - - - - - diff --git a/modules/playground/src/web_workers/todo/index.ts b/modules/playground/src/web_workers/todo/index.ts deleted file mode 100644 index f3791aca9123d..0000000000000 --- a/modules/playground/src/web_workers/todo/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {bootstrapWorkerUi} from '@angular/platform-webworker'; - -bootstrapWorkerUi('loader.js'); diff --git a/modules/playground/src/web_workers/todo/index_common.ts b/modules/playground/src/web_workers/todo/index_common.ts deleted file mode 100644 index 9630d459276e0..0000000000000 --- a/modules/playground/src/web_workers/todo/index_common.ts +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {Component} from '@angular/core'; - -import {Store, Todo, TodoFactory} from './services/TodoStore'; - -@Component({selector: 'todo-app', viewProviders: [Store, TodoFactory], templateUrl: 'todo.html'}) -export class TodoApp { - todoEdit: Todo = null; - inputValue: string; - hideActive: boolean = false; - hideCompleted: boolean = false; - isComplete: boolean = false; - - constructor(public todoStore: Store, public factory: TodoFactory) {} - - enterTodo(): void { - this.addTodo(this.inputValue); - this.inputValue = ''; - } - - doneEditing($event: KeyboardEvent, todo: Todo): void { - const which = $event.keyCode; - if (which === 13) { - todo.title = todo.editTitle; - this.todoEdit = null; - } else if (which === 27) { - this.todoEdit = null; - todo.editTitle = todo.title; - } - } - - editTodo(todo: Todo): void { - this.todoEdit = todo; - } - - addTodo(newTitle: string): void { - this.todoStore.add(this.factory.create(newTitle, false)); - } - - completeMe(todo: Todo): void { - todo.completed = !todo.completed; - } - - toggleCompleted(): void { - this.hideActive = !this.hideActive; - this.hideCompleted = false; - } - - toggleActive(): void { - this.hideCompleted = !this.hideCompleted; - this.hideActive = false; - } - - showAll(): void { - this.hideCompleted = false; - this.hideActive = false; - } - - deleteMe(todo: Todo): void { - this.todoStore.remove(todo); - } - - toggleAll($event: MouseEvent): void { - this.isComplete = !this.isComplete; - this.todoStore.list.forEach((todo: Todo) => { - todo.completed = this.isComplete; - }); - } - - clearCompleted(): void { - this.todoStore.removeBy((todo: Todo) => todo.completed); - } -} diff --git a/modules/playground/src/web_workers/todo/index_web_socket.html b/modules/playground/src/web_workers/todo/index_web_socket.html deleted file mode 100644 index e4fac7623f219..0000000000000 --- a/modules/playground/src/web_workers/todo/index_web_socket.html +++ /dev/null @@ -1,10 +0,0 @@ - - - Todo Angular - WebWorker - - - - Loading... - - - diff --git a/modules/playground/src/web_workers/todo/loader.js b/modules/playground/src/web_workers/todo/loader.js deleted file mode 100644 index 9dd1900c0b1c5..0000000000000 --- a/modules/playground/src/web_workers/todo/loader.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -importScripts('angular/modules/playground/src/web_workers/worker-configure.js'); - -System.config({packages: {'angular/modules/playground/src/web_workers': {defaultExtension: 'js'}}}); - -System.import('./background_index.js') - .catch(error => console.error('error loading background', error)); diff --git a/modules/playground/src/web_workers/todo/services/TodoStore.ts b/modules/playground/src/web_workers/todo/services/TodoStore.ts deleted file mode 100644 index 34896ca7c84bf..0000000000000 --- a/modules/playground/src/web_workers/todo/services/TodoStore.ts +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -import {Injectable} from '@angular/core'; - -// base model for RecordStore -export class KeyModel { - constructor(public key: number) {} -} - -export class Todo extends KeyModel { - editTitle: string; - constructor(key: number, public title: string, public completed: boolean) { - super(key); - this.editTitle = title; - } -} - -@Injectable() -export class TodoFactory { - private _uid: number = 0; - - nextUid(): number { - return ++this._uid; - } - - create(title: string, isCompleted: boolean): Todo { - return new Todo(this.nextUid(), title, isCompleted); - } -} - -// Store manages any generic item that inherits from KeyModel -@Injectable() -export class Store { - list: T[] = []; - - add(record: T): void { - this.list.push(record); - } - - remove(record: T): void { - this.removeBy((item) => item === record); - } - - removeBy(callback: (record: T) => boolean): void { - this.list = this.list.filter((record) => !callback(record)); - } -} diff --git a/modules/playground/src/web_workers/todo/todo.html b/modules/playground/src/web_workers/todo/todo.html deleted file mode 100644 index d65042c440c7b..0000000000000 --- a/modules/playground/src/web_workers/todo/todo.html +++ /dev/null @@ -1,68 +0,0 @@ -
      - - - -
      - - - -
        - -
      • -
        - - - - - - -
        - -
        - - - -
        -
      • -
      - -
      - - - -
      - - diff --git a/modules/playground/src/web_workers/worker-configure.js b/modules/playground/src/web_workers/worker-configure.js deleted file mode 100644 index 8aba8ffcfabde..0000000000000 --- a/modules/playground/src/web_workers/worker-configure.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.io/license - */ - -importScripts('npm/node_modules/reflect-metadata/Reflect.js'); -importScripts('angular/packages/zone.js/bundles/zone.umd.js'); -importScripts('angular/packages/zone.js/bundles/long-stack-trace-zone.umd.js'); -importScripts('npm/node_modules/systemjs/dist/system.js'); - -importScripts('angular/modules/playground/systemjs-config.js'); diff --git a/modules/playground/systemjs-config.js b/modules/playground/systemjs-config.js index e30ed5878ba7c..cc0f8b95b9e9c 100644 --- a/modules/playground/systemjs-config.js +++ b/modules/playground/systemjs-config.js @@ -21,8 +21,6 @@ const angularPackages = [ 'http', 'platform-browser', 'platform-browser-dynamic', - 'platform-webworker', - 'platform-webworker-dynamic', 'router', 'upgrade', 'upgrade/static', diff --git a/package.json b/package.json index 350be9de2de69..c425e2a2ad961 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "angular-srcs", - "version": "10.1.0-next.4", + "version": "11.1.0-next.0", "private": true, "description": "Angular - a web framework for modern web apps", "homepage": "https://github.com/angular/angular", @@ -28,13 +28,12 @@ "test-non-ivy": "bazelisk test --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only", "test-fixme-ivy-aot": "bazelisk test --config=ivy --build_tag_filters=-no-ivy-aot --test_tag_filters=-no-ivy-aot", "list-fixme-ivy-targets": "bazelisk query --output=label 'attr(\"tags\", \"\\[.*fixme-ivy.*\\]\", //...) except kind(\"sh_binary\", //...) except kind(\"devmode_js_sources\", //...)' | sort", - "//circleci-win-comment": "See the test-win circleci job for why these are needed. If they are not needed anymore, remove them.", - "circleci-win-ve": "bazelisk test --build_tag_filters=-ivy-only --test_tag_filters=-ivy-only,-browser:chromium-local //packages/compiler-cli/... //tools/ts-api-guardian/...", - "circleci-win-ivy": "bazelisk test --config=ivy --build_tag_filters=-no-ivy-aot,-fixme-ivy-aot --test_tag_filters=-no-ivy-aot,-fixme-ivy-aot,-browser:chromium-local //packages/compiler-cli/... //tools/ts-api-guardian/...", "lint": "yarn -s tslint && yarn -s ng-dev format changed --check", "tslint": "tsc -p tools/tsconfig.json && tslint -c tslint.json \"+(dev-infra|packages|modules|scripts|tools)/**/*.+(js|ts)\"", "public-api:check": "node goldens/public-api/manage.js test", "public-api:update": "node goldens/public-api/manage.js accept", + "symbol-extractor:check": "node tools/symbol-extractor/run_all_symbols_extractor_tests.js test", + "symbol-extractor:update": "node tools/symbol-extractor/run_all_symbols_extractor_tests.js accept", "ts-circular-deps": "ts-node --transpile-only -- dev-infra/ts-circular-dependencies/index.ts --config ./packages/circular-deps-test.conf.js", "ts-circular-deps:check": "yarn -s ts-circular-deps check", "ts-circular-deps:approve": "yarn -s ts-circular-deps approve", @@ -54,12 +53,12 @@ "@babel/template": "^7.8.6", "@babel/traverse": "^7.8.6", "@babel/types": "^7.8.6", - "@bazel/jasmine": "1.7.0", - "@bazel/karma": "1.7.0", - "@bazel/protractor": "1.7.0", - "@bazel/rollup": "1.7.0", - "@bazel/terser": "1.7.0", - "@bazel/typescript": "1.7.0", + "@bazel/jasmine": "2.2.0", + "@bazel/karma": "2.2.0", + "@bazel/protractor": "2.2.0", + "@bazel/rollup": "2.2.0", + "@bazel/terser": "2.2.0", + "@bazel/typescript": "2.2.0", "@microsoft/api-extractor": "7.7.11", "@octokit/rest": "16.28.7", "@octokit/types": "^5.0.1", @@ -76,19 +75,20 @@ "@types/diff": "^3.5.1", "@types/fs-extra": "4.0.2", "@types/hammerjs": "2.0.35", - "@types/inquirer": "^6.5.0", + "@types/inquirer": "^7.3.0", "@types/jasmine": "3.5.10", "@types/jasmine-ajax": "^3.3.1", "@types/jasminewd2": "^2.0.8", "@types/minimist": "^1.2.0", + "@types/multimatch": "^4.0.0", "@types/node": "^12.11.1", "@types/node-fetch": "^2.5.7", "@types/selenium-webdriver": "3.0.7", "@types/semver": "^6.0.2", "@types/shelljs": "^0.8.6", "@types/systemjs": "0.19.32", - "@types/yaml": "^1.2.0", - "@types/yargs": "^11.1.1", + "@types/yaml": "^1.9.7", + "@types/yargs": "^15.0.5", "@webcomponents/custom-elements": "^1.1.0", "angular": "npm:angular@1.7", "angular-1.5": "npm:angular@1.5", @@ -118,7 +118,7 @@ "jasmine-core": "^3.5.0", "jquery": "3.0.0", "js-levenshtein": "^1.1.6", - "karma": "~4.1.0", + "karma": "~4.4.0", "karma-chrome-launcher": "^2.2.0", "karma-firefox-launcher": "^1.2.0", "karma-jasmine": "^2.0.1", @@ -132,7 +132,7 @@ "node-uuid": "1.4.8", "nodejs-websocket": "^1.7.2", "protractor": "^5.4.2", - "puppeteer": "3.3.0", + "puppeteer": "5.1.0", "reflect-metadata": "^0.1.3", "requirejs": "^2.3.6", "rollup": "^2.16.1", @@ -149,11 +149,11 @@ "terser": "^4.4.0", "tsickle": "0.38.1", "tslib": "^2.0.0", - "tslint": "6.0.0", - "typescript": "~3.9.5", + "tslint": "6.1.3", + "typescript": "~4.0.2", "xhr2": "0.2.0", - "yaml": "^1.7.2", - "yargs": "15.3.0" + "yaml": "^1.10.0", + "yargs": "^15.4.1" }, "// 2": "devDependencies are not used under Bazel. Many can be removed after test.sh is deleted.", "devDependencies": { @@ -169,7 +169,7 @@ "check-side-effects": "0.0.21", "clang-format": "^1.4.0", "cldr": "4.10.0", - "cldr-data": "36.0.0", + "cldr-data-downloader": "0.3.2", "cldrjs": "0.5.0", "cli-progress": "^3.7.0", "conventional-changelog": "^2.0.3", @@ -179,8 +179,9 @@ "glob": "7.1.2", "gulp": "3.9.1", "gulp-conventional-changelog": "^2.0.3", - "husky": "^4.2.3", - "inquirer": "^7.1.0", + "husky": "^4.2.5", + "inquirer": "^7.3.3", + "inquirer-autocomplete-prompt": "^1.0.2", "jpm": "1.3.1", "karma-browserstack-launcher": "^1.3.0", "karma-sauce-launcher": "^2.0.2", @@ -188,8 +189,9 @@ "multimatch": "^4.0.0", "mutation-observer": "^1.0.3", "nock": "^13.0.3", + "ora": "^5.0.0", "rewire": "2.5.2", - "sauce-connect": "https://saucelabs.com/downloads/sc-4.5.1-linux.tar.gz", + "sauce-connect": "https://saucelabs.com/downloads/sc-4.6.2-linux.tar.gz", "semver": "^6.3.0", "ts-node": "^8.6.2", "tslint-eslint-rules": "5.4.0", @@ -209,7 +211,9 @@ "cldr-data-coverage": "full", "husky": { "hooks": { - "commit-msg": "yarn -s ng-dev commit-message pre-commit-validate --file-env-variable HUSKY_GIT_PARAMS" + "pre-commit": "yarn -s ng-dev format staged", + "commit-msg": "yarn -s ng-dev commit-message pre-commit-validate --file-env-variable HUSKY_GIT_PARAMS", + "prepare-commit-msg": "yarn -s ng-dev commit-message restore-commit-message-draft --file-env-variable HUSKY_GIT_PARAMS" } } } diff --git a/packages/BUILD.bazel b/packages/BUILD.bazel index ff8c68c4fa6b2..da0cac42282b7 100644 --- a/packages/BUILD.bazel +++ b/packages/BUILD.bazel @@ -5,8 +5,7 @@ exports_files([ "tsconfig.json", ]) -load("@npm_bazel_typescript//:index.bzl", "ts_config") -load("//tools:defaults.bzl", "ts_library") +load("//tools:defaults.bzl", "ts_config", "ts_library") ts_library( name = "types", diff --git a/packages/animations/browser/src/render/css_keyframes/css_keyframes_driver.ts b/packages/animations/browser/src/render/css_keyframes/css_keyframes_driver.ts index 9f5b771b44fdc..68805f196e2b7 100644 --- a/packages/animations/browser/src/render/css_keyframes/css_keyframes_driver.ts +++ b/packages/animations/browser/src/render/css_keyframes/css_keyframes_driver.ts @@ -72,7 +72,7 @@ export class CssKeyframesDriver implements AnimationDriver { keyframeStr += `}\n`; const kfElm = document.createElement('style'); - kfElm.innerHTML = keyframeStr; + kfElm.textContent = keyframeStr; return kfElm; } diff --git a/packages/animations/browser/test/render/css_keyframes/css_keyframes_driver_spec.ts b/packages/animations/browser/test/render/css_keyframes/css_keyframes_driver_spec.ts index 95c2a61a4048e..c062712e8da23 100644 --- a/packages/animations/browser/test/render/css_keyframes/css_keyframes_driver_spec.ts +++ b/packages/animations/browser/test/render/css_keyframes/css_keyframes_driver_spec.ts @@ -106,7 +106,7 @@ describe('CssKeyframesDriver tests', () => { it('should animate until the `animationend` method is emitted, but stil retain the ')).toEqual(''); + expect(sanitizeHtml(defaultDoc, '')).toEqual(''); }); it('ignores content of style elements', () => { - expect(_sanitizeHtml(defaultDoc, '
      hi
      ')) + expect(sanitizeHtml(defaultDoc, '
      hi
      ')) .toEqual('
      hi
      '); - expect(_sanitizeHtml(defaultDoc, '')).toEqual(''); - expect(_sanitizeHtml(defaultDoc, '')).toEqual(''); + expect(sanitizeHtml(defaultDoc, '')).toEqual(''); + expect(sanitizeHtml(defaultDoc, '')).toEqual(''); expect(logMsgs.join('\n')).toMatch(/sanitizing HTML stripped some content/); }); + it('should strip unclosed iframe tag', () => { + expect(sanitizeHtml(defaultDoc, '