diff --git a/.eslintrc.json b/.eslintrc.json index 55db43c7c..de67877be 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -25,7 +25,7 @@ "no-plusplus": "off", "no-unused-expressions": [2, { "allowShortCircuit": true, "allowTernary": true }], "prefer-destructuring": "off", - + "consistent-return": "off", "no-multi-assign": "off", "no-param-reassign": "off", "no-shadow": "off" diff --git a/.github/workflows/angular.yml b/.github/workflows/angular.yml index 649b58b74..c972c5efb 100644 --- a/.github/workflows/angular.yml +++ b/.github/workflows/angular.yml @@ -22,23 +22,32 @@ on: [push, pull_request] env: JHI_RUN_APP: 1 JHI_JDK: 11 - JHI_LIB_REPO: https://github.com/jhipster/jhipster.git + JHI_LIB_REPO: https://github.com/jhipster/jhipster-bom.git JHI_LIB_BRANCH: release JHI_GEN_REPO: https://github.com/jhipster/generator-jhipster.git - JHI_GEN_BRANCH: v6.10.5 + JHI_GEN_BRANCH: v7.0.0 SPRING_OUTPUT_ANSI_ENABLED: ALWAYS SPRING_JPA_SHOW_SQL: false JHI_DISABLE_WEBPACK_LOGS: true JHI_E2E_HEADLESS: true - JHI_SCRIPTS_PATH: generator-jhipster/test-integration/scripts - JHI_SCRIPTS: $HOME/$JHI_SCRIPTS_PATH - KOTLIN_JHI_SCRIPTS: ${{ github.workspace }}/test-integration/scripts + JHI_FOLDER_APP: ${{ github.workspace }}/app + JHI_HOME: ${{ github.workspace }}/generator-jhipster-kotlin + KOTLIN_JHI_SCRIPTS: ${{ github.workspace }}/generator-jhipster-kotlin/test-integration/scripts NG_CLI_ANALYTICS: 'false' JHI_GITHUB_CI: true + FORCE_COLOR: 1 + # https://github.com/actions/virtual-environments/issues/1499#issuecomment-689467080 + MAVEN_OPTS: >- + -Dhttp.keepAlive=false + -Dmaven.wagon.http.pool=false + -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 jobs: applications: name: ${{ matrix.app-type }} runs-on: ${{ matrix.os }} + defaults: + run: + working-directory: ${{ github.workspace }}/app if: >- !contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]') && @@ -49,102 +58,153 @@ jobs: strategy: fail-fast: false matrix: - node_version: [14.15.0] - os: [ubuntu-latest] + node_version: [14.16.0] + os: [ubuntu-20.04] + cache: [angular] app-type: - ngx-default - - ngx-psql-es-noi18n-mapsid + - ngx-mysql-es-noi18n-mapsid - ngx-mariadb-oauth2-infinispan - - ngx-mongodb-kafka-cucumber - ngx-h2mem-ws-nol2 - ngx-gradle-fr - - ngx-gradle-psql-es-noi18n-mapsid + - ngx-gradle-mysql-es-noi18n-mapsid - ngx-gradle-mariadb-oauth2-infinispan - ngx-gradle-mongodb-kafka-cucumber - - ngx-gradle-yarn-h2disk-ws-nocache + - ngx-gradle-h2disk-ws-nocache include: - app-type: ngx-default - entity: sql - profile: prod + entity: sqlfull + jdl-entity: '*' + environment: prod war: 0 - protractor: 1 + e2e: 1 testcontainers: 1 - - app-type: ngx-psql-es-noi18n-mapsid - entity: sqlfull - profile: prod + sonar-analyse: 1 + - app-type: ngx-mysql-es-noi18n-mapsid + entity: sql + environment: prod war: 0 - protractor: 1 + e2e: 1 testcontainers: 0 - app-type: ngx-mariadb-oauth2-infinispan entity: sqlfull - profile: prod - war: 0 - protractor: 1 - testcontainers: 0 - - app-type: ngx-mongodb-kafka-cucumber - entity: mongodb - profile: dev,webpack + environment: prod war: 0 - protractor: 1 + e2e: 1 testcontainers: 0 - app-type: ngx-h2mem-ws-nol2 entity: sql - profile: dev,webpack + environment: dev war: 0 # TODO: need change to 1, when maven+war is fixed - protractor: 1 + e2e: 1 testcontainers: 0 - app-type: ngx-gradle-fr entity: sql - profile: prod + environment: prod war: 0 - protractor: 1 + e2e: 1 testcontainers: 0 - - app-type: ngx-gradle-psql-es-noi18n-mapsid + - app-type: ngx-gradle-mysql-es-noi18n-mapsid entity: sqlfull - profile: prod + environment: prod war: 0 - protractor: 1 + e2e: 1 testcontainers: 1 - app-type: ngx-gradle-mariadb-oauth2-infinispan entity: sql - profile: dev,webpack + environment: dev war: 0 - protractor: 1 + e2e: 1 testcontainers: 1 - app-type: ngx-gradle-mongodb-kafka-cucumber entity: mongodb - profile: prod + environment: prod war: 0 - protractor: 1 + e2e: 1 testcontainers: 0 - - app-type: ngx-gradle-yarn-h2disk-ws-nocache + - app-type: ngx-gradle-h2disk-ws-nocache entity: sql - profile: dev,webpack + environment: dev war: 1 - protractor: 1 + e2e: 1 testcontainers: 0 env: + JHI_GENERATE_SKIP_CONFIG: 1 JHI_ENTITY: ${{ matrix.entity }} - JHI_APP: ${{ matrix.app-type }} - JHI_PROFILE: ${{ matrix.profile }} + JHI_JDL_ENTITY: ${{ matrix.jdl-entity }} + JHI_APP: ${{ matrix.jhi-app-type || matrix.app-type }} + JHI_PROFILE: ${{ matrix.environment }} JHI_WAR: ${{ matrix.war }} - JHI_PROTRACTOR: ${{ matrix.protractor }} - JHI_TESTCONTAINERS: ${{ matrix.testcontainers }} + JHI_E2E: ${{ matrix.e2e }} + SPRING_PROFILES_ACTIVE: ${{ fromJson('["", "testcontainers"]')[matrix.testcontainers] }} steps: #---------------------------------------------------------------------- # Install all tools and check configuration #---------------------------------------------------------------------- - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - name: 'SETUP: Checkout generator-jhipster-kotlin' + uses: actions/checkout@v2 with: - node-version: ${{ matrix.node_version }} - - name: Download latest chrome binary + path: generator-jhipster-kotlin + fetch-depth: 2 + - name: 'SETUP: Create required structure' run: | - sudo apt update - sudo apt install google-chrome-stable + mkdir app + mkdir -p base/generator-jhipster-kotlin + mkdir -p base/app + working-directory: ${{ github.workspace }} + - uses: actions/setup-node@v2.1.5 + with: + node-version: ${{ matrix.node_version }} - uses: actions/setup-java@v1 with: java-version: '11.x' + - name: 'SETUP: Get date' + id: get-date + run: | + echo "::set-output name=date::$(/bin/date -u "+%Y%m%d")" + - name: 'SETUP: load npm cache' + uses: actions/cache@v2.1.4 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ matrix.cache }}-${{ steps.get-date.outputs.date }}-${{ hashFiles('generator-jhipster/package-lock.json', 'generator-jhipster/**/package.json.ejs') }} + restore-keys: | + ${{ runner.os }}-node-${{ matrix.cache }}-${{ steps.get-date.outputs.date }}- + - name: 'SETUP: load maven cache' + if: "!contains(matrix.app-type, 'gradle')" + uses: actions/cache@v2.1.4 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ steps.get-date.outputs.date }}-${{ hashFiles('generator-jhipster/**/pom.xml.ejs') }} + restore-keys: | + ${{ runner.os }}-maven-${{ steps.get-date.outputs.date }}- + - name: 'SETUP: load jhipster-bom maven cache' + if: contains(matrix.app-type, 'gradle') + uses: actions/cache@v2.1.4 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-jhipster-bom-${{ steps.get-date.outputs.date }}- + restore-keys: | + ${{ runner.os }}-maven-jhipster-bom- + - name: 'SETUP: load gradle cache' + if: contains(matrix.app-type, 'gradle') + uses: actions/cache@v2 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('generator-jhipster/**/build.gradle.ejs') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: 'SETUP: load e2e cache' + if: matrix.e2e == 1 + uses: actions/cache@v2.1.4 + with: + path: ~/.cache/Cypress/ + key: ${{ runner.os }}-cypress-${{ hashFiles('generator-jhipster/client/common/package.json') }} + restore-keys: | + ${{ runner.os }}-cypress- + - name: 'ENV: display variables' + run: $KOTLIN_JHI_SCRIPTS/01-display-configuration.sh - name: 'TOOLS: configure tools installed by the system' run: $KOTLIN_JHI_SCRIPTS/03-system.sh - name: 'TOOLS: configure git' @@ -154,29 +214,100 @@ jobs: #---------------------------------------------------------------------- - name: 'GENERATION: install JHipster' run: $KOTLIN_JHI_SCRIPTS/10-install-jhipster-kotlin.sh - - name: 'GENERATION: entities' - run: $HOME/$JHI_SCRIPTS_PATH/11-generate-entities.sh + - name: 'GENERATION: config' + run: $KOTLIN_JHI_SCRIPTS/11-generate-config.sh - name: 'GENERATION: project' run: $KOTLIN_JHI_SCRIPTS/12-generate-project-kotlin.sh - - name: 'GENERATION: replace version in generated project' - run: $HOME/$JHI_SCRIPTS_PATH/13-replace-version-generated-project.sh - name: 'GENERATION: jhipster info' - run: $HOME/$JHI_SCRIPTS_PATH/14-jhipster-info.sh + run: $KOTLIN_JHI_SCRIPTS/14-jhipster-info.sh + #---------------------------------------------------------------------- + # Detect changes against base commit + #---------------------------------------------------------------------- + - name: 'MERGE: Install base generator-jhipster-kotlin' + continue-on-error: true + id: base-checkout + if: github.event.pull_request + working-directory: ${{ github.workspace }}/base/generator-jhipster-kotlin + run: | + git clone ${{ github.workspace }}/generator-jhipster-kotlin . + git checkout @~1 + git log + npm uninstall -g generator-jhipster-kotlin + npm install + npm install -g . + - name: 'MERGE: merge base project' + continue-on-error: true + id: base-app + if: steps.base-checkout.outcome == 'success' + working-directory: ${{ github.workspace }}/base/app + run: | + $KOTLIN_JHI_SCRIPTS/11-generate-config.sh + # 11-generate-entities.sh removes current dir, we need to switch to the new one + cd ../app + $KOTLIN_JHI_SCRIPTS/12-generate-project-kotlin.sh --skip-install --skip-git + env: + JHI_FOLDER_APP: ${{ github.workspace }}/base/app + - name: 'MERGE: merge project diff' + continue-on-error: true + id: merge-is-equal + if: steps.base-app.outcome == 'success' + working-directory: ${{ github.workspace }}/base/app + run: | + # Copy git repository (clone without the files) + cp -a ${{ github.workspace }}/app/.git . + git log + # File keystore.p12 always changes + # File package-lock.json is not generated + # Verify if the generated source has changed + git add . + git -c color.ui=always diff -R --cached -- '.yo-rc.json' '.jhipster/**' + git -c color.ui=always diff -R --cached --exit-code -- . ':!.yo-rc.json' ':!.jhipster/**' ':!package-lock.json' ':!src/main/resources/config/tls/keystore.p12' || echo "::set-output name=has-changes::true" + - name: 'MERGE: tests should be skipped' + id: tests-should-be-skipped + if: > + steps.merge-is-equal.outcome == 'success' && + steps.merge-is-equal.outputs.has-changes != 'true' + run: echo 'Skipping tests' && echo "::set-output name=skip-tests::true" #---------------------------------------------------------------------- # Launch tests #---------------------------------------------------------------------- - - name: 'TESTS: Start docker-compose containers' - run: $HOME/$JHI_SCRIPTS_PATH/20-docker-compose.sh + - name: 'TESTS: Start docker-compose containers for e2e and backend tests' + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' && matrix.testcontainers != 1 + run: npm run ci:e2e:prepare - name: 'TESTS: backend' - run: $HOME/$JHI_SCRIPTS_PATH/21-tests-backend.sh + id: backend + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' + run: npm run ci:backend:test - name: 'TESTS: frontend' - run: $HOME/$JHI_SCRIPTS_PATH/22-tests-frontend.sh + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' + run: npm run ci:frontend:test - name: 'TESTS: packaging' - run: $HOME/$JHI_SCRIPTS_PATH/23-package.sh - - name: 'TESTS: End-to-End' - run: $HOME/$JHI_SCRIPTS_PATH/24-tests-e2e.sh - - name: 'TESTS: Sonar analysis' - run: $HOME/$JHI_SCRIPTS_PATH/25-sonar-analyze.sh + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' + run: npm run ci:e2e:package + - name: 'TESTS: Start docker-compose containers for e2e tests' + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' && matrix.testcontainers == 1 + run: npm run ci:e2e:prepare + - name: 'E2E: Run' + id: e2e + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' + run: npm run ci:e2e:run --if-present + - name: 'E2E: Teardown' + if: always() && matrix.e2e == 1 && steps.tests-should-be-skipped.outputs.skip-tests != 'true' + run: npm run ci:e2e:teardown + - name: 'BACKEND: Store failure logs' + uses: actions/upload-artifact@v2 + if: always() && steps.backend.outcome == 'failure' + with: + name: log-${{ matrix.app-type }} + path: ${{ github.workspace }}/app/build/test-results/**/*.xml + - name: 'E2E: Store failure screenshots' + uses: actions/upload-artifact@v2 + if: always() && steps.e2e.outcome == 'failure' + with: + name: screenshots-${{ matrix.app-type }} + path: ${{ github.workspace }}/app/*/cypress/screenshots + - name: 'ANALYSIS: Sonar analysis' + run: $KOTLIN_JHI_SCRIPTS/25-sonar-analyze.sh env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.github/workflows/applications.yml b/.github/workflows/applications.yml deleted file mode 100644 index e91578c72..000000000 --- a/.github/workflows/applications.yml +++ /dev/null @@ -1,78 +0,0 @@ -name: KHipster Generated Applications CI -on: [push, pull_request] -env: - JHI_RUN_APP: 1 - JHI_PROTRACTOR: 0 - JHI_JDK: 11 - JHI_LIB_REPO: https://github.com/jhipster/jhipster.git - JHI_LIB_BRANCH: release - JHI_GEN_REPO: https://github.com/jhipster/generator-jhipster.git - JHI_GEN_BRANCH: v6.10.5 - SPRING_OUTPUT_ANSI_ENABLED: ALWAYS - SPRING_JPA_SHOW_SQL: false - JHI_DISABLE_WEBPACK_LOGS: true - JHI_E2E_HEADLESS: true - JHI_SCRIPTS_PATH: generator-jhipster/test-integration/scripts - JHI_SCRIPTS: $HOME/$JHI_SCRIPTS_PATH - KOTLIN_JHI_SCRIPTS: ${{ github.workspace }}/test-integration/scripts - NG_CLI_ANALYTICS: 'false' - JHI_GITHUB_CI: true -jobs: - applications: - name: ${{ matrix.app-type }} application test suite - runs-on: ${{ matrix.os }} - timeout-minutes: 40 - strategy: - fail-fast: false - matrix: - node_version: [12.x] - os: [ubuntu-latest] - app-type: [ngx-session-cassandra-fr, ngx-mongodb-kafka-cucumber, ngx-couchbase] - include: - - app-type: ngx-session-cassandra-fr - entity: cassandra - profile: dev - - app-type: ngx-mongodb-kafka-cucumber - entity: mongodb - profile: dev - - app-type: ngx-couchbase - entity: couchbase - profile: prod - env: - JHI_ENTITY: ${{ matrix.entity }} - JHI_APP: ${{ matrix.app-type }} - JHI_PROFILE: ${{ matrix.profile }} - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node_version }} - - uses: actions/setup-java@v1 - with: - java-version: '11.x' - - name: Stop MySQL server - run: sudo /etc/init.d/mysql stop - - name: Config git variables - run: $KOTLIN_JHI_SCRIPTS/04-git-config.sh - - name: Install KHipster - run: $KOTLIN_JHI_SCRIPTS/10-install-jhipster-kotlin.sh - - name: Generate entities - run: $HOME/$JHI_SCRIPTS_PATH/11-generate-entities.sh - - name: Generate project - run: $KOTLIN_JHI_SCRIPTS/12-generate-project-kotlin.sh - - name: Replace version in the generated project - run: $HOME/$JHI_SCRIPTS_PATH/13-replace-version-generated-project.sh - - name: Jhipster Info - run: $HOME/$JHI_SCRIPTS_PATH/14-jhipster-info.sh - - name: Start docker containers - run: $HOME/$JHI_SCRIPTS_PATH/20-docker-compose.sh - - name: Run backend tests - run: $HOME/$JHI_SCRIPTS_PATH/21-tests-backend.sh - - name: Run frontend tests - run: $HOME/$JHI_SCRIPTS_PATH/22-tests-frontend.sh - - name: Package application - run: $HOME/$JHI_SCRIPTS_PATH/23-package.sh - - name: Run e2e tests - run: $HOME/$JHI_SCRIPTS_PATH/24-tests-e2e.sh - - name: Sonar analysis - run: $HOME/$JHI_SCRIPTS_PATH/25-sonar-analyze.sh diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 2cdbd9b53..5c12105f4 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -1,51 +1,50 @@ -name: "Code scanning - action" +name: 'Code scanning - action' on: - push: - pull_request: - schedule: - - cron: '0 1 * * 0' + push: + pull_request: + schedule: + - cron: '0 1 * * 0' jobs: - CodeQL-Build: - - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - with: - # We must fetch at least the immediate parents so that if this is - # a pull request then we can checkout the head. - fetch-depth: 2 - - # If this run was triggered by a pull request event, then checkout - # the head of the pull request instead of the merge commit. - - run: git checkout HEAD^2 - if: ${{ github.event_name == 'pull_request' }} - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - # Override language selection by uncommenting this and choosing your languages - # with: - # languages: go, javascript, csharp, python, cpp, java - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v1 - - # ℹī¸ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl - - # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language - - #- run: | - # make bootstrap - # make release - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + CodeQL-Build: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + # We must fetch at least the immediate parents so that if this is + # a pull request then we can checkout the head. + fetch-depth: 2 + + # If this run was triggered by a pull request event, then checkout + # the head of the pull request instead of the merge commit. + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + # Override language selection by uncommenting this and choosing your languages + # with: + # languages: go, javascript, csharp, python, cpp, java + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏ī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/generator.yml b/.github/workflows/generator.yml index bdb4e8c00..27e54fe2f 100644 --- a/.github/workflows/generator.yml +++ b/.github/workflows/generator.yml @@ -1,43 +1,56 @@ -name: KHipster Generator CI +# +# Copyright 2013-2021 the original author or authors from the JHipster project. +# +# This file is part of the JHipster project, see https://www.jhipster.tech/ +# for more information. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +name: Generator on: [push, pull_request] -env: - JHI_RUN_APP: 1 - JHI_PROTRACTOR: 0 - JHI_JDK: 11 - JHI_LIB_REPO: https://github.com/jhipster/jhipster.git - JHI_LIB_BRANCH: release - JHI_GEN_REPO: https://github.com/jhipster/generator-jhipster.git - JHI_GEN_BRANCH: v6.10.5 - SPRING_OUTPUT_ANSI_ENABLED: ALWAYS - SPRING_JPA_SHOW_SQL: false - JHI_DISABLE_WEBPACK_LOGS: true - JHI_E2E_HEADLESS: true - JHI_SCRIPTS: $HOME/generator-jhipster/test-integration/scripts - KOTLIN_JHI_SCRIPTS: ${{ github.workspace }}/test-integration/scripts - JHI_GITHUB_CI: true - JHI_APP: '' jobs: - kotlin-hipster: - name: KHipster generator unit test suite + generator-jhipster: + name: npm test runs-on: ${{ matrix.os }} - if: >- - !contains(github.event.head_commit.message, '[ci skip]') && - !contains(github.event.head_commit.message, '[skip ci]') && - !contains(github.event.pull_request.title, '[skip ci]') && - !contains(github.event.pull_request.title, '[ci skip]') && - (github.event.pull_request.draft == false || !contains(github.event.pull_request.labels.*.name, 'pr: skip-ci')) timeout-minutes: 20 strategy: fail-fast: false matrix: - node_version: [14.15.0] - os: [ubuntu-latest] + node_version: [14.16.0] + os: [ubuntu-20.04] steps: - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - uses: actions/setup-node@v2.1.5 with: node-version: ${{ matrix.node_version }} + - name: 'install required npm version' + run: npm install -g npm@$(node -e "console.log(require('generator-jhipster/generators/generator-constants').NPM_VERSION);") + - name: 'install npm@${{ matrix.npm_version }}' + run: npm install -g npm@${{ matrix.npm_version }} + - run: git --no-pager log -n 10 --graph --pretty='%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue) <%an>%Creset' --abbrev-commit + shell: bash - name: Config git variables - run: $KOTLIN_JHI_SCRIPTS/04-git-config.sh - - name: Install and execute unit tests - run: $KOTLIN_JHI_SCRIPTS/10-install-jhipster-kotlin.sh + env: + JHI_SCRIPTS: ./test-integration/scripts + run: $JHI_SCRIPTS/04-git-config.sh + shell: bash + - run: npm ci + - run: npm i -g . + - run: npm test + if: >- + !contains(github.event.head_commit.message, '[ci skip]') && + !contains(github.event.head_commit.message, '[skip ci]') && + !contains(github.event.pull_request.title, '[skip ci]') && + !contains(github.event.pull_request.title, '[ci skip]') && + (github.event.pull_request.draft == false || !contains(github.event.pull_request.labels.*.name, 'pr: skip-ci')) diff --git a/.github/workflows/react.yml b/.github/workflows/react.yml index dd6ffdd2b..11906f871 100644 --- a/.github/workflows/react.yml +++ b/.github/workflows/react.yml @@ -1,5 +1,5 @@ # -# Copyright 2013-2019 the original author or authors from the JHipster project. +# Copyright 2013-2021 the original author or authors from the JHipster project. # # This file is part of the JHipster project, see https://www.jhipster.tech/ # for more information. @@ -8,7 +8,7 @@ # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -22,23 +22,32 @@ on: [push, pull_request] env: JHI_RUN_APP: 1 JHI_JDK: 11 - JHI_LIB_REPO: https://github.com/jhipster/jhipster.git + JHI_LIB_REPO: https://github.com/jhipster/jhipster-bom.git JHI_LIB_BRANCH: release JHI_GEN_REPO: https://github.com/jhipster/generator-jhipster.git - JHI_GEN_BRANCH: v6.10.5 + JHI_GEN_BRANCH: v7.0.0 SPRING_OUTPUT_ANSI_ENABLED: ALWAYS SPRING_JPA_SHOW_SQL: false JHI_DISABLE_WEBPACK_LOGS: true JHI_E2E_HEADLESS: true - JHI_SCRIPTS_PATH: generator-jhipster/test-integration/scripts - JHI_SCRIPTS: $HOME/$JHI_SCRIPTS_PATH - KOTLIN_JHI_SCRIPTS: ${{ github.workspace }}/test-integration/scripts + JHI_FOLDER_APP: ${{ github.workspace }}/app + JHI_HOME: ${{ github.workspace }}/generator-jhipster-kotlin + KOTLIN_JHI_SCRIPTS: ${{ github.workspace }}/generator-jhipster-kotlin/test-integration/scripts NG_CLI_ANALYTICS: 'false' JHI_GITHUB_CI: true + FORCE_COLOR: 1 + # https://github.com/actions/virtual-environments/issues/1499#issuecomment-689467080 + MAVEN_OPTS: >- + -Dhttp.keepAlive=false + -Dmaven.wagon.http.pool=false + -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 jobs: applications: name: ${{ matrix.app-type }} runs-on: ${{ matrix.os }} + defaults: + run: + working-directory: ${{ github.workspace }}/app if: >- !contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]') && @@ -49,95 +58,153 @@ jobs: strategy: fail-fast: false matrix: - node_version: [14.15.0] - os: [ubuntu-latest] + node_version: [14.16.0] + os: [ubuntu-20.04] + cache: [react] app-type: - react-default - - react-maven-psql-es-noi18n-mapsid + - react-maven-mysql-es-noi18n-mapsid - react-maven-h2mem-memcached - react-maven-cassandra-session-redis - - react-maven-couchbase-caffeine - - react-gradle-psql-es-noi18n-mapsid + # - react-maven-couchbase-caffeine + - react-gradle-mysql-es-noi18n-mapsid - react-gradle-h2mem-memcached - react-gradle-cassandra-session-redis - - react-gradle-couchbase-caffeine + # - react-gradle-couchbase-caffeine include: - app-type: react-default entity: sql - profile: prod + environment: prod war: 0 - protractor: 1 + e2e: 1 testcontainers: 0 - - app-type: react-maven-psql-es-noi18n-mapsid + - app-type: react-maven-mysql-es-noi18n-mapsid entity: sqlfull - profile: prod + environment: prod war: 0 - protractor: 1 + e2e: 1 testcontainers: 1 - app-type: react-maven-h2mem-memcached entity: sql - profile: dev,webpack + environment: prod war: 0 # TODO: need change to 1, when maven+war is fixed - protractor: 1 + e2e: 1 testcontainers: 0 - app-type: react-maven-cassandra-session-redis entity: cassandra - profile: prod + environment: prod war: 0 - protractor: 1 - testcontainers: 0 - - app-type: react-maven-couchbase-caffeine - entity: couchbase - profile: prod - war: 0 - protractor: 0 - testcontainers: 0 - - app-type: react-gradle-psql-es-noi18n-mapsid + e2e: 1 + testcontainers: 1 + # - app-type: react-maven-couchbase-caffeine + # entity: couchbase + # environment: prod + # war: 0 + # e2e: 0 + # testcontainers: 0 + - app-type: react-gradle-mysql-es-noi18n-mapsid entity: sqlfull - profile: prod + environment: prod war: 0 - protractor: 1 + e2e: 1 testcontainers: 0 - app-type: react-gradle-h2mem-memcached entity: sql - profile: dev,webpack + environment: prod war: 1 - protractor: 1 + e2e: 1 testcontainers: 0 - app-type: react-gradle-cassandra-session-redis entity: cassandra - profile: prod - war: 0 - protractor: 1 - testcontainers: 0 - - app-type: react-gradle-couchbase-caffeine - entity: couchbase - profile: prod + environment: prod war: 0 - protractor: 1 - testcontainers: 0 + e2e: 1 + testcontainers: 1 + # - app-type: react-gradle-couchbase-caffeine + # entity: couchbase + # environment: prod + # war: 0 + # e2e: 1 + # testcontainers: 0 env: + JHI_GENERATE_SKIP_CONFIG: 1 JHI_ENTITY: ${{ matrix.entity }} + JHI_JDL_ENTITY: ${{ matrix.jdl-entity }} JHI_APP: ${{ matrix.app-type }} - JHI_PROFILE: ${{ matrix.profile }} + JHI_PROFILE: ${{ matrix.environment }} JHI_WAR: ${{ matrix.war }} - JHI_PROTRACTOR: ${{ matrix.protractor }} - JHI_TESTCONTAINERS: ${{ matrix.testcontainers }} + JHI_E2E: ${{ matrix.e2e }} + SPRING_PROFILES_ACTIVE: ${{ fromJson('["", "testcontainers"]')[matrix.testcontainers] }} steps: #---------------------------------------------------------------------- # Install all tools and check configuration #---------------------------------------------------------------------- - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - name: 'SETUP: Checkout generator-jhipster-kotlin' + uses: actions/checkout@v2 + with: + path: generator-jhipster-kotlin + fetch-depth: 2 + - name: 'SETUP: Create required structure' + run: | + mkdir app + mkdir -p base/generator-jhipster-kotlin + mkdir -p base/app + working-directory: ${{ github.workspace }} + - uses: actions/setup-node@v2.1.5 with: node-version: ${{ matrix.node_version }} - uses: actions/setup-java@v1 with: java-version: '11.x' - - name: Download latest chrome binary + - name: 'SETUP: Get date' + id: get-date run: | - sudo apt update - sudo apt install google-chrome-stable + echo "::set-output name=date::$(/bin/date -u "+%Y%m%d")" + - name: 'SETUP: load npm cache' + uses: actions/cache@v2.1.4 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ matrix.cache }}-${{ steps.get-date.outputs.date }}-${{ hashFiles('generator-jhipster/package-lock.json', 'generator-jhipster/**/package.json.ejs') }} + restore-keys: | + ${{ runner.os }}-node-${{ matrix.cache }}-${{ steps.get-date.outputs.date }}- + - name: 'SETUP: load maven cache' + if: "!contains(matrix.app-type, 'gradle')" + uses: actions/cache@v2.1.4 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ steps.get-date.outputs.date }}-${{ hashFiles('generator-jhipster/**/pom.xml.ejs') }} + restore-keys: | + ${{ runner.os }}-maven-${{ steps.get-date.outputs.date }}- + - name: 'SETUP: load jhipster-bom maven cache' + if: contains(matrix.app-type, 'gradle') + uses: actions/cache@v2.1.4 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-jhipster-bom-${{ steps.get-date.outputs.date }}- + restore-keys: | + ${{ runner.os }}-maven-jhipster-bom- + - name: 'SETUP: load gradle cache' + if: contains(matrix.app-type, 'gradle') + uses: actions/cache@v2.1.4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('generator-jhipster/**/build.gradle.ejs') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: 'SETUP: load e2e cache' + if: matrix.e2e == 1 + uses: actions/cache@v2.1.4 + with: + path: ~/.cache/Cypress/ + key: ${{ runner.os }}-cypress-${{ hashFiles('generator-jhipster/client/common/package.json') }} + restore-keys: | + ${{ runner.os }}-cypress- + - name: 'ENV: display variables' + run: $KOTLIN_JHI_SCRIPTS/01-display-configuration.sh + - name: 'TOOLS: install npm@${{ matrix.npm_version }}' + run: npm install -g npm@${{ matrix.npm_version }} - name: 'TOOLS: configure tools installed by the system' run: $KOTLIN_JHI_SCRIPTS/03-system.sh - name: 'TOOLS: configure git' @@ -147,29 +214,101 @@ jobs: #---------------------------------------------------------------------- - name: 'GENERATION: install JHipster' run: $KOTLIN_JHI_SCRIPTS/10-install-jhipster-kotlin.sh - - name: 'GENERATION: entities' - run: $HOME/$JHI_SCRIPTS_PATH/11-generate-entities.sh + - name: 'GENERATION: config' + run: $KOTLIN_JHI_SCRIPTS/11-generate-config.sh - name: 'GENERATION: project' run: $KOTLIN_JHI_SCRIPTS/12-generate-project-kotlin.sh - - name: 'GENERATION: replace version in generated project' - run: $HOME/$JHI_SCRIPTS_PATH/13-replace-version-generated-project.sh - name: 'GENERATION: jhipster info' - run: $HOME/$JHI_SCRIPTS_PATH/14-jhipster-info.sh + run: $KOTLIN_JHI_SCRIPTS/14-jhipster-info.sh + #---------------------------------------------------------------------- + # Detect changes against base commit + #---------------------------------------------------------------------- + - name: 'MERGE: Install base generator-jhipster-kotlin' + continue-on-error: true + id: base-checkout + if: github.event.pull_request + working-directory: ${{ github.workspace }}/base/generator-jhipster-kotlin + run: | + git clone ${{ github.workspace }}/generator-jhipster-kotlin . + git checkout @~1 + git log + npm uninstall -g generator-jhipster-kotlin + npm install + npm install -g . + - name: 'MERGE: merge base project' + continue-on-error: true + id: base-app + if: steps.base-checkout.outcome == 'success' + working-directory: ${{ github.workspace }}/base/app + run: | + $KOTLIN_JHI_SCRIPTS/11-generate-config.sh + # 11-generate-entities.sh removes current dir, we need to switch to the new one + cd ../app + $KOTLIN_JHI_SCRIPTS/12-generate-project.sh --skip-install --skip-git + env: + JHI_FOLDER_APP: ${{ github.workspace }}/base/app + - name: 'MERGE: merge project diff' + continue-on-error: true + id: merge-is-equal + if: steps.base-app.outcome == 'success' + working-directory: ${{ github.workspace }}/base/app + run: | + # Copy git repository (clone without the files) + cp -a ${{ github.workspace }}/app/.git . + git log + # File keystore.p12 always changes + # File package-lock.json is not generated + # Verify if the generated source has changed + git add . + git -c color.ui=always diff -R --cached -- '.yo-rc.json' '.jhipster/**' + git -c color.ui=always diff -R --cached --exit-code -- . ':!.yo-rc.json' ':!.jhipster/**' ':!package-lock.json' ':!src/main/resources/config/tls/keystore.p12' || echo "::set-output name=has-changes::true" + - name: 'MERGE: tests should be skipped' + id: tests-should-be-skipped + if: > + steps.merge-is-equal.outcome == 'success' && + steps.merge-is-equal.outputs.has-changes != 'true' + run: echo 'Skipping tests' && echo "::set-output name=skip-tests::true" #---------------------------------------------------------------------- # Launch tests #---------------------------------------------------------------------- - - name: 'TESTS: Start docker-compose containers' - run: $HOME/$JHI_SCRIPTS_PATH/20-docker-compose.sh + - name: 'TESTS: Start docker-compose containers for e2e and backend tests' + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' && matrix.testcontainers != 1 + run: npm run ci:e2e:prepare - name: 'TESTS: backend' - run: $HOME/$JHI_SCRIPTS_PATH/21-tests-backend.sh + id: backend + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' + run: npm run ci:backend:test - name: 'TESTS: frontend' - run: $HOME/$JHI_SCRIPTS_PATH/22-tests-frontend.sh + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' + run: npm run ci:frontend:test - name: 'TESTS: packaging' - run: $HOME/$JHI_SCRIPTS_PATH/23-package.sh - - name: 'TESTS: End-to-End' - run: $HOME/$JHI_SCRIPTS_PATH/24-tests-e2e.sh - - name: 'TESTS: Sonar analysis' - run: $HOME/$JHI_SCRIPTS_PATH/25-sonar-analyze.sh + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' + run: npm run ci:e2e:package + - name: 'TESTS: Start docker-compose containers for e2e tests' + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' && matrix.testcontainers == 1 + run: npm run ci:e2e:prepare + - name: 'E2E: Run' + id: e2e + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' + run: npm run ci:e2e:run --if-present + - name: 'E2E: Teardown' + if: always() && matrix.e2e == 1 && steps.tests-should-be-skipped.outputs.skip-tests != 'true' + run: npm run ci:e2e:teardown + - name: 'BACKEND: Store failure logs' + uses: actions/upload-artifact@v2 + if: always() && steps.backend.outcome == 'failure' + with: + name: log-${{ matrix.app-type }} + path: ${{ github.workspace }}/app/build/test-results/**/*.xml + - name: 'E2E: Store failure screenshots' + uses: actions/upload-artifact@v2 + if: always() && steps.e2e.outcome == 'failure' + with: + name: screenshots-${{ matrix.app-type }} + path: ${{ github.workspace }}/app/*/cypress/screenshots + - name: 'ANALYSIS: Sonar analysis' + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' + run: $KOTLIN_JHI_SCRIPTS/25-sonar-analyze.sh env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/.github/workflows/webflux.yml b/.github/workflows/webflux.yml index 433f2bc61..ba231b621 100644 --- a/.github/workflows/webflux.yml +++ b/.github/workflows/webflux.yml @@ -1,5 +1,5 @@ # -# Copyright 2013-2020 the original author or authors from the JHipster project. +# Copyright 2013-2021 the original author or authors from the JHipster project. # # This file is part of the JHipster project, see https://www.jhipster.tech/ # for more information. @@ -8,7 +8,7 @@ # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, @@ -22,108 +22,196 @@ on: [push, pull_request] env: JHI_RUN_APP: 1 JHI_JDK: 11 - JHI_LIB_REPO: https://github.com/jhipster/jhipster.git + JHI_LIB_REPO: https://github.com/jhipster/jhipster-bom.git JHI_LIB_BRANCH: release JHI_GEN_REPO: https://github.com/jhipster/generator-jhipster.git - JHI_GEN_BRANCH: v6.10.5 + JHI_GEN_BRANCH: v7.0.0 SPRING_OUTPUT_ANSI_ENABLED: ALWAYS SPRING_JPA_SHOW_SQL: false JHI_DISABLE_WEBPACK_LOGS: true JHI_E2E_HEADLESS: true - JHI_SCRIPTS_PATH: generator-jhipster/test-integration/scripts - JHI_SCRIPTS: $HOME/$JHI_SCRIPTS_PATH - KOTLIN_JHI_SCRIPTS: ${{ github.workspace }}/test-integration/scripts + JHI_FOLDER_APP: ${{ github.workspace }}/app + JHI_HOME: ${{ github.workspace }}/generator-jhipster-kotlin + KOTLIN_JHI_SCRIPTS: ${{ github.workspace }}/generator-jhipster-kotlin/test-integration/scripts NG_CLI_ANALYTICS: 'false' JHI_GITHUB_CI: true + FORCE_COLOR: 1 + # https://github.com/actions/virtual-environments/issues/1499#issuecomment-689467080 + MAVEN_OPTS: >- + -Dhttp.keepAlive=false + -Dmaven.wagon.http.pool=false + -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 jobs: applications: name: ${{ matrix.app-type }} runs-on: ${{ matrix.os }} + defaults: + run: + working-directory: ${{ github.workspace }}/app if: >- !contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.pull_request.title, '[skip ci]') && !contains(github.event.pull_request.title, '[ci skip]') && - (github.event.pull_request.draft == false || !contains(github.event.pull_request.labels.*.name, 'pr: skip-ci')) + (github.event.pull_request.draft == false || !contains(github.event.pull_request.labels.*.name, 'pr: skip-ci')) && + !contains(github.event.pull_request.user.login, 'dependabot') timeout-minutes: 40 strategy: fail-fast: false matrix: - node_version: [14.15.0] - os: [ubuntu-latest] + node_version: [14.16.0] + os: [ubuntu-20.04] + cache: [webflux] app-type: - webflux-mongodb - webflux-mongodb-es-session - webflux-mongodb-oauth2 - webflux-gateway-jwt - - webflux-kt-gateway-oauth2 - - webflux-couchbase - - webflux-couchbase-es-oauth2 - - webflux-psql + - webflux-gateway-oauth2 + # - webflux-couchbase + # - webflux-couchbase-es-oauth2 + # - webflux-psql - https://github.com/pgjdbc/r2dbc-postgresql/issues/397 + # - webflux-mysql + # - webflux-mariadb-gradle - https://github.com/pgjdbc/r2dbc-postgresql/issues/397 include: - app-type: webflux-mongodb entity: mongodb - profile: prod + environment: prod war: 0 - protractor: 1 + e2e: 1 + testcontainers: 1 - app-type: webflux-mongodb-es-session entity: mongodb - profile: prod + environment: prod war: 0 - protractor: 1 + e2e: 1 + testcontainers: 1 - app-type: webflux-mongodb-oauth2 entity: mongodb - profile: prod + environment: prod war: 0 - protractor: 1 + e2e: 1 + testcontainers: 1 - app-type: webflux-gateway-jwt entity: none - profile: prod + environment: prod war: 0 - protractor: 1 - - app-type: webflux-kt-gateway-oauth2 + e2e: 1 + testcontainers: 0 + - app-type: webflux-gateway-oauth2 entity: none - profile: prod + environment: prod war: 0 - protractor: 1 - - app-type: webflux-couchbase - entity: couchbase - profile: prod - war: 0 - protractor: 1 - - app-type: webflux-couchbase-es-oauth2 - entity: couchbase - profile: prod - war: 0 - protractor: 1 - - app-type: webflux-psql - entity: none - profile: prod - war: 0 - protractor: 1 + e2e: 1 + testcontainers: 1 + # - app-type: webflux-couchbase + # entity: couchbase + # profile: prod + # war: 0 + # e2e: 1 + # - app-type: webflux-couchbase-es-oauth2 + # entity: couchbase + # profile: prod + # war: 0 + # e2e: 1 + # - app-type: webflux-psql + # entity: sql + # environment: prod + # war: 0 + # e2e: 1 + # testcontainers: 1 + # - app-type: webflux-mysql + # entity: sqllight + # environment: prod + # war: 0 + # e2e: 1 + # testcontainers: 1 + # Disabled because of missing mariadb Clob converter issue + # - app-type: webflux-mariadb-gradle + # entity: sqllight + # environment: prod + # war: 0 + # e2e: 1 + # testcontainers: 0 env: + JHI_GENERATE_SKIP_CONFIG: 1 JHI_ENTITY: ${{ matrix.entity }} + JHI_JDL_ENTITY: ${{ matrix.jdl-entity }} JHI_APP: ${{ matrix.app-type }} - JHI_PROFILE: ${{ matrix.profile }} + JHI_PROFILE: ${{ matrix.environment }} JHI_WAR: ${{ matrix.war }} - JHI_PROTRACTOR: ${{ matrix.protractor }} + JHI_E2E: ${{ matrix.e2e }} + SPRING_PROFILES_ACTIVE: ${{ fromJson('["", "testcontainers"]')[matrix.testcontainers] }} steps: #---------------------------------------------------------------------- # Install all tools and check configuration #---------------------------------------------------------------------- - - uses: actions/checkout@v2 - - uses: actions/setup-node@v1 + - name: 'SETUP: Checkout generator-jhipster-kotlin' + uses: actions/checkout@v2 with: - node-version: ${{ matrix.node_version }} - - name: Download latest chrome binary + path: generator-jhipster-kotlin + fetch-depth: 2 + - name: 'SETUP: Create required structure' run: | - sudo apt update - sudo apt install google-chrome-stable - - name: 'Install Yarn' - run: npm i -g yarn + mkdir app + mkdir -p base/generator-jhipster-kotlin + mkdir -p base/app + working-directory: ${{ github.workspace }} + - uses: actions/setup-node@v2.1.5 + with: + node-version: ${{ matrix.node_version }} - uses: actions/setup-java@v1 with: java-version: '11.x' + - name: 'SETUP: Get date' + id: get-date + run: | + echo "::set-output name=date::$(/bin/date -u "+%Y%m%d")" + - name: 'SETUP: load npm cache' + uses: actions/cache@v2.1.4 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ matrix.cache }}-${{ steps.get-date.outputs.date }}-${{ hashFiles('generator-jhipster/package-lock.json', 'generator-jhipster/**/package.json.ejs') }} + restore-keys: | + ${{ runner.os }}-node-${{ matrix.cache }}-${{ steps.get-date.outputs.date }}- + - name: 'SETUP: load maven cache' + if: "!contains(matrix.app-type, 'gradle')" + uses: actions/cache@v2.1.4 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ steps.get-date.outputs.date }}-${{ hashFiles('generator-jhipster/**/pom.xml.ejs') }} + restore-keys: | + ${{ runner.os }}-maven-${{ steps.get-date.outputs.date }}- + - name: 'SETUP: load jhipster-bom maven cache' + if: contains(matrix.app-type, 'gradle') + uses: actions/cache@v2.1.4 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-jhipster-bom-${{ steps.get-date.outputs.date }}- + restore-keys: | + ${{ runner.os }}-maven-jhipster-bom- + - name: 'SETUP: load gradle cache' + if: contains(matrix.app-type, 'gradle') + uses: actions/cache@v2.1.4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('generator-jhipster/**/build.gradle.ejs') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: 'SETUP: load e2e cache' + if: matrix.e2e == 1 + uses: actions/cache@v2.1.4 + with: + path: ~/.cache/Cypress/ + key: ${{ runner.os }}-cypress-${{ hashFiles('generator-jhipster/client/common/package.json') }} + restore-keys: | + ${{ runner.os }}-cypress- + - name: 'ENV: display variables' + run: $KOTLIN_JHI_SCRIPTS/01-display-configuration.sh + - name: 'TOOLS: install npm@${{ matrix.npm_version }}' + run: npm install -g npm@${{ matrix.npm_version }} - name: 'TOOLS: configure tools installed by the system' run: $KOTLIN_JHI_SCRIPTS/03-system.sh - name: 'TOOLS: configure git' @@ -133,29 +221,101 @@ jobs: #---------------------------------------------------------------------- - name: 'GENERATION: install JHipster' run: $KOTLIN_JHI_SCRIPTS/10-install-jhipster-kotlin.sh - - name: 'GENERATION: entities' - run: $HOME/$JHI_SCRIPTS_PATH/11-generate-entities.sh + - name: 'GENERATION: config' + run: $KOTLIN_JHI_SCRIPTS/11-generate-config.sh - name: 'GENERATION: project' run: $KOTLIN_JHI_SCRIPTS/12-generate-project-kotlin.sh - - name: 'GENERATION: replace version in generated project' - run: $HOME/$JHI_SCRIPTS_PATH/13-replace-version-generated-project.sh - name: 'GENERATION: jhipster info' - run: $HOME/$JHI_SCRIPTS_PATH/14-jhipster-info.sh + run: $KOTLIN_JHI_SCRIPTS/14-jhipster-info.sh + #---------------------------------------------------------------------- + # Detect changes against base commit + #---------------------------------------------------------------------- + - name: 'MERGE: Install base generator-jhipster-kotlin' + continue-on-error: true + id: base-checkout + if: github.event.pull_request + working-directory: ${{ github.workspace }}/base/generator-jhipster-kotlin + run: | + git clone ${{ github.workspace }}/generator-jhipster-kotlin . + git checkout @~1 + git log + npm uninstall -g generator-jhipster-kotlin + npm install + npm install -g . + - name: 'MERGE: merge base project' + continue-on-error: true + id: base-app + if: steps.base-checkout.outcome == 'success' + working-directory: ${{ github.workspace }}/base/app + run: | + $KOTLIN_JHI_SCRIPTS/11-generate-config.sh + # 11-generate-entities.sh removes current dir, we need to switch to the new one + cd ../app + $KOTLIN_JHI_SCRIPTS/12-generate-project.sh --skip-install --skip-git + env: + JHI_FOLDER_APP: ${{ github.workspace }}/base/app + - name: 'MERGE: merge project diff' + continue-on-error: true + id: merge-is-equal + if: steps.base-app.outcome == 'success' + working-directory: ${{ github.workspace }}/base/app + run: | + # Copy git repository (clone without the files) + cp -a ${{ github.workspace }}/app/.git . + git log + # File keystore.p12 always changes + # File package-lock.json is not generated + # Verify if the generated source has changed + git add . + git -c color.ui=always diff -R --cached -- '.yo-rc.json' '.jhipster/**' + git -c color.ui=always diff -R --cached --exit-code -- . ':!.yo-rc.json' ':!.jhipster/**' ':!package-lock.json' ':!src/main/resources/config/tls/keystore.p12' || echo "::set-output name=has-changes::true" + - name: 'MERGE: tests should be skipped' + id: tests-should-be-skipped + if: > + steps.merge-is-equal.outcome == 'success' && + steps.merge-is-equal.outputs.has-changes != 'true' + run: echo 'Skipping tests' && echo "::set-output name=skip-tests::true" #---------------------------------------------------------------------- # Launch tests #---------------------------------------------------------------------- - - name: 'TESTS: Start docker-compose containers' - run: $HOME/$JHI_SCRIPTS_PATH/20-docker-compose.sh + - name: 'TESTS: Start docker-compose containers for e2e and backend tests' + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' && matrix.testcontainers != 1 + run: npm run ci:e2e:prepare - name: 'TESTS: backend' - run: $HOME/$JHI_SCRIPTS_PATH/21-tests-backend.sh + id: backend + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' + run: npm run ci:backend:test - name: 'TESTS: frontend' - run: $KOTLIN_JHI_SCRIPTS/22-tests-frontend.sh + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' + run: npm run ci:frontend:test - name: 'TESTS: packaging' - run: $HOME/$JHI_SCRIPTS_PATH/23-package.sh - - name: 'TESTS: End-to-End' - run: $HOME/$JHI_SCRIPTS_PATH/24-tests-e2e.sh - - name: 'TESTS: Sonar analysis' - run: $HOME/$JHI_SCRIPTS_PATH/25-sonar-analyze.sh + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' + run: npm run ci:e2e:package + - name: 'TESTS: Start docker-compose containers for e2e tests' + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' && matrix.testcontainers == 1 + run: npm run ci:e2e:prepare + - name: 'E2E: Run' + id: e2e + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' + run: npm run ci:e2e:run --if-present + - name: 'E2E: Teardown' + if: always() && matrix.e2e == 1 && steps.tests-should-be-skipped.outputs.skip-tests != 'true' + run: npm run ci:e2e:teardown + - name: 'BACKEND: Store failure logs' + uses: actions/upload-artifact@v2 + if: always() && steps.backend.outcome == 'failure' + with: + name: log-${{ matrix.app-type }} + path: ${{ github.workspace }}/app/build/test-results/**/*.xml + - name: 'E2E: Store failure screenshots' + uses: actions/upload-artifact@v2 + if: always() && steps.e2e.outcome == 'failure' + with: + name: screenshots-${{ matrix.app-type }} + path: ${{ github.workspace }}/app/*/cypress/screenshots + - name: 'ANALYSIS: Sonar analysis' + if: steps.tests-should-be-skipped.outputs.skip-tests != 'true' + run: $KOTLIN_JHI_SCRIPTS/25-sonar-analyze.sh env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/README.md b/README.md index 3734001eb..bfbb27b53 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,6 @@ > JHipster is a development platform to quickly generate, develop, and deploy modern web applications and microservice architectures. We support many frontend technologies, including Angular, React, and Vue. We even have mobile app support for Ionic and React Native! On the backend, we support Spring Boot (with Java or Kotlin), Micronaut, Quarkus, Node.js, and .NET. For deployment, we embrace cloud native principles with Docker and Kubernetes. Deployment support exists for AWS, Azure, Cloud Foundry, Google Cloud Platform, Heroku, and OpenShift. - Documentation and information about KHipster is available [here](https://www.khipster.dev/) Full documentation and information about JHipster is available [here](https://www.jhipster.tech/) diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index a3bb4ee2f..000000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,151 +0,0 @@ -# -# Copyright 2013-2020 the original author or authors from the JHipster project. -# -# This file is part of the JHipster project, see https://www.jhipster.tech/ -# for more information. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -jobs: - - job: Test - pool: - vmImage: 'Ubuntu 16.04' - variables: - JHI_PROFILE: dev - JHI_RUN_APP: 1 - JHI_PROTRACTOR: 0 - JHI_JDK: 11 - # if JHI_LIB_BRANCH value is release, use the release from Maven - JHI_LIB_REPO: https://github.com/jhipster/jhipster.git - JHI_LIB_BRANCH: release - # if JHI_GEN_BRANCH value is release, use the release from NPM - JHI_GEN_REPO: https://github.com/jhipster/generator-jhipster.git - JHI_GEN_BRANCH: v6.10.5 - # specific config - SPRING_OUTPUT_ANSI_ENABLED: NEVER - SPRING_JPA_SHOW_SQL: false - JHI_DISABLE_WEBPACK_LOGS: true - JHI_E2E_HEADLESS: true - JHI_SCRIPTS: $HOME/generator-jhipster/test-integration/scripts - KOTLIN_JHI_SCRIPTS: $(Build.Repository.LocalPath)/test-integration/scripts - NG_CLI_ANALYTICS: false - - strategy: - matrix: - ms-ngx-gateway-eureka-jwt: - JHI_APP: ms-ngx-gateway-eureka-jwt - JHI_ENTITY: sqllight - JHI_PROFILE: prod - JHI_PROTRACTOR: 1 - ms-ngx-gateway-eureka-oauth2: - JHI_APP: ms-ngx-gateway-eureka-oauth2 - JHI_ENTITY: sqllight - JHI_PROFILE: prod - JHI_PROTRACTOR: 1 - ms-ngx-gateway-eureka-uaa: - JHI_APP: ms-ngx-gateway-eureka-uaa - JHI_ENTITY: uaa - ms-micro-eureka-jwt: - JHI_APP: ms-micro-eureka-jwt - JHI_ENTITY: micro - ms-micro-eureka-infinispan: - JHI_APP: ms-micro-eureka-infinispan - JHI_ENTITY: micro - ms-react-gateway-consul-jwt: - JHI_APP: ms-react-gateway-consul-jwt - JHI_ENTITY: sqllight - JHI_PROFILE: prod - JHI_PROTRACTOR: 1 - ms-react-gateway-consul-oauth2: - JHI_APP: ms-react-gateway-consul-oauth2 - JHI_ENTITY: sqllight - JHI_PROFILE: prod - JHI_PROTRACTOR: 1 - jdl-default: - JHI_APP: jdl-default - JHI_ENTITY: jdl - JHI_PROFILE: prod - JHI_PROTRACTOR: 1 - JHI_TESTCONTAINERS: 1 - - steps: - #---------------------------------------------------------------------- - # Install all tools and check configuration - #---------------------------------------------------------------------- - - task: NodeTool@0 - inputs: - versionSpec: '14.15.0' - displayName: 'TOOLS: install Node.js' - - script: | - if [[ $JHI_JDK = '11' ]]; then - echo '*** Using OpenJDK 11' - sudo add-apt-repository ppa:openjdk-r/ppa - sudo apt-get update - sudo apt-get install -y openjdk-11-jdk - sudo update-java-alternatives -s java-1.11.0-openjdk-amd64 - java -version - else - echo '*** Using OpenJDK 8 by default' - fi - displayName: 'TOOLS: configuring OpenJDK' - - script: | - wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - - sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' - sudo apt update - sudo apt install google-chrome-stable - displayName: 'TOOLS: install google-chrome-stable' - - script: npm install -g npm - displayName: 'TOOLS: update NPM' - - script: npm install -g yarn - displayName: 'TOOLS: install Yarn' - - bash: $(KOTLIN_JHI_SCRIPTS)/01-display-configuration.sh - displayName: 'TOOLS: display configuration' - - bash: $(KOTLIN_JHI_SCRIPTS)/03-system.sh - displayName: 'TOOLS: configure tools installed by the system' - - bash: $(KOTLIN_JHI_SCRIPTS)/04-git-config.sh - displayName: 'TOOLS: configure git' - - #---------------------------------------------------------------------- - # Install JHipster and generate project+entities - #---------------------------------------------------------------------- - - bash: $(KOTLIN_JHI_SCRIPTS)/10-install-jhipster-kotlin.sh - displayName: 'GENERATION: install JHipster' - - bash: $(JHI_SCRIPTS)/11-generate-entities.sh - displayName: 'GENERATION: entities' - - bash: $(KOTLIN_JHI_SCRIPTS)/12-generate-project-kotlin.sh - displayName: 'GENERATION: project' - - bash: $(JHI_SCRIPTS)/13-replace-version-generated-project.sh - displayName: 'GENERATION: replace version in generated project' - - bash: $(JHI_SCRIPTS)/14-jhipster-info.sh - displayName: 'GENERATION: jhipster info' - - #---------------------------------------------------------------------- - # Bugs fix - #---------------------------------------------------------------------- - - bash: $(JHI_SCRIPTS)/20-no-memory-limit-elasticsearch.sh - displayName: 'BUGS-FIX: no memory limit for Elasticsearch' - - #---------------------------------------------------------------------- - # Launch tests - #---------------------------------------------------------------------- - - bash: $(JHI_SCRIPTS)/20-docker-compose.sh - displayName: 'TESTS: Start docker-compose containers' - - bash: $(JHI_SCRIPTS)/21-tests-backend.sh - displayName: 'TESTS: backend' - - bash: $(JHI_SCRIPTS)/22-tests-frontend.sh - displayName: 'TESTS: frontend' - - bash: $(JHI_SCRIPTS)/23-package.sh - displayName: 'TESTS: packaging' - - bash: $(JHI_SCRIPTS)/24-tests-e2e.sh - displayName: 'TESTS: End-to-End' diff --git a/generators/entity-server/files.js b/generators/entity-server/files.js index 3e86c0132..0e12b02b3 100644 --- a/generators/entity-server/files.js +++ b/generators/entity-server/files.js @@ -19,12 +19,12 @@ const path = require('path'); const _ = require('lodash'); const chalk = require('chalk'); -const faker = require('faker'); const fs = require('fs'); const utils = require('generator-jhipster/generators/utils'); const constants = require('generator-jhipster/generators/generator-constants'); const baseServerFiles = require('generator-jhipster/generators/entity-server/files').serverFiles; -const writeFilesToDisk = require('../server/files').writeFilesToDisk; +// const writeFilesToDisk = require('generator-jhipster/generators/generator-base').writeFilesToDisk; +// const writeFilesToDisk = require('../server/files').writeFilesToDisk; const NeedleServerChacheKt = require('./needle-server-cache-kt'); /* Constants use throughout */ @@ -33,9 +33,6 @@ const TEST_DIR = constants.TEST_DIR; const SERVER_MAIN_SRC_KOTLIN_DIR = `${constants.MAIN_DIR}kotlin/`; const SERVER_TEST_SRC_KOTLIN_DIR = `${constants.TEST_DIR}kotlin/`; -/* Use customized randexp */ -const randexp = utils.RandexpWithFaker; - /** * The default is to use a file path string. It implies use of the template method. * For any other config an object { file:.., method:.., template:.. } can be used @@ -69,8 +66,8 @@ const serverFiles = { path: SERVER_MAIN_SRC_KOTLIN_DIR, templates: [ { - file: 'package/service/dto/EntityCriteria.kt', - renameTo: generator => `${generator.packageFolder}/service/dto/${generator.entityClass}Criteria.kt`, + file: 'package/service/criteria/EntityCriteria.kt', + renameTo: generator => `${generator.packageFolder}/service/criteria/${generator.entityClass}Criteria.kt`, useBluePrint: true, }, { @@ -81,7 +78,7 @@ const serverFiles = { ], }, { - condition: generator => generator.searchEngine === 'elasticsearch', + condition: generator => generator.searchEngine === 'elasticsearch' && !generator.embedded, path: SERVER_MAIN_SRC_KOTLIN_DIR, templates: [ { @@ -92,9 +89,7 @@ const serverFiles = { ], }, { - condition: generator => - (!generator.reactive || !['mongodb', 'cassandra', 'couchbase', 'neo4j'].includes(generator.databaseType)) && - !generator.embedded, + condition: generator => !generator.reactive && !generator.embedded, path: SERVER_MAIN_SRC_KOTLIN_DIR, templates: [ { @@ -105,19 +100,32 @@ const serverFiles = { ], }, { - condition: generator => - generator.reactive && - ['mongodb', 'cassandra', 'couchbase', 'neo4j'].includes(generator.databaseType) && - !generator.embedded, + condition: generator => generator.reactive && !generator.embedded, path: SERVER_MAIN_SRC_KOTLIN_DIR, templates: [ { - file: 'package/repository/EntityReactiveRepository.kt', + file: 'package/repository/EntityRepository_reactive.kt', renameTo: generator => `${generator.packageFolder}/repository/${generator.entityClass}ReactiveRepository.kt`, useBluePrint: true, }, ], }, + { + condition: generator => generator.reactive && generator.databaseType === 'sql' && !generator.embedded, + path: SERVER_MAIN_SRC_KOTLIN_DIR, + templates: [ + { + file: 'package/repository/EntityRepositoryInternalImpl_reactive.kt', + renameTo: generator => `${generator.packageFolder}/repository/${generator.entityClass}RepositoryInternalImpl.kt`, + useBluePrint: true, + }, + { + file: 'package/repository/rowmapper/EntityRowMapper.kt', + renameTo: generator => `${generator.packageFolder}/repository/rowmapper/${generator.entityClass}RowMapper.kt`, + useBluePrint: true, + }, + ], + }, { condition: generator => generator.service === 'serviceImpl' && !generator.embedded, path: SERVER_MAIN_SRC_KOTLIN_DIR, @@ -176,7 +184,6 @@ const serverFiles = { file: 'package/web/rest/EntityResourceIT.kt', options: { context: { - randexp, _, chalkRed: chalk.red, fs, @@ -189,7 +196,7 @@ const serverFiles = { ], }, { - condition: generator => generator.searchEngine === 'elasticsearch', + condition: generator => generator.searchEngine === 'elasticsearch' && !generator.embedded, path: SERVER_TEST_SRC_KOTLIN_DIR, templates: [ { @@ -216,7 +223,7 @@ const serverFiles = { templates: [ { file: 'package/domain/EntityTest.kt', - renameTo: generator => `${generator.packageFolder}/domain/${generator.entityClass}Test.kt`, + renameTo: generator => `${generator.packageFolder}/domain/${generator.asEntity(generator.entityClass)}Test.kt`, useBluePrint: true, }, ], @@ -250,53 +257,21 @@ const serverFiles = { module.exports = { writeFiles, serverFiles, + customizeFiles, }; function writeFiles() { return { - saveRemoteEntityPath() { - if (_.isUndefined(this.microservicePath)) { - return; - } - this.copy( - `${this.microservicePath}/${this.jhipsterConfigDirectory}/${this.entityNameCapitalized}.json`, - this.destinationPath(`${this.jhipsterConfigDirectory}/${this.entityNameCapitalized}.json`) - ); - }, - - setupReproducibility() { - if (this.skipServer) return; - - // In order to have consistent results with Faker, restart seed with current entity name hash. - faker.seed(utils.stringHashCode(this.name.toLowerCase())); - }, - writeServerFiles() { if (this.skipServer) return; // write server side files - writeFilesToDisk(serverFiles, this, false, this.fetchFromInstalledJHipster('entity-server/templates')); - - if (this.databaseType === 'sql') { - if (!this.skipDbChangelog) { - if (this.fieldsContainOwnerManyToMany || this.fieldsContainOwnerOneToOne || this.fieldsContainManyToOne) { - this.addConstraintsChangelogToLiquibase(`${this.changelogDate}_added_entity_constraints_${this.entityClass}`); - } - this.addChangelogToLiquibase(`${this.changelogDate}_added_entity_${this.entityClass}`); - } - - const serverCacheKt = new NeedleServerChacheKt(this); - - if (['ehcache', 'caffeine', 'infinispan', 'redis'].includes(this.cacheProvider) && this.enableHibernateCache) { - serverCacheKt.addEntityToCache( - this.asEntity(this.entityClass), - this.relationships, - this.packageName, - this.packageFolder, - this.cacheProvider - ); - } + // writeFilesToDisk(serverFiles, this, false, this.fetchFromInstalledJHipster('entity-server/templates')); + if (this.reactive) { + return this.writeFilesToDisk(serverFiles, ['reactive', '']); } + + return this.writeFilesToDisk(serverFiles); }, writeEnumFiles() { @@ -310,7 +285,7 @@ function writeFiles() { const fieldType = field.fieldType; const enumInfo = { ...utils.getEnumInfo(field, this.clientRootFolder), - angularAppName: this.angularAppName, + frontendAppName: this.frontendAppName, packageName: this.packageName, }; // eslint-disable-next-line no-console @@ -330,3 +305,19 @@ function writeFiles() { }, }; } + +function customizeFiles() { + if (this.databaseType === 'sql') { + const serverCacheKt = new NeedleServerChacheKt(this); + + if (['ehcache', 'caffeine', 'infinispan', 'redis'].includes(this.cacheProvider) && this.enableHibernateCache) { + serverCacheKt.addEntityToCache( + this.asEntity(this.entityClass), + this.relationships, + this.packageName, + this.packageFolder, + this.cacheProvider + ); + } + } +} diff --git a/generators/entity-server/index.js b/generators/entity-server/index.js index dc885f71a..b1727b5a3 100644 --- a/generators/entity-server/index.js +++ b/generators/entity-server/index.js @@ -24,7 +24,8 @@ const writeFiles = require('./files').writeFiles; module.exports = class extends EntityServerGenerator { constructor(args, opts) { super(args, { fromBlueprint: true, ...opts }); // fromBlueprint variable is important - if (!this.jhipsterContext) { + const jhContext = (this.jhipsterContext = this.options.jhipsterContext); + if (!jhContext) { this.error(`This is a JHipster blueprint and should be used only like ${chalk.yellow('jhipster --blueprint kotlin')}`); } } @@ -33,7 +34,26 @@ module.exports = class extends EntityServerGenerator { return super._initializing(); } + get preparingFields() { + return super._preparingFields(); + } + + get default() { + return super._default(); + } + get writing() { - return writeFiles(); + return { + ...writeFiles(), + ...super._missingPostWriting(), + }; + } + + get preparing() { + return super._preparing(); + } + + get postWriting() { + return super._postWriting(); } }; diff --git a/generators/entity-server/templates/partials/it_patch_update.partial.kt.ejs b/generators/entity-server/templates/partials/it_patch_update.partial.kt.ejs new file mode 100644 index 000000000..84054256b --- /dev/null +++ b/generators/entity-server/templates/partials/it_patch_update.partial.kt.ejs @@ -0,0 +1,80 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + + This file is part of the JHipster project, see https://www.jhipster.tech/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +// Initialize the database +<%_ if (primaryKey.type === 'UUID' && databaseType !== 'sql') { _%> + <%= persistInstance %>.<%= primaryKey.name %> =UUID.randomUUID() +<%_ } _%> +<%= entityInstance %>Repository.<%= saveMethod %>(<%= persistInstance %>)<%= callBlock %> + +val databaseSizeBeforeUpdate = <%= entityInstance %>Repository.findAll()<%= callListBlock %>.size + +// Update the <%= entityInstance %> using partial update +val partialUpdated<%= persistClass%> = <%= persistClass%>().apply { + <%= primaryKey.name %> = <%= persistInstance %>.<%= primaryKey.name %> + <%_ fieldsToUpdate = fields.filter(field => field.includeField) %> +<%_ if (fluentMethods && fieldsToUpdate.length > 0) { _%> + <% for (field of fieldsToUpdate) { %> + <%= field.fieldName %> = <%= 'UPDATED_' + field.fieldNameUnderscored.toUpperCase() %><% if (field.fieldWithContentType) { %> + <%= field.fieldName %>ContentType = <%= 'UPDATED_' + field.fieldNameUnderscored.toUpperCase() %>_CONTENT_TYPE<% } %><% } %> +<%_ } else { _%> +<%_ for (field of fieldsToUpdate) { _%> + <%_ if (field.includeField) { %> + <%= field.fieldName %> = <%= field.updateWithValue %> + <%_ if (field.fieldWithContentType) { _%> + <%= field.fieldName %>ContentType = <%= field.updateWithValue %>_CONTENT_TYPE + <%_ } _%> + <%_ } _%> +<%_ } _%> +<%_ } _%> +} + + +<%_ if (!reactive) { _%> +rest<%= entityClass %>MockMvc.perform(patch(ENTITY_API_URL_ID, partialUpdated<%= persistClass %>.<%= primaryKey.name %>)<% if (testsNeedCsrf) { %>.with(csrf())<% }%> +.contentType("application/merge-patch+json") +.content(convertObjectToJsonBytes(<%= 'partialUpdated' + persistClass %>))) +.andExpect(status().isOk) +<%_ } else { _%> +webTestClient +.patch() +.uri(ENTITY_API_URL_ID, partialUpdated<%= persistClass %>.<%= primaryKey.name %>) +.contentType(MediaType.valueOf("application/merge-patch+json")) +.bodyValue(convertObjectToJsonBytes(<%= 'partialUpdated' + persistClass %>)) +.exchange() +.expectStatus() +.isOk +<%_ } _%> + +// Validate the <%= entityClass %> in the database +<%_ if (databaseType === 'couchbase') { _%> +SecurityContextHolder.setContext(TestSecurityContextHolder.getContext()) +<%_ } _%> +val <%= entityInstance %>List = <%= entityInstance %>Repository.findAll()<%= callListBlock %> +assertThat(<%= entityInstance %>List).hasSize(databaseSizeBeforeUpdate) +val test<%= entityClass %> = <%= entityInstance %>List.last() +<%_ for (field of fields) { if (field.fieldType === 'ZonedDateTime') { _%> + assertThat(test<%= entityClass %>.<%= field.fieldName %>).isEqualTo(<%= field.testWithConstant %>) +<%_ } else if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { _%> + assertThat(test<%= entityClass %>.<%= field.fieldName %>).isEqualTo(<%= field.testWithConstant %>) + assertThat(test<%= entityClass %>.<%= field.fieldName %>ContentType).isEqualTo(<%= field.testWithConstant %>_CONTENT_TYPE) +<%_ } else if (field.fieldType === 'BigDecimal'){ _%> + assertThat(test<%= entityClass %>.<%= field.fieldName %>?.stripTrailingZeros()).isEqualByComparingTo(<%= field.testWithConstant %>.stripTrailingZeros()) +<%_ } else { _%> + assertThat(test<%= entityClass %>.<%= field.fieldName %>).isEqualTo(<%= field.testWithConstant %>) +<%_ } } _%> diff --git a/generators/entity-server/templates/src/main/kotlin/package/common/save_template.ejs b/generators/entity-server/templates/partials/save_template.ejs similarity index 72% rename from generators/entity-server/templates/src/main/kotlin/package/common/save_template.ejs rename to generators/entity-server/templates/partials/save_template.ejs index 45a9cc39b..5057c713d 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/common/save_template.ejs +++ b/generators/entity-server/templates/partials/save_template.ejs @@ -16,8 +16,8 @@ See the License for the specific language governing permissions and limitations under the License. -%> -<%_ //const instanceType = (dto === 'mapstruct') ? asDto(entityClass) : asEntity(entityClass); -const instanceName = (dto === 'mapstruct') ? asDto(entityInstance) : asEntity(entityInstance); +<%_ +const instanceName = restInstance; const mapper = `${entityInstance}Mapper`; const dtoToEntity = `${mapper}.toEntity`; const entityToDto = `${mapper}.toDto`; @@ -33,43 +33,46 @@ if (isUsingMapsId === true) { mapsIdRepoInstance = `${mapsIdEntityInstance}Repository`; otherEntityName = mapsIdAssoc.otherEntityName; if (isController === true) { _%> - if (Objects.isNull(<%= instanceName%>.<%= mapsIdAssoc.relationshipName %> <%_ if (dto === 'mapstruct') { _%> Id <%_ } _%>)) { + if (Objects.isNull(<%= instanceName%>.<%= mapsIdAssoc.relationshipName %>)) { throw BadRequestAlertException("Invalid association value provided", ENTITY_NAME, "null") } <%_ } _%> <%_ } if (!viaService) { if (dto === 'mapstruct') { - resultEntity = asEntity(entityInstance) %> - var <%= asEntity(entityInstance) %> = <%= dtoToEntity %>(<%= instanceName %>) + resultEntity = persistInstance %> + var <%= persistInstance %> = <%= dtoToEntity %>(<%= instanceName %>) <%_ if (isUsingMapsId === true) { _%> - val <%= otherEntityName %>Id = <%= instanceName %>.<%= mapsIdAssoc.relationshipName %>Id + val <%= otherEntityName %>Id = <%= instanceName %>.<%= mapsIdAssoc.relationshipName %>?.<%= primaryKey.name %> if (<%= otherEntityName %>Id != null) { <%= mapsIdRepoInstance %>.findById(<%= otherEntityName %>Id) - .ifPresent { <%= asEntity(entityInstance) %>.<%= otherEntityName %> = it } + .ifPresent { <%= persistInstance %>.<%= otherEntityName %> = it } } <%_ } _%> - <%= asEntity(entityInstance) %> = <%= entityInstance %>Repository.save(<%= asEntity(entityInstance) %>) - <%= returnPrefix %> <%= entityToDto %>(<%= asEntity(entityInstance) %>) + <%= persistInstance %> = <%= entityInstance %>Repository.save(<%= persistInstance %>) + <%= returnPrefix %> <%= entityToDto %>(<%= persistInstance %>) <%_ } else { resultEntity = 'result'; _%> <%_ if (isUsingMapsId === true) { _%> - val <%= otherEntityName %>Id = <%= instanceName %>.<%= mapsIdAssoc.relationshipName %>?.id + val <%= otherEntityName %>Id = <%= instanceName %>.<%= mapsIdAssoc.relationshipName %>?.<%= primaryKey.name %> if (<%= otherEntityName %>Id != null) { <%= mapsIdRepoInstance %>.findById(<%= otherEntityName %>Id) - .ifPresent { <%= asEntity(entityInstance) %>.<%= otherEntityName %> = it } + .ifPresent { <%= persistInstance %>.<%= otherEntityName %> = it } } <%_ } _%> - <%= returnPrefix %> <%= entityInstance %>Repository.save(<%= asEntity(entityInstance) %>) - <%_ } if (searchEngine === 'elasticsearch') { _%> + <%= returnPrefix %> <%= entityInstance %>Repository.save(<%= persistInstance %>) + <%_ } + if (searchEngine === 'elasticsearch') { _%> <%= entityInstance %>SearchRepository.save(<%= resultEntity %>) <%_ if (returnDirectly) { _%> return result - <%_ }}} else { _%> + <%_ } + } + } else { _%> <%_ if (isUsingMapsId === true && isController === false) { _%> - val <%= otherEntityName %>Id = <%= entityInstance %>.<%= mapsIdAssoc.relationshipName %>?.id + val <%= otherEntityName %>Id = <%= entityInstance %>.<%= mapsIdAssoc.relationshipName %>?.<%= primaryKey.name %> if (<%= otherEntityName %>Id != null) { <%= mapsIdRepoInstance %>.findById(<%= otherEntityName %>Id) - .ifPresent { <%= asEntity(entityInstance) %>.<%= otherEntityName %> = it } + .ifPresent { <%= persistInstance %>.<%= otherEntityName %> = it } } <%_ } _%> <%= returnPrefix %> <%= entityInstance %>Service.save(<%= instanceName %>) diff --git a/generators/entity-server/templates/reactive/partials/save_template.ejs b/generators/entity-server/templates/reactive/partials/save_template.ejs new file mode 100644 index 000000000..0821bf1be --- /dev/null +++ b/generators/entity-server/templates/reactive/partials/save_template.ejs @@ -0,0 +1,36 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + + This file is part of the JHipster project, see https://www.jhipster.tech/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +<%_ +const instanceName = restInstance; +const mapper = entityInstance + 'Mapper'; +const dtoToEntity = mapper + '.' + 'toEntity'; +const entityToDtoReference = mapper + '::' + 'toDto'; +const returnVal = noReturn ? '' : 'return'; +_%> +<%_ if (viaService) { _%> + <%= returnVal %> <%= entityInstance %>Service.save(<%= instanceName %>) +<%_ } else { _%> + <%= returnVal %> <%= entityInstance %>Repository.save(<%if (dto === 'mapstruct') { %><%= dtoToEntity %>(<% } %><%= instanceName %>)<%if (dto === 'mapstruct') { %>)<% } -%> + <%_ if (searchEngine === 'elasticsearch') { %> + .flatMap(<%= entityInstance %>SearchRepository::save) + <%_ } -%> + <%_ if (dto === 'mapstruct') { %> + .map(<%= entityToDtoReference %>) + <%_ } -%> +<%_ } _%> diff --git a/generators/entity-server/templates/src/main/kotlin/package/common/field_validators.ejs b/generators/entity-server/templates/src/main/kotlin/package/common/field_validators.ejs index f6d486fa6..a7777a6a2 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/common/field_validators.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/common/field_validators.ejs @@ -18,7 +18,6 @@ -%> <%# Returns a string of all validator annotations for the entity field. -%> <% -const field = fields[idx]; let result = ''; if (field.fieldValidate === true) { @@ -28,7 +27,8 @@ if (field.fieldValidate === true) { const isBlob = field.fieldType === 'byte[]'; if (rules.includes('required') && !isBlob) { - validators.push('@get: NotNull'); + // reactive tests need a default validation message because lookup is blocking + validators.push('@get: NotNull' + (reactive ? '(message = "must not be null")' : '')); } if (rules.includes('minlength') && !rules.includes('maxlength')) { validators.push('@get: Size(min = ' + field.fieldValidateRulesMinlength + ')'); diff --git a/generators/entity-server/templates/src/main/kotlin/package/common/get_all_stream_template.ejs b/generators/entity-server/templates/src/main/kotlin/package/common/get_all_stream_template.ejs index be3fa3051..5aadac7eb 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/common/get_all_stream_template.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/common/get_all_stream_template.ejs @@ -19,15 +19,30 @@ <% const mapper = entityInstance + 'Mapper'; const entityToDtoReference = mapper + '::' + 'toDto'; -for (idx in relationships) { if (relationships[idx].relationshipType === 'one-to-one' && relationships[idx].ownerSide !== true) { %> - if ("<%= relationships[idx].relationshipName.toLowerCase() %>-is-null".equals(filter)) { - log.debug("REST request to get all <%= entityClass %>s where <%= relationships[idx].relationshipName %> is null")<% if (viaService) { %> - return <% if (pagination !== 'no') { %>ResponseEntity(<% } %><%= entityInstance %>Service.findAllWhere<%= relationships[idx].relationshipNameCapitalized %>IsNull()<% if (pagination !== 'no') { %>, - HttpStatus.OK)<% } %><% } else { %> - return <% if (pagination !== 'no') { %>ResponseEntity(<% } %><%= entityInstance %>Repository.findAll() +const reactiveSql = (databaseType === 'sql' && reactive); +let toResponseEntityPrefix = ''; +let toResponseEntityPostfix = ''; +if (pagination !== 'no') { + if (reactiveSql) { + toResponseEntityPostfix = '.map(ResponseEntity::ok)'; + } else { + toResponseEntityPrefix = 'ResponseEntity('; + toResponseEntityPostfix = ', HttpStatus.OK)'; + } +} +for (const relationship of relationships) { + if (relationship.relationshipType === 'one-to-one' && relationship.ownerSide !== true) { %> + if ("<%= relationship.relationshipName.toLowerCase() %>-is-null".equals(filter)) { + log.debug("REST request to get all <%= entityClass %>s where <%= relationship.relationshipName %> is null") + <%_ if (viaService) { _%> + return <%- toResponseEntityPrefix %><%= entityInstance %>Service.findAllWhere<%= relationship.relationshipNameCapitalized %>IsNull()<% if (reactiveSql) { %>.collectList()<% } %><%= toResponseEntityPostfix %> + <%_ } else { _%> + return <%- toResponseEntityPrefix %><% if (reactiveSql) { %><%= entityInstance %>Repository.findAllWhere<%= relationship.relationshipNameCapitalized %>IsNull()<% if (dto === 'mapstruct') { %>.map(<%= entityToDtoReference %>)<% } %>.collectList()<%= toResponseEntityPostfix %> + <%_ } else { _%><%= entityInstance %>Repository.findAll() .asSequence() - .filter { it.<%= relationships[idx].relationshipName %> == null }<% if (dto === 'mapstruct') { %> + .filter { it.<%= relationship.relationshipName %> == null }<% if (dto === 'mapstruct') { %> .map(<%= entityToDtoReference %>)<% } if (pagination !== 'no') { %> .toMutableList(), HttpStatus.OK)<% } else { %> - .toMutableList()<% } %><% } %> - }<% } } %> + .toMutableList()<% } %> + <%_ } } _%> + } <% } } %> diff --git a/generators/entity-server/templates/src/main/kotlin/package/common/get_all_template.ejs b/generators/entity-server/templates/src/main/kotlin/package/common/get_all_template.ejs index 4b11e8d03..f510682cd 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/common/get_all_template.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/common/get_all_template.ejs @@ -17,17 +17,19 @@ limitations under the License. -%> <%_ - const instanceType = (dto === 'mapstruct') ? asDto(entityClass) : asEntity(entityClass); + const instanceClass = restClass; + const instanceType = restInstance; const mapper = entityInstance + 'Mapper'; const entityListToDtoListReference = mapper + '.' + 'toDto'; const entityToDtoReference = mapper + '::'+ 'toDto'; + const reactiveEntityToDto = (dto === 'mapstruct' && !viaService) ? `.map(${entityToDtoReference})` : ''; _%> <%_ if (jpaMetamodelFiltering) { _%> fun getAll<%= entityClassPlural %>( criteria: <%= entityClass %>Criteria<% if (pagination != 'no') { %>, pageable: Pageable <% if (reactive) { %>, request: ServerHttpRequest<% } %><% } %> - ): ResponseEntity>> { + ): ResponseEntity>> { log.debug("REST request to get <%= entityClassPlural %> by criteria: $criteria") <%_ if (pagination === 'no') { _%> val entityList = <%= entityInstance %>QueryService.findByCriteria(criteria) @@ -52,42 +54,48 @@ _%> } <% } else { %> <%_ if (pagination === 'no') { _%> - fun getAll<%= entityClassPlural %>(<% if (fieldsContainNoOwnerOneToOne) { %>@RequestParam(required = false) filter: String?<% } %><% if (fieldsContainOwnerManyToMany && fieldsContainNoOwnerOneToOne) { %>,<% } %><% if (fieldsContainOwnerManyToMany) { %>@RequestParam(required = false, defaultValue = "false") eagerload: Boolean<% }%>): <% if (reactive) { %>Mono<<% } %>MutableList<<%= instanceType %>><% if (reactive) { %>><% } %> {<%- include('get_all_stream_template', {viaService: viaService}); -%> + fun getAll<%= entityClassPlural %>(<% if (fieldsContainNoOwnerOneToOne) { %>@RequestParam(required = false) filter: String?<% } %><% if (relationshipsContainEagerLoad && fieldsContainNoOwnerOneToOne) { %>,<% } %><% if (relationshipsContainEagerLoad) { %>@RequestParam(required = false, defaultValue = "false") eagerload: Boolean<% }%>): <% if (reactive) { %>Mono<<% } %>MutableList<<%= instanceClass %>><% if (reactive) { %>><% } %> {<%- include('get_all_stream_template', {viaService: viaService}); -%> log.debug("REST request to get all <%= entityClassPlural %>") <% if (viaService) { %> return <%= entityInstance %>Service.findAll()<% if (reactive) { %>.collectList()<% } %> <% } else if (dto === 'mapstruct') { %> - val <%= entityInstancePlural %> = <%= entityInstance %>Repository.<% if (fieldsContainOwnerManyToMany) { %>findAllWithEagerRelationships<% } else { %>findAll<% } %>() + val <%= entityInstancePlural %> = <%= entityInstance %>Repository.<% if (relationshipsContainEagerLoad) { %>findAllWithEagerRelationships<% } else { %>findAll<% } %>() <%_ if (!reactive) { _%> return <%= entityListToDtoListReference %>(<%= entityInstancePlural %>) <%_ } else { _%> return <%= entityInstancePlural %>.map(<%= entityToDtoReference %>).collectList() <%_ } _%> <%_ } else { _%> - return <%= entityInstance %>Repository.<% if (fieldsContainOwnerManyToMany) { %>findAllWithEagerRelationships<% } else { %>findAll<% } %>()<% if (reactive) { %>.collectList()<% } %> + return <%= entityInstance %>Repository.<% if (relationshipsContainEagerLoad) { %>findAllWithEagerRelationships<% } else { %>findAll<% } %>()<% if (reactive) { %>.collectList()<% } %> <%_ } _%> <%_ } else { _%> - fun getAll<%= entityClassPlural %>(pageable: Pageable<% if (reactive) { %>, request: ServerHttpRequest<% } %><% if (fieldsContainNoOwnerOneToOne) { %>, @RequestParam(required = false) filter: String?<% } %><% if (fieldsContainOwnerManyToMany) { %>, @RequestParam(required = false, defaultValue = "false") eagerload: Boolean<% } %>): <% if (reactive) { %>Mono>>><% } else { %>ResponseEntity>><% } %> {<%- include('get_all_stream_template', {viaService: viaService}); -%> + fun getAll<%= entityClassPlural %>(pageable: Pageable<% if (reactive) { %>, request: ServerHttpRequest<% } %><% if (fieldsContainNoOwnerOneToOne) { %>, @RequestParam(required = false) filter: String?<% } %><% if (relationshipsContainEagerLoad) { %>, @RequestParam(required = false, defaultValue = "false") eagerload: Boolean<% } %>): <% if (reactive) { %>Mono>>><% } else { %>ResponseEntity>><% } %> {<%- include('get_all_stream_template', {viaService: viaService}); -%> log.debug("REST request to get a page of <%= entityClassPlural %>") <%_ if (!reactive) { _%> - <%_ if (fieldsContainOwnerManyToMany) { _%> - val page: Page<<%= instanceType %>> = if (eagerload) { - <%= entityInstance %><%= viaService ? 'Service' : 'Repository' %>.findAllWithEagerRelationships(pageable)<% if (dto === 'mapstruct' && !viaService) { %>.map(<%= entityToDtoReference %>)<% } %> + <%_ if (relationshipsContainEagerLoad) { _%> + val page: Page<<%= instanceClass %>> = if (eagerload) { + <%= entityInstance %><%= viaService ? 'Service' : 'Repository' %>.findAllWithEagerRelationships(pageable)<%= reactiveEntityToDto %> } else { - <%= entityInstance %><%= viaService ? 'Service' : 'Repository' %>.findAll(pageable)<% if (dto === 'mapstruct' && !viaService) { %>.map(<%= entityToDtoReference %>)<% } %> + <%= entityInstance %><%= viaService ? 'Service' : 'Repository' %>.findAll(pageable)<%= reactiveEntityToDto %> } val headers = PaginationUtil.generatePaginationHttpHeaders(<% if (!reactive) { %>ServletUriComponentsBuilder.fromCurrentRequest()<% } else { %>UriComponentsBuilder.fromHttpRequest(request)<% } %>, page) <%_ } else { _%> - val page = <%= entityInstance %><%= viaService ? 'Service' : 'Repository' %>.findAll(pageable)<% if (dto === 'mapstruct' && !viaService) { %>.map(<%= entityToDtoReference %>)<% } %> + val page = <%= entityInstance %><%= viaService ? 'Service' : 'Repository' %>.findAll(pageable)<%= reactiveEntityToDto %> val headers = PaginationUtil.generatePaginationHttpHeaders(<% if (!reactive) { %>ServletUriComponentsBuilder.fromCurrentRequest()<% } else { %>UriComponentsBuilder.fromHttpRequest(request)<% } %>, page); <%_ } _%> return ResponseEntity.ok().headers(headers).body(page.content) <%_ } else { _%> - + // TODO:SK CHECK TYPE info return <%= entityInstance %><%= viaService ? 'Service.countAll' : 'Repository.count' %>() - .map { PageImpl<<%= instanceType %>>(listOf(), pageable, it) } - .map { PaginationUtil.generatePaginationHttpHeaders(UriComponentsBuilder.fromHttpRequest(request), it) } - .map { ResponseEntity.ok().headers(it).body(<%= entityInstance %><%= viaService ? 'Service.findAll' : 'Repository.findAllBy' %>(pageable)<% if (!viaService && dto === 'mapstruct') { %>.map(<%= entityToDtoReference %>)<% } %>) } + .zipWith(<%= entityInstance %><%= viaService ? 'Service.findAll' : 'Repository.findAllBy' %>(pageable)<%= reactiveEntityToDto %>.collectList()) + .map { + ResponseEntity.ok().headers( + PaginationUtil.generatePaginationHttpHeaders( + UriComponentsBuilder.fromHttpRequest(request), + PageImpl(it.t2, pageable, it.t1) + ) + ).body(it.t2) + } <%_ } _%> <%_ } _%> } diff --git a/generators/entity-server/templates/src/main/kotlin/package/common/get_filtered_template.ejs b/generators/entity-server/templates/src/main/kotlin/package/common/get_filtered_template.ejs index a09883ee0..86a67eac6 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/common/get_filtered_template.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/common/get_filtered_template.ejs @@ -17,25 +17,30 @@ limitations under the License. -%> <% -const instanceType = (dto === 'mapstruct') ? asDto(entityClass) : asEntity(entityClass); +const instanceType = restClass; const mapper = entityInstance + 'Mapper'; const entityToDtoReference = mapper + '.toDto(it)'; -for (const idx in relationships) { if (relationships[idx].relationshipType === 'one-to-one' && relationships[idx].ownerSide !== true) { %> +const reactiveSql = (databaseType === 'sql' && reactive); +for (const relationship of relationships) { if (relationship.relationshipType === 'one-to-one' && relationship.ownerSide !== true) { %> /** - * Get all the <%= entityInstancePlural %> where <%= relationships[idx].relationshipNameCapitalized %> is `null`. + * Get all the <%= entityInstancePlural %> where <%= relationship.relationshipNameCapitalized %> is `null`. * @return the list of entities. */<% if (databaseType === 'sql') { %> @Transactional(readOnly = true) <% } %> - <% if (service === 'serviceImpl') { %>override <% } %>fun findAllWhere<%= relationships[idx].relationshipNameCapitalized %>IsNull(): MutableList<<%= instanceType %>> { - log.debug("Request to get all <%= entityInstancePlural %> where <%= relationships[idx].relationshipNameCapitalized %> is null") + <% if (service === 'serviceImpl') { %>override <% } %>fun findAllWhere<%= relationship.relationshipNameCapitalized %>IsNull(): <%= reactiveSql ? 'Flux' : 'MutableList' %><<%= instanceType %>> { + log.debug("Request to get all <%= entityInstancePlural %> where <%= relationship.relationshipNameCapitalized %> is null") + <%_ if (reactiveSql) { _%> + return <%= entityInstance %>Repository.findAllWhere<%= relationship.relationshipNameCapitalized %>IsNull()<% if (dto === 'mapstruct') { _%> + .map(<%= entityToDtoReference %>)<%_ } _%> + <%_ } else { _%> return <%= entityInstance %>Repository.findAll() + .filter { it.<%= relationship.relationshipName %> == null } <%_ if (dto === 'mapstruct') { _%> - .asSequence() - .filter { it.<%= relationships[idx].relationshipName %> == null } - .mapTo(mutableListOf()) { <%= entityToDtoReference %> } - <%_ } else { _%> - .filterTo(mutableListOf()) { it.<%= relationships[idx].relationshipName %> == null } + .map { <%= entityToDtoReference %> } + <%_ } if (!reactiveSql) { _%> + .toMutableList() <%_ } _%> + <%_ } _%> } <% } } %> diff --git a/generators/entity-server/templates/src/main/kotlin/package/common/get_template.ejs b/generators/entity-server/templates/src/main/kotlin/package/common/get_template.ejs index 37e7914aa..319871552 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/common/get_template.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/common/get_template.ejs @@ -16,13 +16,14 @@ See the License for the specific language governing permissions and limitations under the License. -%> -<% const instanceName = (dto === 'mapstruct') ? asDto(entityInstance) : asEntity(entityInstance); +<% + const instanceName = restInstance; const mapper = `${entityInstance}Mapper`; const entityToDtoReference = `${mapper}::toDto`; const returnPrefix = returnDirectly ? 'return' : `val ${instanceName} =`; %> <%_ if (!viaService) { _%> - <%- returnPrefix %> <%= entityInstance %>Repository.<% if (fieldsContainOwnerManyToMany === true) { %>findOneWithEagerRelationships(id)<% } else { %>findById(id)<% } %><% if (dto !== 'mapstruct') { %><% } else { %> + <%- returnPrefix %> <%= entityInstance %>Repository.<% if (relationshipsContainEagerLoad) { %>findOneWithEagerRelationships(id)<% } else { %>findById(id)<% } %><% if (dto !== 'mapstruct') { %><% } else { %> .map(<%= entityToDtoReference %>)<% } %> <%_ } else { _%> <%- returnPrefix %> <%= entityInstance %>Service.findOne(id) diff --git a/generators/entity-server/templates/src/main/kotlin/package/common/inject_template.ejs b/generators/entity-server/templates/src/main/kotlin/package/common/inject_template.ejs index 511192004..b6369cb2a 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/common/inject_template.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/common/inject_template.ejs @@ -19,6 +19,7 @@ <%_ const beans = []; if (viaService) { beans.push({class: `${entityClass}Service`, instance: `${entityInstance}Service`}); + beans.push({class: `${entityClass}Repository`, instance: `${entityInstance}Repository`}); if (queryService) { beans.push({class: `${entityClass}QueryService`, instance: `${entityInstance}QueryService`}); } diff --git a/generators/entity-server/templates/src/main/kotlin/package/common/patch_template.ejs b/generators/entity-server/templates/src/main/kotlin/package/common/patch_template.ejs new file mode 100644 index 000000000..cd5c93ab8 --- /dev/null +++ b/generators/entity-server/templates/src/main/kotlin/package/common/patch_template.ejs @@ -0,0 +1,55 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + + This file is part of the JHipster project, see https://www.jhipster.tech/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +<% +const instanceType = restClass; +const instanceName = restInstance; +const returnType = reactive ? 'Mono' : 'Optional' +const mapOrFlatMap = reactive ? 'flatMap' : 'map' +const returnPrefix = (isService) ? 'return' : 'val result ='; +const mapper = entityInstance + 'Mapper'; +%> +<%_ if(viaService) { %> + val result = <%= entityInstance %>Service.partialUpdate(<%= instanceName %>) +<%_ } else { %> + <%- returnPrefix %> <%= entityInstance %>Repository.findById(<%= instanceName %>.<%= primaryKey.name %>) + .map { + <%_ if(dto === 'mapstruct') { %><%= mapper %>.partialUpdate(it, <%= instanceName %>)<%_ } else { %> + <%_ for (const field of fields.filter(field => !field.id && !field.transient)) { _%> + if (<%= instanceName %>.<%= field.fieldName %>!= null) { + it.<%= field.fieldName %> = <%= instanceName %>.<%= field.fieldName %> + } + <%_ if (field.fieldWithContentType) { _%> + if (<%= instanceName %>.<%= field.fieldName %>ContentType != null) { + it.<%= field.fieldName %>ContentType = <%= instanceName %>.<%= field.fieldName %>ContentType + } + <%_ } } _%> + <%_ } %> + it + } + .<%= mapOrFlatMap %> { <%= entityInstance %>Repository.save(it) }<% if (searchEngine === 'elasticsearch') { %> + .<%= mapOrFlatMap %> { + <%= entityInstance %>SearchRepository.save(it) + <%_ if(!reactive) { %> + it + <%_ } else { %> + Mono.just(it) + <%_ } %> + }<% } %><% if (dto !== 'no') { %> + .map { <%= mapper %>.toDto(it) }<% } %> +<%_ } %> diff --git a/generators/entity-server/templates/src/main/kotlin/package/common/save_reactive_template.ejs b/generators/entity-server/templates/src/main/kotlin/package/common/save_reactive_template.ejs deleted file mode 100644 index fa60fed99..000000000 --- a/generators/entity-server/templates/src/main/kotlin/package/common/save_reactive_template.ejs +++ /dev/null @@ -1,31 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -<%_ const instanceType = (dto === 'mapstruct') ? asDto(entityClass) : asEntity(entityClass); -const instanceName = (dto === 'mapstruct') ? asDto(entityInstance) : asEntity(entityInstance); -const mapper = `${entityInstance}Mapper`; -const dtoToEntity = `${mapper}.toEntity`; -const entityToDtoReference = `${mapper}::toDto`; -_%> -<%_ if (viaService) { _%> - return <%= entityInstance %>Service.save(<%= instanceName %>) -<%_ } else { _%> - return <%= entityInstance %>Repository.save(<%if (dto === 'mapstruct') { %><%= dtoToEntity %>(<% } %><%= instanceName %>)<%if (dto === 'mapstruct') { %>)<% } -%> - <%_ if (searchEngine === 'elasticsearch') { %> - .flatMap { <%= entityInstance %>SearchRepository.save(it) } - <%_ } -%> - <%_ if (dto === 'mapstruct') { %> - .map(<%= entityToDtoReference %>) - <%_ } -%> -<%_ } _%> \ No newline at end of file diff --git a/generators/entity-server/templates/src/main/kotlin/package/common/search_stream_template.ejs b/generators/entity-server/templates/src/main/kotlin/package/common/search_stream_template.ejs index c6a985a28..c300ff7d2 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/common/search_stream_template.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/common/search_stream_template.ejs @@ -18,24 +18,22 @@ -%> <%_ const mapper = `${entityInstance}Mapper`; -const entityToDtoReference = `${mapper}::toDto`; %> +const entityToDtoReference = `${mapper}.toDto`; %> <%_ if (!viaService) { _%> <%_ if (!reactive) { _%> <%_ if (searchEngine === 'elasticsearch') { _%> - return StreamSupport - .stream(<%= entityInstance %>SearchRepository.search(queryStringQuery(query)).spliterator(), false) + return <%= entityInstance %>SearchRepository.search(queryStringQuery(query)) <%_ } else { _%> return <%= entityInstance %>Repository.search(<%= entityClass %>.PREFIX, query) <%_ } _%> <%_ if (dto === 'mapstruct') { _%> - .map(<%= entityToDtoReference %>) - <%_ } _%> - <%_ if (dto === 'mapstruct' || searchEngine !== 'couchbase') { _%> - .collect(Collectors.toList()) + .map { <%= entityToDtoReference %>(it) } <%_ } _%> + .toMutableList() <%_ } else { _%> return <%= entityInstance %><% if (searchEngine === 'elasticsearch') { %>Search<% } %>Repository.search(<% if (searchEngine === 'couchbase') { %><%= entityClass %>.PREFIX, <% } %>query)<%_ if (dto === 'mapstruct') { %> - .map(<%= entityToDtoReference %>)<%_ } %><%_ if (fromResource) { _%>.collectList()<%_ } _%> + .map { <%= entityToDtoReference %>(it) }<%_ } %><%_ if (fromResource) { _%>.collectList()<%_ } _%> + <%_ } _%> <%_ } else { _%> return <%= entityInstance %>Service.search(query)<% if (reactive && fromResource) { %>.collectList()<% } %> diff --git a/generators/entity-server/templates/src/main/kotlin/package/common/search_template.ejs b/generators/entity-server/templates/src/main/kotlin/package/common/search_template.ejs index 0b6754e58..178ee9b90 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/common/search_template.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/common/search_template.ejs @@ -17,7 +17,8 @@ limitations under the License. -%> <%_ - const instanceType = (dto === 'mapstruct') ? asDto(entityClass) : asEntity(entityClass); + const instanceType = restClass; + const instanceName = restInstance; const mapper = `${entityInstance}Mapper`; const listOrFlux = (reactive === true) ? 'Flux' : 'MutableList'; const entityToDtoReference = `${mapper}::toDto`; diff --git a/generators/entity-server/templates/src/main/kotlin/package/domain/Entity.kt.ejs b/generators/entity-server/templates/src/main/kotlin/package/domain/Entity.kt.ejs index 3cdb155ac..76ed11578 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/domain/Entity.kt.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/domain/Entity.kt.ejs @@ -19,21 +19,13 @@ package <%= packageName %>.domain <%_ -let { importApiModelProperty, importJsonIgnore, importJsonIgnoreProperties, importSet, uniqueEnums } = _processJavaEntityImports(fields, relationships); let hasDto = dto === 'mapstruct'; -let isUsingMapsId = false; let hasTextBlob = false; let hasRelationship = relationships.length !== 0; _%> <%_ - for (idx in relationships) { - isUsingMapsId = relationships[idx].useJPADerivedIdentifier === true; - if (isUsingMapsId) { - break; - } - } - for (idx in fields) { - if (prodDatabaseType === 'postgresql' && fields[idx].fieldTypeBlobContent === 'text') { + for (const field of fields.filter(field => !field.transient)) { + if (prodDatabaseType === 'postgresql' && field.fieldTypeBlobContent === 'text') { hasTextBlob = true; break; } @@ -45,20 +37,24 @@ import org.springframework.data.annotation.Id import org.springframework.data.cassandra.core.mapping.Column <%_ } _%> import org.springframework.data.cassandra.core.mapping.Table -<%_ } if (importJsonIgnore === true) { _%> -import com.fasterxml.jackson.annotation.JsonIgnore -<%_ } if (importJsonIgnoreProperties === true) { _%> +<%_ } _%> +<%_ if (relationshipsContainOtherSideIgnore === true) { _%> import com.fasterxml.jackson.annotation.JsonIgnoreProperties -<%_ } if (!hasDto && typeof javadoc != 'undefined') { _%> +<%_ } _%> +<%_ if (!hasDto && typeof javadoc != 'undefined') { _%> import io.swagger.annotations.ApiModel -<%_ } if (!hasDto && importApiModelProperty === true) { _%> +<%_ } _%> +<%_ if (!hasDto && importApiModelProperty === true) { _%> import io.swagger.annotations.ApiModelProperty -<%_ } if (enableHibernateCache) { _%> +<%_ } _%> +<%_ if (enableHibernateCache) { _%> import org.hibernate.annotations.Cache import org.hibernate.annotations.CacheConcurrencyStrategy -<%_ } if (hasTextBlob === true || (fieldsContainUUID === true && ['mysql', 'mariadb'].includes(prodDatabaseType))) { _%> +<%_ } _%> +<%_ if (!reactive && (hasTextBlob === true || (fieldsContainUUID === true && ['mysql', 'mariadb'].includes(prodDatabaseType)))) { _%> import org.hibernate.annotations.Type -<%_ } if (databaseType === 'mongodb') { +<%_ } _%> +<%_ if (databaseType === 'mongodb') { if (!embedded) { _%> import org.springframework.data.annotation.Id import org.springframework.data.mongodb.core.mapping.Document @@ -80,17 +76,24 @@ import org.springframework.data.couchbase.core.query.FetchType import org.springframework.data.couchbase.core.query.N1qlJoin <%_ } _%> <%_ } else if (databaseType === 'neo4j') { _%> -import org.neo4j.springframework.data.core.schema.GeneratedValue -import org.neo4j.springframework.data.core.schema.Id -import org.neo4j.springframework.data.core.schema.Node -import org.neo4j.springframework.data.core.schema.Property -import org.neo4j.springframework.data.core.support.UUIDStringGenerator - <%_ if (hasRelationship) { _%> -import org.neo4j.springframework.data.core.schema.Relationship - <%_ } _%> +import org.springframework.data.neo4j.core.schema.GeneratedValue; +import org.springframework.data.neo4j.core.schema.Id; +import org.springframework.data.neo4j.core.schema.Node; +import org.springframework.data.neo4j.core.schema.Property; +import org.springframework.data.neo4j.core.support.UUIDStringGenerator; +<%_ if (hasRelationship) { _%> +import org.springframework.data.neo4j.core.schema.Relationship +<%_ } _%> <%_ } if (databaseType === 'sql') { _%> - + <%_ if (reactive) { _%> +import org.springframework.data.annotation.Id +import org.springframework.data.annotation.Transient +import org.springframework.data.relational.core.mapping.Column +import org.springframework.data.relational.core.mapping.Table +import org.springframework.data.annotation.PersistenceConstructor + <%_ } else { _%> import javax.persistence.* + <%_ } _%> <%_ } if (validation) { _%> import javax.validation.constraints.* <%_ } _%> @@ -112,7 +115,7 @@ import java.time.ZonedDateTime <%_ } if (fieldsContainDuration === true) { _%> import java.time.Duration <%_ } _%> -<%_ if (databaseType === 'cassandra' || fieldsContainUUID === true) { _%> +<%_ if (fieldsContainUUID) { _%> import java.util.UUID <%_ } Object.keys(uniqueEnums).forEach(function(element) { _%> @@ -127,7 +130,7 @@ import org.springframework.data.couchbase.core.mapping.id.GenerationStrategy.UNI <%_ } _%> <%_ if (typeof javadoc == 'undefined') { _%> /** - * A <%= asEntity(entityClass) %>. + * A <%= persistClass %>. */ <%_ } else { _%> <%- formatAsClassJavadoc(javadoc) %> @@ -136,42 +139,48 @@ import org.springframework.data.couchbase.core.mapping.id.GenerationStrategy.UNI <%_ }_%> <%_ } _%> <%_ if (databaseType === 'sql') { _%> + <%_ if (reactive) { _%> +@Table("<%= entityTableName %>") + <%_ } else { _%> @Entity @Table(name = "<%= entityTableName %>") -<%_ if (enableHibernateCache) { _%> + <%_ if (enableHibernateCache) { _%> @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) -<%_ } -} if (!embedded) { - if (databaseType === 'mongodb') { _%> + <%_ } _%> + <%_ } _%> +<%_ } _%> +<%_ if (!embedded) { _%> + <%_ if (databaseType === 'mongodb') { _%> @Document(collection = "<%= entityTableName %>") - <%_ } if (databaseType === 'neo4j') { _%> + <%_ } else if (databaseType === 'neo4j') { _%> @Node - <%_ } if (databaseType === 'couchbase') { _%> + <%_ } else if (databaseType === 'couchbase') { _%> @Document - <%_ } - } if (databaseType === 'cassandra') { _%> + <%_ } else if (databaseType === 'cassandra') { _%> @Table("<%= entityInstance %>") - <%_ } if (searchEngine === 'elasticsearch') { _%> + <%_ } _%> +<%_ } _%> +<%_ if (searchEngine === 'elasticsearch') { _%> @org.springframework.data.elasticsearch.annotations.Document(indexName = "<%= entityInstance.toLowerCase() %>") <%_ } _%> -data class <%= asEntity(entityClass) %>( +data class <%= persistClass %>( <%_ if (!embedded) { _%> @Id - <%_ if (databaseType === 'sql' && isUsingMapsId === false) { _%> - <%_ if (prodDatabaseType === 'mysql' || prodDatabaseType === 'mariadb') { _%> + <%_ if (databaseType === 'sql' && isUsingMapsId === false && !reactive && !primaryKey.composite) { _%> + <%_ if (primaryKey.fields[0].jpaGeneratedValue === 'identity') { _%> @GeneratedValue(strategy = GenerationType.IDENTITY) - <%_ } else { _%> + <%_ } else if (primaryKey.fields[0].jpaGeneratedValue === 'sequence') { _%> @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") @SequenceGenerator(name = "sequenceGenerator") + <%_ } else if (primaryKey.fields[0].jpaGeneratedValue) { _%> + @GeneratedValue <%_ } _%> - <%_ } _%> - <%_ if (databaseType === 'couchbase' && !embedded) { _%> + <%_ } else if (databaseType === 'couchbase' && !embedded) { _%> @GeneratedValue(strategy = UNIQUE, delimiter = ID_DELIMITER) - <%_ } _%> - <%_ if (databaseType === 'neo4j') { _%> + <%_ } else if (databaseType === 'neo4j') { _%> @GeneratedValue(UUIDStringGenerator::class) <%_ } _%> - var id: <%= primaryKeyType %>? = null, + var <%= primaryKey.name %>: <%= primaryKey.type %>? = null, <%_ } _%> <%_ // TODO temporary calculation update this later. @@ -180,21 +189,24 @@ const relationshipLength = relationships.filter(r => { return !(embedded && !r.otherEntityIsEmbedded && oside === false); }).length - 1; -for (idx in fields) { - if (typeof fields[idx].javadoc !== 'undefined') { _%> -<%- formatAsFieldJavadoc(fields[idx].javadoc) %> +const filteredFields = fields.filter(field => !field.id && !field.transient); +let idx = 0; +for (const field of filteredFields) { + idx++; + if (typeof field.javadoc !== 'undefined') { _%> +<%- formatAsFieldJavadoc(field.javadoc) %> <%_ } let required = false; let unique = false; - const fieldValidate = fields[idx].fieldValidate; - const fieldValidateRules = fields[idx].fieldValidateRules; - const fieldValidateRulesMaxlength = fields[idx].fieldValidateRulesMaxlength; - const fieldType = fields[idx].fieldType; - const fieldTypeBlobContent = fields[idx].fieldTypeBlobContent; - const fieldName = fields[idx].fieldName; - const fieldNameUnderscored = fields[idx].fieldNameUnderscored; - const fieldNameAsDatabaseColumn = fields[idx].fieldNameAsDatabaseColumn; - const comma = (parseInt(idx, 10) === (fields.length - 1) && relationshipLength < 0 ) ? '' : ','; + const fieldValidate = field.fieldValidate; + const fieldValidateRules = field.fieldValidateRules; + const fieldValidateRulesMaxlength = field.fieldValidateRulesMaxlength; + const fieldType = field.fieldType; + const fieldTypeBlobContent = field.fieldTypeBlobContent; + const fieldName = field.fieldName; + const fieldNameUnderscored = field.fieldNameUnderscored; + const fieldNameAsDatabaseColumn = field.fieldNameAsDatabaseColumn; + const comma = (idx === (filteredFields.length - 1) && relationshipLength < 0 ) ? '' : ','; if (fieldValidate === true) { if (fieldValidateRules.includes('required')) { required = true; @@ -202,13 +214,16 @@ for (idx in fields) { if (fieldValidateRules.includes('unique')) { unique = true; } _%> - <%- include('../common/field_validators'); -%> + <%- include('../common/field_validators', {field, reactive}); -%> + <%_ } _%> + <%_ if (!hasDto && typeof field.javadoc != 'undefined') { _%> + @ApiModelProperty(value = "<%- formatAsApiDescription(field.javadoc) %>"<% if (required) { %>, required = true<% } %>) <%_ } _%> - <%_ if (!hasDto && typeof fields[idx].javadoc != 'undefined') { _%> - @ApiModelProperty(value = "<%- formatAsApiDescription(fields[idx].javadoc) %>"<% if (required) { %>, required = true<% } %>) + <%_ if (databaseType === 'sql' && reactive) { _%> + @Column("<%- fieldNameAsDatabaseColumn %>") <%_ } _%> - <%_ if (databaseType === 'sql') { _%> - <%_ if (fields[idx].fieldIsEnum) { _%> + <%_ if (databaseType === 'sql' && !reactive) { + if (field.fieldIsEnum) { _%> @Enumerated(EnumType.STRING) <%_ } if (fieldType === 'byte[]') { _%> @@ -235,42 +250,51 @@ for (idx in fields) { @Property("<%=fieldNameUnderscored %>") <%_ } _%> <%_ if (fieldTypeBlobContent !== 'text') { _%> - var <%= fieldName %>: <% if(fieldType === 'byte[]') { _%>ByteArray<%_ } else if(fieldType==='Integer'){ _%>Int<%_ } else { _%><%= fieldType %><% } %>? = null<%_ if (fieldType === 'byte[]' || fieldType === 'ByteBuffer') { _%>,<%_ } else { _%><%= comma %><%_ } %> + var <%= fieldName %>: <% if(fieldType === 'byte[]') { _%>ByteArray<%_ } else if(fieldType==='Integer'){ _%>Int<%_ } else { _%><%= fieldType %><% } %>? = null<%_ if (fieldType === 'byte[]' || fieldType === 'ByteBuffer') { _%>,<%_ } else { _%>,<%_ } %> <%_ } else { _%> - var <%= fieldName %>: String? = null<%= comma %> + var <%= fieldName %>: String? = null, <%_ } _%> - <%_ if ((fieldType === 'byte[]' || fieldType === 'ByteBuffer') && fieldTypeBlobContent !== 'text') { _%> - <%_ if (databaseType === 'sql' || databaseType === 'cassandra') { _%> + <%_ if (field.fieldWithContentType) { _%> + <%_ if ((databaseType === 'sql' && !reactive) || databaseType === 'cassandra') { _%> @Column(<% if (databaseType !== 'cassandra') { %>name = <% } %>"<%-fieldNameAsDatabaseColumn %>_content_type"<% if (required && databaseType !== 'cassandra') { %>, nullable = false<% } %>) <%_ if (required && databaseType === 'cassandra') { _%> @field:NotNull <%_ } _%> <%_ } _%> + <%_ if (databaseType === 'sql' && reactive) { _%> + @Column("<%- fieldNameAsDatabaseColumn %>_content_type") + <%_ if (required) { _%> + @NotNull + <%_ } _%> + <%_ } _%> <%_ if (databaseType === 'mongodb' || databaseType === 'couchbase') { _%> @Field("<%=fieldNameUnderscored %>_content_type") <%_ } _%> <%_ if (databaseType === 'neo4j') { _%> @Property("<%=fieldNameUnderscored %>_content_type") <%_ } _%> - var <%= fieldName %>ContentType: String? = null<%= comma %> + var <%= fieldName %>ContentType: String? = null, <%_ } _%> <%_ } - for (idx in relationships) { - const otherEntityRelationshipName = relationships[idx].otherEntityRelationshipName; - const otherEntityRelationshipNamePlural = relationships[idx].otherEntityRelationshipNamePlural; - const otherEntityIsEmbedded = relationships[idx].otherEntityIsEmbedded; - const relationshipName = relationships[idx].relationshipName; - const relationshipFieldName = relationships[idx].relationshipFieldName; - const relationshipFieldNamePlural = relationships[idx].relationshipFieldNamePlural; - const joinTableName = getJoinTableName(entityTableName, relationshipName, prodDatabaseType); - const relationshipType = relationships[idx].relationshipType; - const relationshipValidate = relationships[idx].relationshipValidate; - const relationshipRequired = relationships[idx].relationshipRequired; - const otherEntityNameCapitalized = relationships[idx].otherEntityNameCapitalized; - const ownerSide = relationships[idx].ownerSide || false; - const isUsingMapsId = relationships[idx].useJPADerivedIdentifier; + relationships.forEach((relationship, idx) => { + const otherEntityRelationshipName = databaseType === 'neo4j' + ? "HAS_" + _.toUpper(_.snakeCase(relationship.otherEntityRelationshipName)) + : relationship.otherEntityRelationshipName; + const otherEntityRelationshipNamePlural = relationship.otherEntityRelationshipNamePlural; + const otherEntityIsEmbedded = relationship.otherEntityIsEmbedded; + const relationshipName = databaseType === 'neo4j' + ? "HAS_" + _.toUpper(_.snakeCase(relationship.relationshipName)) + : relationship.relationshipName; + const relationshipFieldName = relationship.relationshipFieldName; + const relationshipFieldNamePlural = relationship.relationshipFieldNamePlural; + const relationshipType = relationship.relationshipType; + const relationshipValidate = relationship.relationshipValidate; + const relationshipRequired = relationship.relationshipRequired; + const otherEntityNameCapitalized = relationship.otherEntityNameCapitalized; + const ownerSide = relationship.ownerSide || false; + const isUsingMapsId = relationship.id; const comma = parseInt(idx,10) === relationshipLength ? '' : ','; if (otherEntityRelationshipName) { mappedBy = otherEntityRelationshipName.charAt(0).toLowerCase() + otherEntityRelationshipName.slice(1) @@ -278,17 +302,17 @@ for (idx in fields) { // An embedded entity should not reference entities that embeds it, unless the other entity is also embedded if (embedded && !otherEntityIsEmbedded && ownerSide === false) { - continue; + return; } - if (typeof relationships[idx].javadoc != 'undefined') { _%> -<%- formatAsFieldJavadoc(relationships[idx].javadoc) %> + if (typeof relationship.javadoc != 'undefined') { _%> +<%- formatAsFieldJavadoc(relationship.javadoc) %> <%_ if (!hasDto) { _%> - @ApiModelProperty(value = "<%- formatAsApiDescription(relationships[idx].javadoc) %>") + @ApiModelProperty(value = "<%- formatAsApiDescription(relationship.javadoc) %>") <%_ }_%> <%_ } if (relationshipType === 'one-to-many') { - if (databaseType === 'sql') { + if (databaseType === 'sql' && !reactive) { _%> @OneToMany(mappedBy = "<%= otherEntityRelationshipName %>") <%_ if (enableHibernateCache) { _%> @@ -305,16 +329,25 @@ for (idx in fields) { @N1qlJoin(on = "lks.<%= relationshipFieldName %>=meta(rks).id", fetchType = FetchType.IMMEDIATE) <%_ } _%> <%_ } else if (databaseType === 'neo4j') { _%> - @Relationship + @Relationship("<%= relationshipName %>") + <%_ } else if (databaseType === 'sql' && reactive) { _%> + @Transient <%_ } _%> - var <%= relationshipFieldNamePlural %>: MutableSet<<%= asEntity(otherEntityNameCapitalized) %>> = mutableSetOf()<%= comma %> + <%_ if (relationship.ignoreOtherSideProperty) { _%> + + @JsonIgnoreProperties(value = [ + <%_ const rels = relationship.otherEntity.relationships.map(otherRelationship => `"${otherRelationship.relationshipReferenceField}"`).join(',') _%> + <%- rels %> + ], allowSetters = true) + <%_ } _%> + var <%= relationshipFieldNamePlural %>: MutableSet<<%= asEntity(otherEntityNameCapitalized) %>>? = mutableSetOf(), <%_ } else if (relationshipType === 'many-to-one') { - if (databaseType === 'sql') { + if (databaseType === 'sql' && !reactive) { _%> @ManyToOne<%_ if (relationshipRequired) { _%>(optional = false)<%_ } _%> <%_ if (relationshipValidate) { _%> - <%- include('relationship_validators'); -%> + <%- include('relationship_validators', { relationship }); -%> <%_ } } else if ((databaseType === 'mongodb' || databaseType === 'couchbase') && !otherEntityIsEmbedded) { if (databaseType === 'mongodb') { _%> @@ -326,28 +359,52 @@ for (idx in fields) { @N1qlJoin(on = "lks.<%= relationshipFieldName %>=meta(rks).id", fetchType = FetchType.IMMEDIATE) <%_ } - } else if (databaseType === 'neo4j') { _%> - @Relationship("<%= relationshipFieldName %>") + } else if (databaseType === 'neo4j') { + if (relationship.ignoreOtherSideProperty) { _%> + @Relationship(value = "<%= otherEntityRelationshipName %>", direction = Relationship.Direction.INCOMING) + <%_ } else { _%> + @Relationship("<%= relationshipName %>") + <%_ } + } _%> + <%_ if (relationship.ignoreOtherSideProperty) { _%> + + @JsonIgnoreProperties(value = [ + <%_ const rels = relationship.otherEntity.relationships.map(otherRelationship => `"${otherRelationship.relationshipReferenceField}"`).join(',') _%> + <%- rels %> + ], allowSetters = true) <%_ } _%> - <%_ if (otherEntityRelationshipNamePlural !==undefined && otherEntityRelationshipNamePlural !== '') { _%> - @JsonIgnoreProperties(value = ["<%= otherEntityRelationshipNamePlural %>"], allowSetters = true) + <%_ if (databaseType === 'sql' && reactive) { _%> + @Transient + <%_ } _%> + var <%= relationshipFieldName %>: <%= asEntity(otherEntityNameCapitalized) %>? = null, + + <%_ if (databaseType === 'sql' && reactive) { _%> + @Column("<%= getColumnName(relationshipName) %>_id") + var <%= relationshipFieldName %>Id: <%= relationship.otherEntity.primaryKey.type %>? = null, <%_ } _%> - var <%= relationshipFieldName %>: <%= asEntity(otherEntityNameCapitalized) %>? = null<%= comma %> <%_ } else if (relationshipType === 'many-to-many') { - if (databaseType === 'sql') { _%> + if (databaseType === 'sql' && !reactive) { _%> @ManyToMany<% if (ownerSide === false) { %>(mappedBy = "<%= otherEntityRelationshipNamePlural %>")<% } %> <%_ if (enableHibernateCache) { _%> @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) <%_ } if (ownerSide === true) { if (relationshipValidate) { _%> - <%- include('relationship_validators'); -%> - <%_ } _%> - @JoinTable(name = "<%= joinTableName %>", - joinColumns = [JoinColumn(name = "<%= getColumnName(name) %>_id", referencedColumnName = "id")], - inverseJoinColumns = [JoinColumn(name = "<%= getColumnName(relationships[idx].relationshipName) %>_id", referencedColumnName = "id")]) - <%_ } - } else if ((databaseType === 'mongodb' || databaseType === 'couchbase') && !otherEntityIsEmbedded) { + <%- include('relationship_validators', { relationship }); -%> + <%_ } _%> + @JoinTable(name = "<%= relationship.joinTable.name %>", + joinColumns = [ + <%_ entity.primaryKey.fields.forEach((field, idx) => { _%> + JoinColumn(name = "<%= `${entityTableName}_${field.columnName}` %>") <%= idx === 0 ? '' : ',' %> + <%_ }) _%> + ], + inverseJoinColumns = [ + <%_ relationship.otherEntity.primaryKey.fields.forEach((field, idx) => { _%> + JoinColumn(name = "<%= `${relationship.columnName}_${field.columnName}` %>")<%= idx === 0 ? '' : ',' %> + <%_ }) _%> + ] + ) <%_ } + } else if ((databaseType === 'mongodb' || databaseType === 'couchbase') && !otherEntityIsEmbedded) { if (databaseType === 'mongodb') { _%> @DBRef <%_ } _%> @@ -357,27 +414,47 @@ for (idx in fields) { @N1qlJoin(on = "lks.<%= relationshipFieldNamePlural %>=meta(rks).id", fetchType = FetchType.IMMEDIATE) <%_ } - } if (ownerSide === false) { _%> - @JsonIgnore + } else if (databaseType === 'neo4j') { _%> + @Relationship(<%_ + if (ownerSide === true) { _%>"<%= relationshipName %>"<%_ + } else { _%>value = "<%= otherEntityRelationshipName %>", direction = Relationship.Direction.INCOMING<%_ } _%>)<%_ + } + if (relationship.ignoreOtherSideProperty) { _%> + + @JsonIgnoreProperties(value = [ + <%_ const rels = relationship.otherEntity.relationships.map(otherRelationship => `"${otherRelationship.relationshipReferenceField}"`).join(',') _%> + <%- rels %> + ], allowSetters = true) <%_ } _%> - var <%= relationshipFieldNamePlural %>: MutableSet<<%= asEntity(otherEntityNameCapitalized) %>> = mutableSetOf()<%= comma %> + <%_ if (databaseType === 'sql' && reactive) { _%> + @Transient + <%_ } else if (databaseType === 'neo4j') { _%> + @Relationship("<%= relationshipName %>") + <%_ } _%> + var <%= relationshipFieldNamePlural %>: MutableSet<<%= asEntity(otherEntityNameCapitalized) %>>? = mutableSetOf(), <%_ } else { - if (databaseType === 'sql') { + if (databaseType === 'sql' && !reactive) { + if (relationship.ignoreOtherSideProperty) { _%> + + @JsonIgnoreProperties(value = [ + <%_ const rels = relationship.otherEntity.relationships.map(otherRelationship => `"${otherRelationship.relationshipReferenceField}"`).join(',') _%> + <%- rels %> + ], allowSetters = true) + <%_ } if (ownerSide) { _%> @OneToOne<%_ if (relationshipRequired) { _%>(optional = false)<%_ } _%> <%_ if (relationshipValidate) { _%> - <%- include('relationship_validators'); -%> + <%- include('relationship_validators', { relationship }); -%> <%_ }_%> <%_ if (isUsingMapsId === true) { %> @MapsId - @JoinColumn(name = "id") + @JoinColumn(name = "<%= relationship.otherEntity.primaryKey.fields[0].columnName %>") <%_ } else { _%> @JoinColumn(unique = true) <%_ } _%> <%_ } else { _%> @OneToOne(mappedBy = "<%= otherEntityRelationshipName %>") - @JsonIgnore <%_ } } else if ((databaseType === 'mongodb' || databaseType === 'couchbase') && !otherEntityIsEmbedded) { if (databaseType === 'mongodb') { _%> @@ -388,16 +465,86 @@ for (idx in fields) { var <%= relationshipFieldName %>Id: String? = null, @N1qlJoin(on = "lks.<%= relationshipFieldName %>=meta(rks).id", fetchType = FetchType.IMMEDIATE) - <%_ } if (ownerSide === false) { _%> - @com.fasterxml.jackson.annotation.JsonBackReference - <%_ } - } _%> - var <%= relationshipFieldName %>: <%= asEntity(otherEntityNameCapitalized) %>? = null<%= comma %> + <%_ } + } else if (databaseType === 'sql' && reactive) { _%> + <%_ if (ownerSide === true && isUsingMapsId !== true) { _%> + var <%= relationshipFieldName %>Id: <%= relationship.otherEntity.primaryKey.type %>? = null, + <%_ } _%> + @Transient + <%_ } _%> + var <%= relationshipFieldName %>: <%= asEntity(otherEntityNameCapitalized) %>? = null, <%_ } - } _%> +}); _%> // jhipster-needle-entity-add-field - JHipster will add fields here ) : Serializable { + +<%_ if(databaseType === 'sql' && reactive && hasRelationship) { _%> + + @PersistenceConstructor + constructor ( + <%_ if (!embedded) { _%> + <%= primaryKey.name %>: <%= primaryKey.type %>?, + <%_ } _%> + <%_ + const filteredFields = fields.filter(field => !field.id && !field.transient); + for (const field of filteredFields) { + let required = false; + let unique = false; + const fieldType = field.fieldType; + const fieldTypeBlobContent = field.fieldTypeBlobContent; + const fieldName = field.fieldName; + + if (fieldTypeBlobContent !== 'text') { + _%> + <%= fieldName %>: <% if(fieldType === 'byte[]') { _%>ByteArray<%_ } else if(fieldType==='Integer'){ _%>Int<%_ } else { _%><%= fieldType %><% } %>?, + <%_ } else { _%> + <%= fieldName %>: String?, + <%_ } _%> + + <%_ if (field.fieldWithContentType) { _%> + <%= fieldName %>ContentType: String?, + <%_ } } _%> + ): this( + <%_ if (!embedded) { _%> + <%= primaryKey.name %>, + <%_ } _%> + <%_ + const filteredFieldsInConstructor = fields.filter(field => !field.id && !field.transient); + for (const field of filteredFieldsInConstructor) { + const fieldName = field.fieldName; + _%> + <%= fieldName %>, + <%_ if (field.fieldWithContentType) { _%> + <%= fieldName %>ContentType, + <%_ } _%> + <%_ } _%> + <%_ + relationships.forEach((relationship, idx) => { + const relationshipType = relationship.relationshipType; + + // An embedded entity should not reference entities that embeds it, unless the other entity is also embedded + if (embedded && !otherEntityIsEmbedded && ownerSide === false) { + return; + } + + if (relationshipType === 'one-to-many') { + _%> + null, + + <%_ } else if (relationshipType === 'many-to-one') { _%> + null, + null, + + <%_ } else if (relationshipType === 'many-to-many') { _%> + null, + + <%_ } else { _%> + null, + <%_ } }); _%> + ) +<%_ } _%> + <%_ if (databaseType === 'couchbase' && !embedded) { _%> @Suppress("unused") @@ -405,58 +552,73 @@ for (idx in fields) { private val prefix: String = PREFIX <%_ } _%> <%_ - for (idx in relationships) { - const relationshipFieldName = relationships[idx].relationshipFieldName; - const ownerSide = relationships[idx].ownerSide || false; - const relationshipFieldNamePlural = relationships[idx].relationshipFieldNamePlural; - const relationshipType = relationships[idx].relationshipType; - const otherEntityNameCapitalized = relationships[idx].otherEntityNameCapitalized; - const relationshipNameCapitalized = relationships[idx].relationshipNameCapitalized; - const otherEntityName = relationships[idx].otherEntityName; - const otherEntityNamePlural = relationships[idx].otherEntityNamePlural; - const otherEntityRelationshipName = relationships[idx].otherEntityRelationshipName; - const otherEntityRelationshipNamePlural = relationships[idx].otherEntityRelationshipNamePlural; - const otherEntityRelationshipNameCapitalized = relationships[idx].otherEntityRelationshipNameCapitalized; - const otherEntityRelationshipNameCapitalizedPlural = relationships[idx].otherEntityRelationshipNameCapitalizedPlural; - const otherEntityIsEmbedded = relationships[idx].otherEntityIsEmbedded; + for (relationship of relationships) { + const relationshipFieldName = relationship.relationshipFieldName; + const relationshipFieldNamePlural = relationship.relationshipFieldNamePlural; + const relationshipType = relationship.relationshipType; + const otherEntityNameCapitalized = relationship.otherEntityNameCapitalized; + const relationshipNameCapitalized = relationship.relationshipNameCapitalized; + const relationshipNameCapitalizedPlural = relationship.relationshipNameCapitalizedPlural; + const otherEntityName = relationship.otherEntityName; + const otherEntityNamePlural = relationship.otherEntityNamePlural; + const otherEntityRelationshipNameCapitalized = relationship.otherEntityRelationshipNameCapitalized; + const otherEntityRelationshipNameCapitalizedPlural = relationship.otherEntityRelationshipNameCapitalizedPlural; + const otherEntityRelationshipNamePlural = relationship.otherEntityRelationshipNamePlural; + const otherEntityIsEmbedded = relationship.otherEntityIsEmbedded; + const otherEntityRelationshipName = relationship.otherEntityRelationshipName; + const ownerSide = relationship.ownerSide || false; // An embedded entity should not reference entities that embeds it, unless the other entity is also embedded if (embedded && !otherEntityIsEmbedded && ownerSide === false) { continue; } + + const id = relationship.id; + const reactiveRelationshipWithId = (databaseType === 'sql' && reactive && !(relationshipType === 'one-to-one' && + (ownerSide === false || (ownerSide === true && id === true)))); _%> <%_ if (relationshipType === 'one-to-many' || relationshipType === 'many-to-many') { _%> <%_ if (fluentMethods) { _%> - fun add<%= relationshipNameCapitalized %>(<%= otherEntityName %>: <%= asEntity(otherEntityNameCapitalized) %>): <%= asEntity(entityClass) %> { - this.<%= relationshipFieldNamePlural %>.add(<%= otherEntityName %>) + fun add<%= relationshipNameCapitalized %>(<%= otherEntityName %>: <%= asEntity(otherEntityNameCapitalized) %>): <%= persistClass %> { + if (this.<%= relationshipFieldNamePlural %> == null) { + this.<%= relationshipFieldNamePlural %> = mutableSetOf() + } + this.<%= relationshipFieldNamePlural %>?.add(<%= otherEntityName %>) <%_ if (!otherEntityIsEmbedded || embedded && ownerSide === true) { _%> <%_ if (databaseType === 'couchbase' && !otherEntityIsEmbedded) { _%> - <%= otherEntityName %>.id?.let { this.<%= relationshipFieldName %>Ids.add(it) } + <%= otherEntityName %>.<%= primaryKey.name %>?.let { this.<%= relationshipFieldName %>Ids.add(it) } <%_ } _%> - <%_ if (relationshipType === 'one-to-many') { _%> + <%_ if (relationship.otherRelationship) { + if (relationshipType === 'one-to-many') { + if (databaseType !== 'neo4j') { _%> <%= otherEntityName %>.<%= otherEntityRelationshipName %> = this - <%_ } else if (otherEntityRelationshipNamePlural !== '' && ownerSide === false && - otherEntityNameCapitalized !== 'User' && relationshipType === 'many-to-many') { + <%_ } _%> + <%_ } else if (otherEntityRelationshipNameCapitalizedPlural && asEntity(otherEntityNameCapitalized)!=='User' && relationshipType === 'many-to-many') { // JHipster version < 3.6.0 didn't ask for this relationship name _%> - <%= otherEntityName %>.<%= otherEntityRelationshipNamePlural %>.add(this) + <%= otherEntityName %>.<%= otherEntityRelationshipNamePlural %>?.add(this) + <%_ } _%> <%_ } _%> <%_ } _%> return this } - fun remove<%= relationshipNameCapitalized %>(<%= otherEntityName %>: <%= asEntity(otherEntityNameCapitalized) %>): <%= asEntity(entityClass) %> { - this.<%= relationshipFieldNamePlural %>.remove(<%= otherEntityName %>) - <%_ if (!otherEntityIsEmbedded || embedded && ownerSide === true) { _%> + fun remove<%= relationshipNameCapitalized %>(<%= otherEntityName %>: <%= asEntity(otherEntityNameCapitalized) %>): <%= persistClass %> { + this.<%= relationshipFieldNamePlural %>?.remove(<%= otherEntityName %>) + <%_ if (!otherEntityIsEmbedded || (embedded && ownerSide === true)) { _%> <%_ if (databaseType === 'couchbase' && !otherEntityIsEmbedded) { _%> - <%= otherEntityName %>.id?.let { this.<%= relationshipFieldName %>Ids.remove(it) } + <%= otherEntityName %>.<%= primaryKey.name %>?.let { this.<%= relationshipFieldName %>Ids.remove(it) } <%_ } _%> - <%_ if (relationshipType === 'one-to-many') { _%> + <%_ if (relationship.otherRelationship) { + if (relationshipType === 'one-to-many') { + if (databaseType !== 'neo4j') { _%> <%= otherEntityName %>.<%= otherEntityRelationshipName %> = null + <%_ } _%> <%_ } else if (otherEntityRelationshipNamePlural !== '' && ownerSide === false && otherEntityNameCapitalized !== 'User' && relationshipType === 'many-to-many') { // JHipster version < 3.6.0 didn't ask for this relationship name _%> - <%= otherEntityName %>.<%= otherEntityRelationshipNamePlural %>.remove(this) + <%= otherEntityName %>.<%= otherEntityRelationshipNamePlural %>?.remove(this) + <%_ } _%> <%_ } _%> <%_ } _%> return this @@ -468,10 +630,10 @@ for (idx in fields) { override fun equals(other: Any?): Boolean { if (this === other) return true - if (other !is <%= asEntity(entityClass) %>) return false + if (other !is <%= persistClass %>) return false <%_ if (!embedded) { _%> - return id != null && other.id != null && id == other.id + return <%= primaryKey.name %> != null && other.<%= primaryKey.name %> != null && <%= primaryKey.name %> == other.<%= primaryKey.name %> <%_ } else { _%> return false; <%_ } _%> @@ -479,38 +641,36 @@ for (idx in fields) { override fun hashCode() = 31 - override fun toString() = "<%= asEntity(entityClass) %>{" + + override fun toString() = "<%= persistClass %>{" + <%_ if (!embedded) { _%> - "id=$id" + + "<%= primaryKey.name %>=$<%= primaryKey.name %>" + <%_ } _%> - <%_ for (idx in fields) { - const fieldType = fields[idx].fieldType; - const fieldTypeBlobContent = fields[idx].fieldTypeBlobContent; - const fieldName = fields[idx].fieldName; - const fieldInJavaBeanMethod = fields[idx].fieldInJavaBeanMethod; - const isNumeric = ['integer', 'long', 'float', 'double', 'bigdecimal'].includes(fieldType.toLowerCase());_%> - ", <%= fieldName %>=<% if (! isNumeric) { %>'<% } %>$<%= fieldName %><% if (! isNumeric) { %>'<% } %>" + - <%_ if ((fieldType === 'byte[]' || fieldType === 'ByteBuffer') && fieldTypeBlobContent !== 'text') { _%> - ", <%= fieldName %>ContentType='$<%= fieldName %>ContentType'" + + <%_ for (field of fields.filter(field => !field.id && !field.transient)) { + const fieldType = field.fieldType; + const fieldTypeBlobContent = field.fieldTypeBlobContent; + const fieldName = field.fieldName; + const fieldInJavaBeanMethod = field.fieldInJavaBeanMethod; + const isNumeric = ['integer', 'long', 'float', 'double', 'bigdecimal'].includes(fieldType.toLowerCase()); _%> + ", <%= fieldName %>=<% if (! isNumeric) { %>'<% } %>$<%= fieldName %><% if (! isNumeric) { %>'<% } %>" + + <%_ if (field.fieldWithContentType) { _%> + ", <%= fieldName %>ContentType='$<%= fieldName %>ContentType'" + + <%_ } _%> <%_ } _%> - <%_ } _%> - <%_ for (idx in relationships) { - const relationshipType = relationships[idx].relationshipType; - const otherEntityIsEmbedded = relationships[idx].otherEntityIsEmbedded; - const relationshipFieldName = relationships[idx].relationshipFieldName; - const relationshipNameCapitalized = relationships[idx].relationshipNameCapitalized; - const relationshipFieldNamePlural = relationships[idx].relationshipFieldNamePlural; - const relationshipNameCapitalizedPlural = relationships[idx].relationshipNameCapitalizedPlural; - const ownerSide = relationships[idx].ownerSide; _%> - <%_ if (otherEntityIsEmbedded) { - if (relationshipType === 'many-to-one') { _%> - ", <%= relationshipFieldNamePlural %>='$<%= relationshipFieldNamePlural %>'" + - <%_ } else if (relationshipType === 'one-to-one' && ownerSide === true) { - _%> - ", <%= relationshipFieldName %>='$<%= relationshipFieldName %>'" + - <%_ } } } _%> - "}" - + <%_ for (relationship of relationships) { + const relationshipType = relationship.relationshipType; + const otherEntityIsEmbedded = relationship.otherEntityIsEmbedded; + const relationshipFieldName = relationship.relationshipFieldName; + const relationshipNameCapitalized = relationship.relationshipNameCapitalized; + const relationshipFieldNamePlural = relationship.relationshipFieldNamePlural; + const relationshipNameCapitalizedPlural = relationship.relationshipNameCapitalizedPlural; + const ownerSide = relationship.ownerSide; _%> + <%_ if (otherEntityIsEmbedded) { + if (relationshipType === 'many-to-one') { _%> + ", <%= relationshipFieldNamePlural %>='$<%= relationshipFieldNamePlural %>'" + + <%_ } else if (relationshipType === 'one-to-one' && ownerSide === true) { _%> + ", <%= relationshipFieldName %>='$<%= relationshipFieldName %>'" + + <%_ } } } _%> + "}" companion object { private const val serialVersionUID = 1L diff --git a/generators/entity-server/templates/src/main/kotlin/package/domain/relationship_validators.ejs b/generators/entity-server/templates/src/main/kotlin/package/domain/relationship_validators.ejs index e1fd6cd27..43f1f5cc1 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/domain/relationship_validators.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/domain/relationship_validators.ejs @@ -18,7 +18,6 @@ -%> <%# Returns a string of all validator annotations for the entity relationships. -%> <% -const relationship = relationships[idx]; let result = ''; if (relationship.relationshipValidate === true) { const validators = []; diff --git a/generators/entity-server/templates/src/main/kotlin/package/repository/EntityReactiveRepository.kt.ejs b/generators/entity-server/templates/src/main/kotlin/package/repository/EntityReactiveRepository.kt.ejs deleted file mode 100644 index 02c607294..000000000 --- a/generators/entity-server/templates/src/main/kotlin/package/repository/EntityReactiveRepository.kt.ejs +++ /dev/null @@ -1,92 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.repository - -import <%= packageName %>.domain.<%= asEntity(entityClass) %> -<%_ if (databaseType === 'cassandra') { _%> -import org.springframework.data.cassandra.repository.ReactiveCassandraRepository -<%_ } _%> -<%_ if (searchEngine === 'couchbase') { _%> -import <%= packageName %>.repository.search.SearchCouchbaseRepository -<%_ } _%> -<%_ if (databaseType === 'couchbase') { _%> -import org.springframework.data.couchbase.core.query.Query -import org.springframework.data.couchbase.repository.ReactiveCouchbaseSortingRepository -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import org.neo4j.springframework.data.repository.ReactiveNeo4jRepository -import org.neo4j.springframework.data.repository.query.Query -<%_ } _%> -<%_ if (pagination !== 'no' || fieldsContainOwnerManyToMany === true) { _%> -import org.springframework.data.domain.Pageable -<%_ } _%> -<%_ if (databaseType === 'mongodb') { _%> - <%_ if (fieldsContainOwnerManyToMany === true) { _%> -import org.springframework.data.mongodb.repository.Query - <%_ } _%> -import org.springframework.data.mongodb.repository.ReactiveMongoRepository -<%_ } _%> -import org.springframework.stereotype.Repository -<%_ if (databaseType === 'couchbase' || pagination !== 'no' || fieldsContainOwnerManyToMany === true) { _%> -import reactor.core.publisher.Flux -<%_ } _%> -<%_ if (fieldsContainOwnerManyToMany === true) { _%> -import reactor.core.publisher.Mono -<%_ } _%> -<%_ if (databaseType === 'cassandra') { _%> - -import java.util.UUID -<%_ } _%> - - /** - * Spring Data <% if (databaseType === 'mongodb') { %>MongoDB<% } if (databaseType === 'couchbase') { %>Couchbase<% } if (databaseType === 'cassandra') { %>Cassandra<% } if (databaseType === 'neo4j') { %>Neo4j<% } %> reactive repository for the <%= asEntity(entityClass) %> entity. - */ -@SuppressWarnings("unused") -@Repository -interface <%= entityClass %>Repository: Reactive<% if (databaseType === 'mongodb') { %>Mongo<% } if (databaseType === 'couchbase') { %>N1qlCouchbase<% } if (databaseType === 'neo4j') { %>Neo4j<% } if (databaseType === 'cassandra') { %>Cassandra<% } %>Repository<<%= asEntity(entityClass) %>, <%= primaryKeyType %>><% if (searchEngine === 'couchbase') { %>, SearchCouchbaseRepository<<%= asEntity(entityClass) %>, <%= primaryKeyType %>><% } %> { - - <%_ if (pagination !== 'no') { _%> - - fun findAllBy(pageable: Pageable): Flux<<%= asEntity(entityClass) %>> - <%_ } _%> - <%_ if (fieldsContainOwnerManyToMany === true) { _%> - <%_ if (databaseType === 'mongodb' || databaseType === 'couchbase') { _%> - - @Query("<%= (databaseType === 'mongodb') ? '{}' : '#{#n1ql.selectEntity} WHERE #{#n1ql.filter}' %>") - fun findAllWithEagerRelationships(pageable: Pageable): Flux<<%= asEntity(entityClass) %>> - - @Query("<%= (databaseType === 'mongodb') ? '{}' : '#{#n1ql.selectEntity} WHERE #{#n1ql.filter}' %>") - fun findAllWithEagerRelationships(): Flux<<%= asEntity(entityClass) %>> - - @Query("<%- (databaseType === 'mongodb') ? "{'id': ?0}" : "#{#n1ql.selectEntity} USE KEYS $1 WHERE #{#n1ql.filter}" %>") - fun findOneWithEagerRelationships(id: <%= primaryKeyType %>): Mono<<%= asEntity(entityClass) %>> - <%_ } _%> - <%_ if (databaseType === 'neo4j') { _%> - @Query("MATCH (n:<%= asEntity(entityClass) %>)<-[]-(m) RETURN n,m") - fun findAllWithEagerRelationships(pageable: Pageable): Flux<<%= asEntity(entityClass) %>> - - @Query("MATCH (n:<%= asEntity(entityClass) %>)<-[]-(m) RETURN n,m") - fun findAllWithEagerRelationships(): Flux<<%= asEntity(entityClass) %>> - - @Query("MATCH (e:<%= asEntity(entityClass) %> {id: $id}) RETURN e") - fun findOneWithEagerRelationships(<%= primaryKeyType %> id): Mono<<%= asEntity(entityClass) %>> - <%_ } _%> - <%_ } _%> - - } \ No newline at end of file diff --git a/generators/entity-server/templates/src/main/kotlin/package/repository/EntityRepository.kt.ejs b/generators/entity-server/templates/src/main/kotlin/package/repository/EntityRepository.kt.ejs index fa08e5f69..af6b144e2 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/repository/EntityRepository.kt.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/repository/EntityRepository.kt.ejs @@ -18,8 +18,8 @@ -%> package <%= packageName %>.repository -import <%= packageName %>.domain.<%= asEntity(entityClass) %> -<%_ if (fieldsContainOwnerManyToMany) { _%> +import <%= packageName %>.domain.<%= persistClass %> +<%_ if (relationshipsContainEagerLoad) { _%> import org.springframework.data.domain.Page import org.springframework.data.domain.Pageable <%_ } _%> @@ -29,7 +29,7 @@ import org.springframework.data.jpa.repository.JpaRepository import org.springframework.data.jpa.repository.JpaSpecificationExecutor <%_ } _%> import org.springframework.data.jpa.repository.Query - <%_ if (fieldsContainOwnerManyToMany) { _%> + <%_ if (relationshipsContainEagerLoad) { _%> import org.springframework.data.repository.query.Param <%_ } _%> <%_ } _%> @@ -38,13 +38,12 @@ import org.springframework.data.mongodb.repository.Query import org.springframework.data.mongodb.repository.MongoRepository <%_ } _%> <%_ if (databaseType === 'neo4j') { _%> -import org.neo4j.springframework.data.repository.Neo4jRepository -import org.neo4j.springframework.data.repository.query.Query +import org.springframework.data.neo4j.repository.Neo4jRepository <%_ } _%> <%_ if (searchEngine === 'couchbase') { _%> import <%= packageName %>.repository.search.SearchCouchbaseRepository <%_ } _%> -<%_ if (databaseType === 'couchbase' && fieldsContainOwnerManyToMany === true) { _%> +<%_ if (databaseType === 'couchbase' && relationshipsContainEagerLoad) { _%> import org.springframework.data.couchbase.core.query.Query <%_ } _%> <%_ if (databaseType === 'cassandra') { _%> @@ -52,7 +51,7 @@ import org.springframework.data.cassandra.repository.CassandraRepository <%_ } _%> import org.springframework.stereotype.Repository <%_ -if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') { +if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'couchbase') { let importList = fieldsContainOwnerManyToMany; for (r of relationships) { if (r.relationshipType === 'many-to-one' && r.otherEntityName === 'user') { @@ -60,62 +59,55 @@ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'ne } } _%> - <%_ if (fieldsContainOwnerManyToMany) { _%> + <%_ if (relationshipsContainEagerLoad) { _%> import java.util.Optional <%_ } _%> <%_ } _%> -<%_ if (databaseType === 'cassandra') { _%> +<%_ if (primaryKey.type === 'UUID') { _%> import java.util.UUID <%_ } _%> /** - * Spring Data <% if (databaseType === 'mongodb') { %>MongoDB<% } if (databaseType === 'neo4j') { %>Neo4j<% } if (databaseType === 'couchbase') { %>Couchbase<% } if (databaseType === 'cassandra') { %>Cassandra<% } %> repository for the [<%= asEntity(entityClass) %>] entity. + * Spring Data <%= officialDatabaseType %> repository for the [<%= persistClass %>] entity. */ -<%_ if (!fieldsContainOwnerManyToMany) { _%> +<%_ if (!relationshipsContainEagerLoad) { _%> @Suppress("unused") <%_ } _%> @Repository -interface <%=entityClass%>Repository : <% if (databaseType === 'sql') { %>JpaRepository<% } %><% if (databaseType === 'mongodb') { %>MongoRepository<% } %><% if (databaseType === 'neo4j') { %>Neo4jRepository<% } %><% if (databaseType === 'cassandra') { %>CassandraRepository<% } %><% if (databaseType === 'couchbase') { %>N1qlCouchbaseRepository<% } %><<%=asEntity(entityClass)%>, <%= primaryKeyType %>><% if (jpaMetamodelFiltering) { %>, JpaSpecificationExecutor<<%= asEntity(entityClass) %>><% } %><% if (searchEngine === 'couchbase') { %>, SearchCouchbaseRepository<<%= asEntity(entityClass) %>, <%= primaryKeyType %>><% } %> { - <%_ for (idx in relationships) { - if (relationships[idx].relationshipType === 'many-to-one' && relationships[idx].otherEntityName === 'user' && databaseType === 'sql') { _%> +interface <%=entityClass%>Repository : <% if (databaseType === 'sql') { %>JpaRepository<% } %><% if (databaseType === 'mongodb') { %>MongoRepository<% } %><% if (databaseType === 'neo4j') { %>Neo4jRepository<% } %><% if (databaseType === 'cassandra') { %>CassandraRepository<% } %><% if (databaseType === 'couchbase') { %>N1qlCouchbaseRepository<% } %><<%=persistClass%>, <%= primaryKey.type %>><% if (jpaMetamodelFiltering) { %>, JpaSpecificationExecutor<<%= persistClass %>><% } %><% if (searchEngine === 'couchbase') { %>, SearchCouchbaseRepository<<%= persistClass %>, <%= primaryKey.type %>><% } %> { + <%_ for (const relationship of relationships) { + if (relationship.relationshipType === 'many-to-one' && relationship.otherEntityName === 'user' && databaseType === 'sql') { _%> - @Query("select <%= entityInstance %> from <%= asEntity(entityClass) %> <%= entityInstance %> where <%= entityInstance %>.<%= relationships[idx].relationshipFieldName %>.login = ?#{principal.<% if (authenticationType === 'oauth2') { %>preferredUsername<% } else { %>username<% } %>}") - fun findBy<%= relationships[idx].relationshipNameCapitalized %>IsCurrentUser(): MutableList<<%= asEntity(entityClass) %>> + @Query("select <%= entityInstance %> from <%= persistClass %> <%= entityInstance %> where <%= entityInstance %>.<%= relationship.relationshipFieldName %>.login = ?#{principal.<% if (authenticationType === 'oauth2') { %>preferredUsername<% } else { %>username<% } %>}") + fun findBy<%= relationship.relationshipNameCapitalized %>IsCurrentUser(): MutableList<<%= persistClass %>> <%_ } } _%> - <%_ if (fieldsContainOwnerManyToMany === true) { + <%_ if (relationshipsContainEagerLoad) { if (databaseType === 'sql') { _%> - @Query(value = "select distinct <%= entityInstance %> from <%= asEntity(entityClass) %> <%= entityInstance %><% for (idx in relationships) { - if (relationships[idx].relationshipType === 'many-to-many' && relationships[idx].ownerSide === true) { %> left join fetch <%= entityInstance %>.<%= relationships[idx].relationshipFieldNamePlural %><% } } %>", - countQuery = "select count(distinct <%= entityInstance %>) from <%= asEntity(entityClass) %> <%= entityInstance %>") - fun findAllWithEagerRelationships(pageable: Pageable): Page<<%= asEntity(entityClass) %>> + @Query(value = "select distinct <%= entityInstance %> from <%= persistClass %> <%= entityInstance %><% for (const relationship of relationships) { + if (relationship.relationshipEagerLoad) { %> left join fetch <%= entityInstance %>.<%= relationship.reference.name %><% } } %>", + countQuery = "select count(distinct <%= entityInstance %>) from <%= persistClass %> <%= entityInstance %>") + fun findAllWithEagerRelationships(pageable: Pageable): Page<<%= persistClass %>> - @Query("select distinct <%= entityInstance %> from <%= asEntity(entityClass) %> <%= entityInstance %><% for (idx in relationships) { - if (relationships[idx].relationshipType === 'many-to-many' && relationships[idx].ownerSide === true) { %> left join fetch <%= entityInstance %>.<%= relationships[idx].relationshipFieldNamePlural %><% } } %>") - fun findAllWithEagerRelationships(): MutableList<<%= asEntity(entityClass) %>> + @Query("select distinct <%= entityInstance %> from <%= persistClass %> <%= entityInstance %><% for (const relationship of relationships) { + if (relationship.relationshipEagerLoad) { %> left join fetch <%= entityInstance %>.<%= relationship.reference.name %><% } } %>") + fun findAllWithEagerRelationships(): MutableList<<%= persistClass %>> - @Query("select <%= entityInstance %> from <%= asEntity(entityClass) %> <%= entityInstance %><% for (idx in relationships) { - if (relationships[idx].relationshipType === 'many-to-many' && relationships[idx].ownerSide === true) { %> left join fetch <%= entityInstance %>.<%= relationships[idx].relationshipFieldNamePlural %><% } } %> where <%= entityInstance %>.id =:id") - fun findOneWithEagerRelationships(@Param("id") id: <%= primaryKeyType %>): Optional<<%= asEntity(entityClass) %>> + @Query("select <%= entityInstance %> from <%= persistClass %> <%= entityInstance %><% for (const relationship of relationships) { + if (relationship.relationshipEagerLoad) { %> left join fetch <%= entityInstance %>.<%= relationship.reference.name %><% } } %> where <%= entityInstance %>.id =:id") + fun findOneWithEagerRelationships(@Param("id") id: <%= primaryKey.type %>): Optional<<%= persistClass %>> <%_ } else if (databaseType === 'mongodb' || databaseType === 'couchbase') { _%> @Query("<%= (databaseType === 'mongodb')?'{}':'#{#n1ql.selectEntity} WHERE #{#n1ql.filter}'%>") - fun findAllWithEagerRelationships(pageable: Pageable): Page<<%= asEntity(entityClass) %>> + fun findAllWithEagerRelationships(pageable: Pageable): Page<<%= persistClass %>> @Query("<%= (databaseType === 'mongodb')?'{}':'#{#n1ql.selectEntity} WHERE #{#n1ql.filter}'%>") - fun findAllWithEagerRelationships(): MutableList<<%= asEntity(entityClass) %>> + fun findAllWithEagerRelationships(): MutableList<<%= persistClass %>> @Query("<%- (databaseType === 'mongodb')?"{'id': ?0}":"#{#n1ql.selectEntity} USE KEYS $1 WHERE #{#n1ql.filter}"%>") - fun findOneWithEagerRelationships(id: <%= primaryKeyType %>): Optional<<%= asEntity(entityClass) %>> - <%_ } else if (databaseType === 'neo4j') { _%> - - @Query("MATCH (n:<%= asEntity(entityClass) %>)<-[]-(m) RETURN n,m") - fun findAllWithEagerRelationships(pageable: Pageable): Page<<%= asEntity(entityClass) %>> - - @Query("MATCH (e:<%= asEntity(entityClass) %> {id: $id}) RETURN e") - fun findOneWithEagerRelationships(id: <%= primaryKeyType %>): Optional<<%= asEntity(entityClass) %>> - <%_ } + fun findOneWithEagerRelationships(id: <%= primaryKey.type %>): Optional<<%= persistClass %>> + <%_ } } _%> } diff --git a/generators/entity-server/templates/src/main/kotlin/package/repository/EntityRepositoryInternalImpl_reactive.kt.ejs b/generators/entity-server/templates/src/main/kotlin/package/repository/EntityRepositoryInternalImpl_reactive.kt.ejs new file mode 100644 index 000000000..fa772fec2 --- /dev/null +++ b/generators/entity-server/templates/src/main/kotlin/package/repository/EntityRepositoryInternalImpl_reactive.kt.ejs @@ -0,0 +1,254 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + + This file is part of the JHipster project, see https://www.jhipster.tech/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %>.repository + +import java.util.function.BiFunction +<%_ if (fieldsContainBigDecimal === true) { _%> +import java.math.BigDecimal +<%_} if (fieldsContainInstant === true) { _%> +import java.time.Instant +<%_ } if (fieldsContainLocalDate === true) { _%> +import java.time.LocalDate +<%_ } if (fieldsContainZonedDateTime === true) { _%> +import java.time.ZonedDateTime +<%_ } if (fieldsContainDuration === true) { _%> +import java.time.Duration +<%_ } if (fieldsContainUUID === true) { _%> +import java.util.UUID +<%_ } _%> +import java.util.ArrayList +import java.util.List +import java.util.Map +import java.util.Map.Entry +import java.util.Optional + +import org.springframework.data.domain.Pageable +<%_ if (databaseType === 'sql') { _%> +import io.r2dbc.spi.Row +import io.r2dbc.spi.RowMetadata + +import org.springframework.data.relational.core.query.Criteria.where +import org.springframework.data.relational.core.query.Query.query + +import org.springframework.data.r2dbc.core.R2dbcEntityTemplate +import org.springframework.data.relational.core.query.Criteria +import org.springframework.data.relational.core.sql.Column +import org.springframework.data.relational.core.sql.Expression +import org.springframework.data.relational.core.sql.Select +import org.springframework.data.relational.core.sql.SelectBuilder.SelectFromAndJoin<% if (reactiveEagerRelations.length > 0) { %>Condition<% } %> +import org.springframework.data.relational.core.sql.Table +import org.springframework.r2dbc.core.DatabaseClient +import org.springframework.r2dbc.core.RowsFetchSpec +<%_ } _%> + +import <%= packageName %>.domain.<%= persistClass %> +<% relationships.forEach(function(rel) { + if (rel.relationshipType === 'many-to-many' && rel.ownerSide) { _%> +import <%= packageName %>.domain.<%= asEntity(rel.otherEntityNameCapitalized) %> + <%_ } _%> +<%_ } ); _%> +<%_ Object.keys(uniqueEnums).forEach(function(element) { _%> + +import <%= packageName %>.domain.enumeration.<%= element %> +<%_ }); _%> + +<%_ reactiveUniqueEntityTypes.forEach(function(element) { _%> +import <%= packageName %>.repository.rowmapper.<%= element %>RowMapper +<%_ }); _%> +import <%= packageName %>.service.EntityManager +<%_ if (fieldsContainOwnerManyToMany) { _%> +import <%= packageName %>.service.EntityManager.LinkTable +<%_ } _%> + +import reactor.core.publisher.Flux +import reactor.core.publisher.Mono + +/** + * Spring Data <%= officialDatabaseType %> reactive custom repository implementation for the <%= persistClass %> entity. + */ +@SuppressWarnings("unused") +class <%= entityClass %>RepositoryInternalImpl( + val db: DatabaseClient, + val r2dbcEntityTemplate: R2dbcEntityTemplate, + val entityManager: EntityManager <% reactiveUniqueEntityTypes.forEach(function(element) { %>, + val <%= element.toLowerCase() %>Mapper: <%= element %>RowMapper + <%_ }); _%> +): <%= entityClass %>RepositoryInternal { + + companion object { + private val entityTable = Table.aliased("<%= entityTableName %>", EntityManager.ENTITY_ALIAS) + <%_ reactiveEagerRelations.forEach(function(rel) { _%> + private val <%= rel.relationshipName %>Table = Table.aliased("<%= rel.otherEntityTableName %>", "<%= _generateSqlSafeName(rel.relationshipName) %>") + <%_ }); _%> + <%_ relationships.forEach(function(rel) { + if (rel.relationshipType === 'many-to-many' && rel.ownerSide) { + const joinTableName = getJoinTableName(entityTableName, rel.relationshipName, prodDatabaseType); + _%> + private val <%= rel.relationshipName %>Link = LinkTable("<%= joinTableName %>", "<%= getColumnName(name) %>_id", "<%= getColumnName(rel.relationshipName) %>_id") + <%_ } + }); _%> + + } + + override fun findAllBy(pageable: Pageable): Flux<<%= persistClass %>> { + return createQuery(pageable, null).all() + } + + override fun findAllBy(pageable: Pageable, criteria: Criteria): Flux<<%= persistClass %>> { + return createQuery(pageable, criteria).all() + } + + fun createQuery(pageable: Pageable?, criteria: Criteria?): RowsFetchSpec<<%= persistClass %>> { + val columns = <%= persistClass %>SqlHelper().getColumns(entityTable, EntityManager.ENTITY_ALIAS) + <%_ reactiveEagerRelations.forEach(function(rel) { _%> + columns.addAll(<%= rel.otherEntityNameCapitalized %>SqlHelper().getColumns(<%= rel.relationshipName %>Table, "<%= rel.relationshipName %>")) + <%_ }); _%> + val selectFrom = Select.builder().select(columns).from(entityTable)<%_ reactiveEagerRelations.forEach(function(rel) { + const colName = _getJoinColumnName(rel); %> + .leftOuterJoin(<%= rel.relationshipName %>Table).on(Column.create("<%= colName %>", entityTable)).equals(Column.create("id", <%= rel.relationshipName %>Table ))<%_ }); _%> + + val select = entityManager.createSelect(selectFrom, <%= persistClass %>::class.java, pageable, criteria) + + <%_ if (databaseType === 'sql') { _%> + val alias = entityTable.referenceName.reference + val selectWhere = + Optional.ofNullable(criteria).map { + StringBuilder(select).append(" ").append("WHERE").append(" ").append(alias).append(".").append(it.toString()).toString()}.orElse(select) // TODO remove once https://github.com/spring-projects/spring-data-jdbc/issues/907 will be fixed + <%_ } _%> + return db.sql(select<% if (databaseType === 'sql') { %>Where<% } %>) + .map(this::process) + } + + override fun findAll(): Flux<<%= persistClass %>> { + return createQuery(null, null).all() + } + + override fun findById(id: <%= primaryKey.type %>): Mono<<%= persistClass %>> { + return createQuery(null, Criteria.where("id").`is`(id)).one(); + } + + <%_ if (fieldsContainOwnerManyToMany) { _%> + + override fun findOneWithEagerRelationships(id: Long): Mono<<%= persistClass %>> { + return findById(id); + } + + override fun findAllWithEagerRelationships(): Flux<<%= persistClass %>> { + return findAll(); + } + + override fun findAllWithEagerRelationships(page: Pageable): Flux<<%= persistClass %>> { + return findAllBy(page); + } + + <%_ } _%> + private fun process(row: Row, metadata: RowMetadata): <%= persistClass %> { + val entity = <%= entityClass.toLowerCase() %>Mapper.apply(row, "e") + <%_ reactiveEagerRelations.forEach(function(rel) { _%> + entity.<%= rel.relationshipName %> = <%= rel.otherEntityNameCapitalized.toLowerCase() %>Mapper.apply(row, "<%= rel.relationshipName %>") + <%_ }); _%> + return entity + } + + override fun > insert(entity: S): Mono { + return entityManager.insert(entity); + } + + override fun > save(entity: S): Mono { + if (entity.<%= primaryKey.name %> == null) { + <%_ if (isUsingMapsId) { _%> + entity.<%= primaryKey.name %> = entity.<%= mapsIdAssoc.relationshipName %>?.<%= primaryKey.name %> + <%_ } _%> + return insert(entity)<% if (fieldsContainOwnerManyToMany) { %>.flatMap{ updateRelations(it) }<% } %> + } else { + return update(entity).map { + if (it.toInt() <= 0) { + throw IllegalStateException("Unable to update <%= entityClass %> with id = " + entity.<%= primaryKey.name %>) + } + entity + }<% if (fieldsContainOwnerManyToMany) { %>.then(updateRelations(entity))<% } %>; + } + } + + override fun update(entity: <%= persistClass %>): Mono { + <%_ if (fields.length + reactiveEagerRelations.length > 0) { _%> + //fixme is this the proper way? + return r2dbcEntityTemplate.update(entity).thenReturn(Integer.valueOf(1) as Integer) + <%_ } else { _%> + // What can we update on this field? + return Mono.just(1).map{ it as Integer } + <%_ } _%> + } + + <%_ if (fieldsContainOwnerManyToMany) { _%> + + override fun deleteById(entityId: Long): Mono { + return deleteRelations(entityId).then( + r2dbcEntityTemplate.delete(<%= asEntity(entityClass) %>::class.java).matching(query(Criteria.where("id").`is`(entityId))).all().then() + ); + } + + protected fun > updateRelations(entity: S): Mono { + <%_ relationships.filter(function(rel) { + return (rel.relationshipType === 'many-to-many' && rel.ownerSide) + }).forEach(function(rel, idx) { + if (idx === 0) { _%> + val result = entityManager.updateLinkTable(<%= rel.relationshipName %>Link, entity.<%= primaryKey.name %>, entity.<%= rel.relationshipNamePlural %>?.map { it.id }).then() + <%_ } else { _%> + result = result.and(entityManager.updateLinkTable(<%= rel.relationshipName %>Link, entity.<%= primaryKey.name %>, entity.<%= rel.relationshipNamePlural %>?.map { it.id }) + <%_ + } + }); _%> + return result.thenReturn(entity) + } + + protected fun deleteRelations(entityId: Long): Mono { + <%_ relationships.filter(function(rel) { + return (rel.relationshipType === 'many-to-many' && rel.ownerSide); + }).forEach(function(rel, idx) { + if (idx === 0) { _%> + return entityManager.deleteFromLinkTable(<%= rel.relationshipName %>Link, entityId)<% + } else { %> + .and(entityManager.deleteFromLinkTable(<%= rel.relationshipName %>Link, entityId))<% } + }); %>; + } + + <%_ } _%> +} + +class <%= entityClass %>SqlHelper { + fun getColumns(table: Table, columnPrefix: String): MutableList { + val columns = mutableListOf(); + columns.add(Column.aliased("id", table, columnPrefix + "_id")); +<%_ fields.forEach(function(field) { + let col = field.fieldNameAsDatabaseColumn; + _%> + columns.add(Column.aliased("<%= col %>", table, columnPrefix + "_<%= col %>")); + <%_ if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { _%> + columns.add(Column.aliased("<%= col %>_content_type", table, columnPrefix + "_<%= col %>_content_type")); + <%_ } _%> +<%_ }); _%> + +<%_ reactiveRegularEagerRelations.forEach(function(rel) { _%> + columns.add(Column.aliased("<%= getColumnName(rel.relationshipName) %>_id", table, columnPrefix + "_<%= getColumnName(rel.relationshipName) %>_id")); +<%_ }); _%> + return columns; + } + +} diff --git a/generators/entity-server/templates/src/main/kotlin/package/repository/EntityRepository_reactive.kt.ejs b/generators/entity-server/templates/src/main/kotlin/package/repository/EntityRepository_reactive.kt.ejs new file mode 100644 index 000000000..7f92344b1 --- /dev/null +++ b/generators/entity-server/templates/src/main/kotlin/package/repository/EntityRepository_reactive.kt.ejs @@ -0,0 +1,170 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + + This file is part of the JHipster project, see https://www.jhipster.tech/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %>.repository + +import <%= packageName %>.domain.<%= persistClass %> +<%_ if (databaseType === 'cassandra') { _%> +import org.springframework.data.cassandra.repository.ReactiveCassandraRepository +<%_ } _%> +<%_ if (searchEngine === 'couchbase') { _%> +import <%= packageName %>.repository.search.SearchCouchbaseRepository +<%_ } _%> +<%_ if (databaseType === 'couchbase') { _%> +import org.springframework.data.couchbase.core.query.Query +import org.springframework.data.couchbase.repository.ReactiveCouchbaseSortingRepository +<%_ } _%> +<%_ if (databaseType === 'neo4j') { _%> +import org.springframework.data.neo4j.repository.ReactiveNeo4jRepository +import org.springframework.data.neo4j.repository.query.Query +<%_ } _%> +<%_ if (pagination !== 'no' || relationshipsContainEagerLoad || databaseType === 'sql') { _%> +import org.springframework.data.domain.Pageable +<%_ } _%> +<%_ if (databaseType === 'sql') { _%> +import org.springframework.data.r2dbc.repository.Query +import org.springframework.data.r2dbc.repository.R2dbcRepository +import org.springframework.data.relational.core.query.Criteria +<%_ } _%> +<%_ if (databaseType === 'mongodb') { _%> + <%_ if (relationshipsContainEagerLoad) { _%> +import org.springframework.data.mongodb.repository.Query + <%_ } _%> +import org.springframework.data.mongodb.repository.ReactiveMongoRepository +<%_ } _%> +import org.springframework.stereotype.Repository +<%_ if (['couchbase', 'sql'].includes(databaseType) || pagination !== 'no' || relationshipsContainEagerLoad) { _%> +import reactor.core.publisher.Flux +<%_ } _%> +<%_ if (relationshipsContainEagerLoad || databaseType === 'sql') { _%> +import reactor.core.publisher.Mono +<%_ } _%> +<%_ if (databaseType === 'cassandra') { _%> + +import java.util.UUID +<%_ } _%> + + /** + * Spring Data <%= officialDatabaseType %> reactive repository for the <%= persistClass %> entity. + */ +@SuppressWarnings("unused") +@Repository +interface <%= entityClass %>Repository: <% if (databaseType === 'sql') { %>R2dbc<% } if (databaseType === 'mongodb') { %>ReactiveMongo<% } if (databaseType === 'couchbase') { %>ReactiveN1qlCouchbase<% } if (databaseType === 'neo4j') { %>ReactiveNeo4j<% } if (databaseType === 'cassandra') { %>ReactiveCassandra<% } %>Repository<<%= persistClass %>, <%= primaryKey.type %>><% if (searchEngine === 'couchbase') { %>, SearchCouchbaseRepository<<%= persistClass %>, <%= primaryKey.type %>><% } %><% if (databaseType === 'sql') { %>, <%= entityClass %>RepositoryInternal<% } %> { + + <%_ if (pagination !== 'no') { _%> + + <% if (databaseType === 'sql') { %>override <% } %>fun findAllBy(pageable: Pageable): Flux<<%= persistClass %>> + <%_ } _%> + <%_ if (relationshipsContainEagerLoad) { _%> + <%_ if (['couchbase', 'mongodb'].includes(databaseType)) { _%> + + @Query("<%= (databaseType === 'mongodb') ? '{}' : '#{#n1ql.selectEntity} WHERE #{#n1ql.filter}' %>") + fun findAllWithEagerRelationships(pageable: Pageable): Flux<<%= persistClass %>> + + @Query("<%= (databaseType === 'mongodb') ? '{}' : '#{#n1ql.selectEntity} WHERE #{#n1ql.filter}' %>") + fun findAllWithEagerRelationships(): Flux<<%= persistClass %>> + + @Query("<%- (databaseType === 'mongodb') ? "{'id': ?0}" : "#{#n1ql.selectEntity} USE KEYS $1 WHERE #{#n1ql.filter}" %>") + fun findOneWithEagerRelationships(id: <%= primaryKey.type %>): Mono<<%= persistClass %>> + <%_ } _%> + <%_ if (databaseType === 'neo4j') { _%> + @Query("MATCH (n:<%= persistClass %>)<-[]-(m) RETURN n,m") + fun findAllWithEagerRelationships(pageable: Pageable): Flux<<%= persistClass %>> + + @Query("MATCH (n:<%= persistClass %>)<-[]-(m) RETURN n,m") + fun findAllWithEagerRelationships(): Flux<<%= persistClass %>> + + @Query("MATCH (e:<%= persistClass %> {id: $id}) RETURN e") + fun findOneWithEagerRelationships(id: <%= primaryKey.type %>): Mono<<%= persistClass %>> + <%_ } _%> + <%_ } _%> + + <%_ if (databaseType === 'sql') { + if (fieldsContainOwnerManyToMany) { _%> + + override fun findOneWithEagerRelationships(id: <%= primaryKey.type %>): Mono<<%= persistClass %>> + + override fun findAllWithEagerRelationships(): Flux<<%= persistClass %>> + + override fun findAllWithEagerRelationships(page: Pageable): Flux<<%= persistClass %>> + + override fun deleteById(id: Long): Mono + + <%_ } _%> + + <%_ for (const relationship of relationships) { + let relationshipType = relationship.relationshipType; + let relationshipName = relationship.relationshipName; + let ownerSide = relationship.ownerSide; + if (relationshipType === 'many-to-one' || (relationshipType === 'one-to-one' && ownerSide === true)) { _%> + + @Query("SELECT * FROM <%= entityTableName %> entity WHERE entity.<%= getColumnName(relationshipName) %>_id = :id") + fun findBy<%= relationship.relationshipNameCapitalized %>(id: <%= primaryKey.type %>): Flux<<%= persistClass %>> + + @Query("SELECT * FROM <%= entityTableName %> entity WHERE entity.<%= getColumnName(relationshipName) %>_id IS NULL") + fun findAllWhere<%= relationship.relationshipNameCapitalized %>IsNull(): Flux<<%= persistClass %>> + <%_ } else if (relationshipType === 'many-to-many') { + const joinTableName = getJoinTableName(entityTableName, relationshipName, prodDatabaseType); + _%> + + @Query("SELECT entity.* FROM <%= entityTableName %> entity JOIN <%= joinTableName %> joinTable ON entity.id = joinTable.<%= getColumnName(name) %>_id WHERE joinTable.<%= getColumnName(relationshipName) %>_id = :id") + fun findBy<%= relationship.relationshipNameCapitalized %>(id: <%= primaryKey.type %>): Flux<<%= persistClass %>> + <%_ } else if (relationshipType === 'one-to-one' && ownerSide === false) { + let otherEntityRelationshipName = relationship.otherEntityRelationshipName; + let otherEntityTableName = relationship.otherEntityTableName; + _%> + + @Query("SELECT * FROM <%= entityTableName %> entity WHERE entity.id not in (select <%= getColumnName(otherEntityRelationshipName) %>_id from <%= otherEntityTableName %>)") + fun findAllWhere<%= relationship.relationshipNameCapitalized %>IsNull(): Flux<<%= persistClass %>> + <%_ } _%> + <%_ } _%> + + // just to avoid having unambigous methods + override fun findAll(): Flux<<%= persistClass %>> + + override fun findById(id: Long?): Mono<<%= persistClass %>> + + override fun > save(entity: S): Mono + + <%_ } _%> + +} + <%_ if (databaseType === 'sql') { _%> +interface <%= entityClass %>RepositoryInternal { + fun > insert (entity: S): Mono + fun > save(entity: S): Mono + fun update(entity: <%= persistClass %>): Mono + + fun findAll(): Flux<<%= persistClass %>> + fun findById(id: <%= primaryKey.type %>): Mono<<%= persistClass %>> + fun findAllBy(pageable: Pageable): Flux<<%= persistClass %>> + fun findAllBy(pageable: Pageable, criteria: Criteria): Flux<<%= persistClass %>> + + <%_ if (fieldsContainOwnerManyToMany) { _%> + + fun findOneWithEagerRelationships(id: <%= primaryKey.type %>): Mono<<%= persistClass %>> + + fun findAllWithEagerRelationships(): Flux<<%= persistClass %>> + + fun findAllWithEagerRelationships(page: Pageable): Flux<<%= persistClass %>> + + fun deleteById(id: Long): Mono + <%_ } _%> + +} +<%_ } _%> diff --git a/generators/entity-server/templates/src/main/kotlin/package/repository/rowmapper/EntityRowMapper.kt.ejs b/generators/entity-server/templates/src/main/kotlin/package/repository/rowmapper/EntityRowMapper.kt.ejs new file mode 100644 index 000000000..4f1368011 --- /dev/null +++ b/generators/entity-server/templates/src/main/kotlin/package/repository/rowmapper/EntityRowMapper.kt.ejs @@ -0,0 +1,78 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + + This file is part of the JHipster project, see https://www.jhipster.tech/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %>.repository.rowmapper + +<%_ if (fieldsContainBigDecimal === true) { _%> +import java.math.BigDecimal +<%_} if (fieldsContainInstant === true) { _%> +import java.time.Instant +<%_ } if (fieldsContainLocalDate === true) { _%> +import java.time.LocalDate +<%_ } if (fieldsContainZonedDateTime === true) { _%> +import java.time.ZonedDateTime +<%_ } if (fieldsContainDuration === true) { _%> +import java.time.Duration +<%_ } if (fieldsContainUUID === true) { _%> +import java.util.UUID +<%_ } _%> +import java.util.function.BiFunction + +import org.springframework.stereotype.Service + +import <%= packageName %>.domain.<%= persistClass %> +<%_ Object.keys(uniqueEnums).forEach(function(element) { _%> +import <%= packageName %>.domain.enumeration.<%= element %> +<%_ }); _%> +import <%= packageName %>.service.ColumnConverter + +import io.r2dbc.spi.Row + +/** + * Converter between {@link Row} to {@link <%= persistClass %>}, with proper type conversions. + */ +@Service +class <%= entityClass %>RowMapper(val converter: ColumnConverter): BiFunction> { + + /** + * Take a {@link Row} and a column prefix, and extract all the fields. + * @return the {@link <%= persistClass %>} stored in the database. + */ + override fun apply(row: Row, prefix: String): <%= persistClass %> { + val entity = <%= persistClass %>() + <%_ fields.forEach(function(field) { + let fieldType = field.fieldType; + if (field.fieldTypeBlobContent === 'text') { + fieldType = 'String'; + } + if (field.fieldType === 'byte[]' && field.fieldTypeBlobContent !== 'text') { _%> + entity.<%= field.fieldName %>ContentType = converter.fromRow(row, prefix + "_<%= field.fieldNameAsDatabaseColumn %>_content_type", String::class.java) + <%_ } if (field.fieldType === 'byte[]' && field.fieldTypeBlobContent !== 'text') { _%> + entity.<%= field.fieldName %> = converter.fromRow(row, prefix + "_<%= field.fieldNameAsDatabaseColumn %>", ByteArray::class.java) + <%_ } else if (field.fieldType === 'Integer') { _%> + entity.<%= field.fieldName %> = converter.fromRow(row, prefix + "_<%= field.fieldNameAsDatabaseColumn %>", Int::class.java) + <%_ } else { _%> + entity.<%= field.fieldName %> = converter.fromRow(row, prefix + "_<%= field.fieldNameAsDatabaseColumn %>", <%= fieldType %>::class.java) + <%_ }}); _%> + <%_ reactiveRegularEagerRelations.forEach(function(rel) { _%> + entity.<%= rel.relationshipName %>Id = converter.fromRow(row, prefix + "_<%= getColumnName(rel.relationshipName) %>_id", <%= rel.otherEntity.primaryKey.type %>::class.java) + <%_ }); _%> + return entity; + } + +} diff --git a/generators/entity-server/templates/src/main/kotlin/package/repository/search/EntitySearchRepository.kt.ejs b/generators/entity-server/templates/src/main/kotlin/package/repository/search/EntitySearchRepository.kt.ejs index fdf085ab7..257c2a3a9 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/repository/search/EntitySearchRepository.kt.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/repository/search/EntitySearchRepository.kt.ejs @@ -19,19 +19,20 @@ package <%= packageName %>.repository.search -import <%= packageName %>.domain.<%= asEntity(entityClass) %> +import <%= packageName %>.domain.<%= persistClass %> <%_ if (reactive) { _%> <%_ if (pagination !== 'no') { _%> import org.springframework.data.domain.Pageable <%_ } _%> import org.springframework.data.elasticsearch.core.ReactiveElasticsearchTemplate +import org.springframework.data.elasticsearch.core.SearchHit import org.springframework.data.elasticsearch.core.query.NativeSearchQuery <%_ } _%> import org.springframework.data.elasticsearch.repository.<% if (reactive) {%>Reactive<% } %>ElasticsearchRepository <%_ if (reactive) { _%> import reactor.core.publisher.Flux <%_ } _%> -<%_ if (primaryKeyType === 'UUID') { _%> +<%_ if (primaryKey.type === 'UUID') { _%> import java.util.UUID <%_ } _%> @@ -44,9 +45,9 @@ import org.springframework.data.elasticsearch.core.query.Query <%_ } _%> /** - * Spring Data Elasticsearch repository for the [<%= asEntity(entityClass) %>] entity. + * Spring Data Elasticsearch repository for the [<%= persistClass %>] entity. */ -interface <%=entityClass%>SearchRepository : <% if (reactive) {%>Reactive<% } %>ElasticsearchRepository<<%= asEntity(entityClass) %>, <%=primaryKeyType%>><% if (reactive) {%>, <%= entityClass %>SearchRepositoryInternal<% } %>{} +interface <%=entityClass%>SearchRepository : <% if (reactive) {%>Reactive<% } %>ElasticsearchRepository<<%= persistClass %>, <%=primaryKey.type%>><% if (reactive) {%>, <%= entityClass %>SearchRepositoryInternal<% } %>{} <%_ if (reactive) { _%> interface <%= entityClass %>SearchRepositoryInternal { fun search(query: String<% if (pagination !== 'no') { %>, pageable: Pageable<% } %>): Flux<<%= entityClass %>> @@ -60,7 +61,9 @@ class <%= entityClass %>SearchRepositoryInternalImpl(private val reactiveElastic <%_ if (pagination !== 'no') { _%> nativeSearchQuery.setPageable(pageable) <%_ } _%> - return reactiveElasticsearchTemplate.find(nativeSearchQuery, <%= entityClass %>::class.java) + return reactiveElasticsearchTemplate + .search(nativeSearchQuery, <%= entityClass %>::class.java) + .map(SearchHit<<%= entityClass %>>::getContent) } } <%_ } _%> \ No newline at end of file diff --git a/generators/entity-server/templates/src/main/kotlin/package/service/EntityQueryService.kt.ejs b/generators/entity-server/templates/src/main/kotlin/package/service/EntityQueryService.kt.ejs index 12349a1f7..c2301ecb2 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/service/EntityQueryService.kt.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/service/EntityQueryService.kt.ejs @@ -20,8 +20,8 @@ package <%= packageName %>.service <%_ const serviceClassName = entityClass + 'QueryService'; - const instanceType = (dto === 'mapstruct') ? asDto(entityClass) : asEntity(entityClass); - const instanceName = (dto === 'mapstruct') ? asDto(entityInstance) : asEntity(entityInstance); + const instanceType = restClass; + const instanceName = restInstance; const mapper = entityInstance + 'Mapper'; const dtoToEntity = mapper + '.'+ 'toEntity'; const entityToDto = mapper + '.'+ 'toDto'; @@ -39,10 +39,11 @@ import org.springframework.data.jpa.domain.Specification import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional -import io.github.jhipster.service.QueryService +import tech.jhipster.service.QueryService +import tech.jhipster.service.filter.Filter -import <%= packageName %>.domain.<%= asEntity(entityClass) %> -import <%= packageName %>.domain.<%= asEntity(entityClass) %>_ +import <%= packageName %>.domain.<%= persistClass %> +import <%= packageName %>.domain.<%= persistClass %>_ <%_ var mappedRelsTypes = []; relationships.forEach((relationship) => { @@ -53,21 +54,22 @@ import <%= packageName %>.domain.<%= asEntity(entityClass) %>_ }); mappedRelsTypes.sort(); mappedRelsTypes - .filter((relType) => relType !== asEntity(entityClass)) + .filter((relType) => relType !== persistClass) .forEach((relType) => { _%> import <%= packageName %>.domain.<%= relType %>_ <%_ }); _%> import <%= packageName %>.repository.<%= entityClass %>Repository<% if (searchEngine === 'elasticsearch') { %> import <%= packageName %>.repository.search.<%= entityClass %>SearchRepository<% } %> -import <%= packageName %>.service.dto.<%= entityClass %>Criteria +import <%= packageName %>.service.criteria.<%= entityClass %>Criteria <%_ if (dto === 'mapstruct') { _%> -import <%= packageName %>.service.dto.<%= asDto(entityClass) %> +import <%= packageName %>.service.dto.<%= dtoClass %> import <%= packageName %>.service.mapper.<%= entityClass %>Mapper <%_ } _%> +import java.util.UUID /** - * Service for executing complex queries for [<%= asEntity(entityClass) %>] entities in the database. + * Service for executing complex queries for [<%= persistClass %>] entities in the database. * The main input is a [<%= entityClass %>Criteria] which gets converted to [Specification], * in a way that all the filters must apply. * It returns a [MutableList] of [<%= instanceType %>] or a [Page] of [<%= instanceType %>] which fulfills the criteria. @@ -76,7 +78,7 @@ import <%= packageName %>.service.mapper.<%= entityClass %>Mapper @Transactional(readOnly = true)<% } %> class <%= serviceClassName %>( <%- include('../common/inject_template', {viaService: false, constructorName: serviceClassName, queryService: false, isUsingMapsId: false, mapsIdAssoc: null, isController: false}); -%> -) : QueryService<<%= asEntity(entityClass) %>>() { +) : QueryService<<%= persistClass %>>() { private val log = LoggerFactory.getLogger(javaClass) @@ -131,17 +133,18 @@ class <%= serviceClassName %>( * @param criteria The object which holds all the filters, which the entities should match. * @return the matching [Specification] of the entity. */ - protected fun createSpecification(criteria: <%= criteria %>?): Specification<<%= asEntity(entityClass) %>?> { - var specification: Specification<<%= asEntity(entityClass) %>?> = Specification.where(null) + protected fun createSpecification(criteria: <%= criteria %>?): Specification<<%= persistClass %>?> { + var specification: Specification<<%= persistClass %>?> = Specification.where(null) if (criteria != null) { - if (criteria.id != null) { - specification = specification.and(<%= getSpecificationBuilder(primaryKeyType) %>(criteria.id, <%= asEntity(entityClass) %>_.id)) + if (criteria.<%= primaryKey.name %> != null) { + specification = specification.and(<%= getSpecificationBuilder(primaryKey.type) %>(criteria.<%= primaryKey.name %>, <%= persistClass %>_.<%= primaryKey.name %>)) } <%_ fields.forEach((field) => { + if (field.id) return; if (isFilterableType(field.fieldType)) { _%> if (criteria.<%= field.fieldName %> != null) { - specification = specification.and(<%= getSpecificationBuilder(field.fieldType) %>(criteria.<%= field.fieldName %>, <%= asEntity(entityClass) %>_.<%= field.fieldName %>)) + specification = specification.and(<%= getSpecificationBuilder(field.fieldType) %>(criteria.<%= field.fieldName %>, <%= persistClass %>_.<%= field.fieldName %>)) } <%_ } }); @@ -149,8 +152,8 @@ class <%= serviceClassName %>( relationships.forEach((relationship) => { const metamodelFieldName = (relationship.relationshipType === 'many-to-many' || relationship.relationshipType === 'one-to-many') ? relationship.relationshipFieldNamePlural : relationship.relationshipFieldName; _%> if (criteria.<%= relationship.relationshipName %>Id != null) { - specification = specification.and(buildSpecification(criteria.<%= relationship.relationshipName %>Id) { - it.join(<%= asEntity(entityClass) %>_.<%= metamodelFieldName %>, JoinType.LEFT).get(<%= asEntity(relationship.otherEntityNameCapitalized) %>_.id) + specification = specification.and(buildSpecification(criteria.<%= relationship.relationshipName %>Id as Filter<<%= relationship.otherEntity.primaryKey.type %>>) { + it.join(<%= persistClass %>_.<%= metamodelFieldName %>, JoinType.LEFT).get(<%= asEntity(relationship.otherEntityNameCapitalized) %>_.<%= relationship.otherEntity.primaryKey.name %>) }) } <%_ }); // forEach diff --git a/generators/entity-server/templates/src/main/kotlin/package/service/EntityService.kt.ejs b/generators/entity-server/templates/src/main/kotlin/package/service/EntityService.kt.ejs index 12636efad..df9fe3f12 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/service/EntityService.kt.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/service/EntityService.kt.ejs @@ -18,25 +18,24 @@ -%> package <%= packageName %>.service <%_ -const primaryKeyType = getPkTypeBasedOnDBAndAssociation(authenticationType, databaseType, relationships); -const instanceType = (dto === 'mapstruct') ? asDto(entityClass) : asEntity(entityClass); -const instanceName = (dto === 'mapstruct') ? asDto(entityInstance) : asEntity(entityInstance); +const instanceType = restClass; +const instanceName = restInstance; const optionalOrMono = (reactive === true) ? 'Mono' : 'Optional'; const listOrFlux = (reactive === true) ? 'Flux' : 'MutableList'; const pageOrFlux = (reactive === true) ? 'Flux' : 'Page'; _%> <%_ if (dto === 'mapstruct') { _%> -import <%= packageName %>.service.dto.<%= asDto(entityClass) %> +import <%= packageName %>.service.dto.<%= dtoClass %> <%_ } else { _%> -import <%= packageName %>.domain.<%= asEntity(entityClass) %> +import <%= packageName %>.domain.<%= persistClass %> <%_ } _%> -<%_ if (pagination !== 'no' || fieldsContainOwnerManyToMany === true) { _%> +<%_ if (pagination !== 'no' || relationshipsContainEagerLoad) { _%> <%_ if (!reactive) { _%> import org.springframework.data.domain.Page <%_ } _%> import org.springframework.data.domain.Pageable <%_ } _%> -<%_ if (reactiveRepositories) { _%> +<%_ if (reactive) { _%> import reactor.core.publisher.Flux import reactor.core.publisher.Mono <%_ } _%> @@ -44,12 +43,12 @@ import reactor.core.publisher.Mono <%_ if (!reactive) { _%> import java.util.Optional <%_ } _%> -<%_ if (databaseType === 'cassandra') { _%> +<%_ if (primaryKey.type === 'UUID') { _%> import java.util.UUID <%_ } _%> /** - * Service Interface for managing [<% if (dto === 'mapstruct') { %><%= packageName %>.domain.<% } %><%= asEntity(entityClass) %>]. + * Service Interface for managing [<% if (dto === 'mapstruct') { %><%= packageName %>.domain.<% } %><%= persistClass %>]. */ interface <%= entityClass %>Service { @@ -61,6 +60,14 @@ interface <%= entityClass %>Service { */ fun save(<%= instanceName %>: <%= instanceType %>): <% if (reactive) { %>Mono<<% } %><%= instanceType %><% if (reactive) { %>><% } %> + /** + * Partially updates a <%= entityInstance %>. + * + * @param <%= instanceName %> the entity to update partially. + * @return the persisted entity. + */ + fun partialUpdate(<%= instanceName %>: <%= instanceType %>): <% if (!reactive) { %>Optional<<% } %><% if (reactive) { %>Mono<<% } %><%= instanceType %>> + /** * Get all the <%= entityInstancePlural %>. *<% if (pagination !== 'no') { %> @@ -68,19 +75,20 @@ interface <%= entityClass %>Service { * @return the list of entities. */ fun findAll(<% if (pagination !== 'no') { %>pageable: Pageable<% } %>): <% if (pagination !== 'no') { %><%= pageOrFlux %><<%= instanceType %><% } else { %><%= listOrFlux %><<%= instanceType %><% } %>> -<% for (idx in relationships) { if (relationships[idx].relationshipType === 'one-to-one' && relationships[idx].ownerSide !== true) { -%> +<% for (const relationship of relationships) { if (relationship.relationshipType === 'one-to-one' && relationship.ownerSide !== true) { -%> /** - * Get all the [<%= asDto(entityClass) %>] where <%= relationships[idx].relationshipNameCapitalized %> is `null`. + * Get all the [<%= restClass %>] where <%= relationship.relationshipNameCapitalized %> is `null`. * * @return the {@link <%= listOrFlux %>} of entities. */ - fun findAllWhere<%= relationships[idx].relationshipNameCapitalized %>IsNull(): <%= listOrFlux %><<%= instanceType %>> + fun findAllWhere<%= relationship.relationshipNameCapitalized %>IsNull(): <%= listOrFlux %><<%= instanceType %>> <%_ } } _%> - <%_ if (fieldsContainOwnerManyToMany === true) { _%> + <%_ if (relationshipsContainEagerLoad) { _%> /** * Get all the <%= entityInstancePlural %> with eager load of many-to-many relationships. - * + * @param pageable the pagination information. + * * @return the list of entities. */ fun findAllWithEagerRelationships(pageable: Pageable): <%= pageOrFlux %><<%= instanceType %>> @@ -88,7 +96,7 @@ interface <%= entityClass %>Service { <%_ if (reactive) { _%> /** * Returns the number of <%= entityInstancePlural %> available. - * + * @return the number of entities in the database. */ fun countAll(): Mono <%_ if (searchEngine === 'elasticsearch') { _%> @@ -106,14 +114,17 @@ interface <%= entityClass %>Service { * @param id the id of the entity. * @return the entity. */ - fun findOne(id: <%= primaryKeyType %>): <%= optionalOrMono %><<%= instanceType %>> + fun findOne(id: <%= primaryKey.type %>): <%= optionalOrMono %><<%= instanceType %>> /** * Delete the "id" <%= entityInstance %>. * * @param id the id of the entity. +<%_ if (reactive) { _%> + * @return a Mono to signal the deletion +<%_ } _%> */ - fun delete(id: <%= primaryKeyType %>)<% if (reactive) { %>: Mono <% } %> + fun delete(id: <%= primaryKey.type %>)<% if (reactive) { %>: Mono <% } %> <% if (searchEngine === 'elasticsearch') { %> diff --git a/generators/entity-server/templates/src/main/kotlin/package/service/dto/EntityCriteria.kt.ejs b/generators/entity-server/templates/src/main/kotlin/package/service/criteria/EntityCriteria.kt.ejs similarity index 75% rename from generators/entity-server/templates/src/main/kotlin/package/service/dto/EntityCriteria.kt.ejs rename to generators/entity-server/templates/src/main/kotlin/package/service/criteria/EntityCriteria.kt.ejs index 06519b0e3..4c66b82a5 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/service/dto/EntityCriteria.kt.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/service/criteria/EntityCriteria.kt.ejs @@ -16,42 +16,39 @@ See the License for the specific language governing permissions and limitations under the License. -%> -package <%= packageName %>.service.dto +package <%= packageName %>.service.criteria import java.io.Serializable -import io.github.jhipster.service.Criteria -<%_ for (idx in fields) { if (fields[idx].fieldIsEnum === true) { _%> -import <%= packageName %>.domain.enumeration.<%= fields[idx].fieldType %> +import tech.jhipster.service.Criteria +<%_ for (const field of fields) { if (field.fieldIsEnum === true) { _%> +import <%= packageName %>.domain.enumeration.<%= field.fieldType %> <%_ } } _%> -import io.github.jhipster.service.filter.BooleanFilter -import io.github.jhipster.service.filter.DoubleFilter -import io.github.jhipster.service.filter.Filter -import io.github.jhipster.service.filter.FloatFilter -import io.github.jhipster.service.filter.IntegerFilter -import io.github.jhipster.service.filter.LongFilter -import io.github.jhipster.service.filter.StringFilter +import tech.jhipster.service.filter.BooleanFilter +import tech.jhipster.service.filter.DoubleFilter +import tech.jhipster.service.filter.Filter +import tech.jhipster.service.filter.FloatFilter +import tech.jhipster.service.filter.IntegerFilter +import tech.jhipster.service.filter.LongFilter +import tech.jhipster.service.filter.StringFilter <%_ if (fieldsContainBigDecimal === true) { _%> -import io.github.jhipster.service.filter.BigDecimalFilter +import tech.jhipster.service.filter.BigDecimalFilter <%_ } _%> <%_ if (fieldsContainDuration === true) { _%> -import io.github.jhipster.service.filter.DurationFilter +import tech.jhipster.service.filter.DurationFilter <%_ } _%> <%_ if (fieldsContainInstant === true) { _%> -import io.github.jhipster.service.filter.InstantFilter +import tech.jhipster.service.filter.InstantFilter <%_ } _%> <%_ if (fieldsContainLocalDate === true) { _%> -import io.github.jhipster.service.filter.LocalDateFilter -<%_ } _%> -<%_ if (fieldsContainUUID === true) { _%> -import io.github.jhipster.service.filter.UUIDFilter +import tech.jhipster.service.filter.LocalDateFilter <%_ } _%> +import tech.jhipster.service.filter.UUIDFilter <%_ if (fieldsContainZonedDateTime === true) { _%> -import io.github.jhipster.service.filter.ZonedDateTimeFilter +import tech.jhipster.service.filter.ZonedDateTimeFilter <%_ } _%> <%_ - const referenceFilterType = '' + primaryKeyType + 'Filter'; - var filterVariables = [{name:'id', type: primaryKeyType, filterType:referenceFilterType,fieldInJavaBeanMethod:'Id' } ]; + var filterVariables = []; var extraFilters = {}; fields.forEach((field) => { const fieldType = field.fieldType; @@ -72,7 +69,8 @@ import io.github.jhipster.service.filter.ZonedDateTimeFilter } }); relationships.forEach((relationship) => { - const relationshipType = relationship.relationshipType; + const relationshipType = relationship.otherEntity.primaryKey.type; + const referenceFilterType = '' + relationshipType + 'Filter'; // user has a String PK when using OAuth, so change relationships accordingly let oauthAwareReferenceFilterType = referenceFilterType; if (relationship.otherEntityName === 'user' && authenticationType === 'oauth2') { @@ -85,7 +83,7 @@ import io.github.jhipster.service.filter.ZonedDateTimeFilter }); _%> /** - * Criteria class for the [<%= packageName %>.domain.<%= asEntity(entityClass) %>] entity. This class is used in + * Criteria class for the [<%= packageName %>.domain.<%= persistClass %>] entity. This class is used in * [<%= packageName %>.web.rest.<%= entityClass %>Resource] to receive all the possible filtering options from the * Http GET request parameters. * For example the following could be a valid request: diff --git a/generators/entity-server/templates/src/main/kotlin/package/service/dto/EntityDTO.kt.ejs b/generators/entity-server/templates/src/main/kotlin/package/service/dto/EntityDTO.kt.ejs index 087187cef..58c1d59e4 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/service/dto/EntityDTO.kt.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/service/dto/EntityDTO.kt.ejs @@ -1,5 +1,5 @@ <%# - Copyright 2013-2020 the original author or authors from the JHipster project. + Copyright 2013-2021 the original author or authors from the JHipster project. This file is part of the JHipster project, see https://www.jhipster.tech/ for more information. @@ -8,7 +8,7 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -18,9 +18,7 @@ -%> package <%= packageName %>.service.dto -<%_ -let { importApiModelProperty, importJsonIgnore, importJsonIgnoreProperties, importSet, uniqueEnums } = _processJavaEntityImports(fields, relationships); -_%> +import java.util.Objects <%_ if (typeof javadoc != 'undefined') { _%> import io.swagger.annotations.ApiModel <%_ } if (importApiModelProperty === true) { _%> @@ -39,13 +37,7 @@ import java.time.ZonedDateTime import java.time.Duration <%_ } _%> <%_ if (validation) { _%> -import javax.validation.constraints.DecimalMax -import javax.validation.constraints.DecimalMin -import javax.validation.constraints.Max -import javax.validation.constraints.Min -import javax.validation.constraints.NotNull -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size +import javax.validation.constraints.* <%_ } _%> import java.io.Serializable <%_ if (fieldsContainBigDecimal) { _%> @@ -54,125 +46,93 @@ import java.math.BigDecimal <%_ if (fieldsContainBlob && databaseType === 'cassandra') { _%> import java.nio.ByteBuffer <%_ } _%> -<%_ if (databaseType === 'cassandra' || fieldsContainUUID === true) { _%> +<%_ if (fieldsContainUUID === true) { _%> import java.util.UUID <%_ } _%> <%_ if (fieldsContainBlob && databaseType === 'sql') { _%> import javax.persistence.Lob <%_ } _%> <%_ Object.keys(uniqueEnums).forEach(function(element) { _%> - import <%= packageName %>.domain.enumeration.<%= element %> +import <%= packageName %>.domain.enumeration.<%= element %> <%_ }); _%> -<%_ -var mappedRels = []; -relationships.forEach((relationship) => { - if ( (relationship.relationshipType === 'many-to-many' && relationship.ownerSide === true) || - (relationship.relationshipType === 'many-to-one' || (relationship.relationshipType === 'one-to-one' && relationship.ownerSide === true)) || - (relationship.otherEntityFieldCapitalized !== 'Id' && relationship.otherEntityFieldCapitalized !== '')) { - // TODO temporary calculation update this later. - const oside = relationship.ownerSide || false; - if (!(embedded && !relationship.otherEntityIsEmbedded && oside === false)) { - mappedRels.push( relationship ); - } - } -}); -_%> /** - * A DTO for the [<%= packageName %>.domain.<%= asEntity(entityClass) %>] entity. + * A DTO for the [<%= packageName %>.domain.<%= persistClass %>] entity. */ <%_ if (typeof javadoc !== 'undefined') { _%> @ApiModel(description = "<%- formatAsApiDescription(javadoc) %>") <%_ } _%> -data class <%= asDto(entityClass) %>( - <% if (!embedded) { %> - var id: <%= primaryKeyType %>? = null, - <%_ } _%> - <%_ for (idx in fields) { - if (typeof fields[idx].javadoc !== 'undefined') { _%> -<%- formatAsFieldJavadoc(fields[idx].javadoc) %> - <%_ } - let required = false; - const fieldValidate = fields[idx].fieldValidate; - const fieldValidateRules = fields[idx].fieldValidateRules; - const fieldValidateRulesMinlength = fields[idx].fieldValidateRulesMinlength; - const fieldValidateRulesMaxlength = fields[idx].fieldValidateRulesMaxlength; - const fieldValidateRulesMinbytes = fields[idx].fieldValidateRulesMinbytes; - const fieldValidateRulesMaxbytes = fields[idx].fieldValidateRulesMaxbytes; - const fieldValidateRulesMin = fields[idx].fieldValidateRulesMin; - const fieldValidateRulesMax = fields[idx].fieldValidateRulesMax; - const fieldValidateRulesPatternJava = fields[idx].fieldValidateRulesPatternJava; - const fieldType = fields[idx].fieldType; - const fieldTypeBlobContent = fields[idx].fieldTypeBlobContent; - const fieldName = fields[idx].fieldName; - const comma = ((parseInt(idx, 10) === (fields.length - 1)) && mappedRels.length < 1 ) ? '' : ',';_%> +data class <%= dtoClass %>( + <%_ + const entityClassProperties = []; + dtoReferences.forEach(reference => { + const classProperty = []; + if (typeof reference.doc !== 'undefined') { + classProperty.push(formatAsFieldJavadoc(reference.doc)); + } + const field = reference.field; + const required = field && field.fieldValidate && field.fieldValidateRules.includes('required'); + if (field) { + if (field.fieldValidate === true) { + classProperty.push(include('../../common/field_validators', {field, reactive})); + } + } + if (reference.doc) { + classProperty.push(`@ApiModelProperty(value="${formatAsApiDescription(reference.doc)}"${required ? ', required = true': ''})`); + } + if (reference.type === 'byte[]' && databaseType === 'sql') { + classProperty.push('@Lob'); + } - <%_ if (fieldValidate === true) { - if (fieldValidateRules.includes('required')) { - required = true; - } _%> - <%- include('../../common/field_validators'); -%> - <%_ } _%> - <%_ if (typeof fields[idx].javadoc != 'undefined') { _%> - @ApiModelProperty(value = "<%- formatAsApiDescription(fields[idx].javadoc) %>"<% if (required) { %>, required = true<% } %>) - <%_ } _%> - <%_ if (fieldType === 'byte[]' && databaseType === 'sql') { _%> - @Lob - <%_ } _%> - <%_ if (fieldTypeBlobContent !== 'text') { _%> - var <%= fieldName %>: <% if(fieldType === 'byte[]') { _%>ByteArray<%_ } else if(fieldType==='Integer'){ _%>Int<%_ } else { _%><%= fieldType %><% } %>? = null<%_ if (fieldType === 'byte[]' || fieldType === 'ByteBuffer') { _%>,<%_ } else { _%><%= comma %><%_ } %> - <%_ } else { _%> - var <%= fieldName %>: String? = null<%= comma %> - <%_ } _%> - <%_ if ((fieldType === 'byte[]' || fieldType === 'ByteBuffer') && fieldTypeBlobContent !== 'text') { _%> - var <%= fieldName %>ContentType: String? = null<%= comma %> - <%_ } _%> - <%_ } _%> - <%_ mappedRels.forEach( (relationship, index) => { - const relationshipFieldName = relationship.relationshipFieldName; - const relationshipFieldNamePlural = relationship.relationshipFieldNamePlural; - const relationshipType = relationship.relationshipType; - const otherEntityPrimaryKeyType = relationship.otherEntityPrimaryKeyType; - const otherEntityNameCapitalized = relationship.otherEntityNameCapitalized; - const otherEntityFieldCapitalized = relationship.otherEntityFieldCapitalized; - const otherEntityIsEmbedded = relationship.otherEntityIsEmbedded; - const ownerSide = relationship.ownerSide; - var comma = index === (mappedRels.length - 1) ? '' : ','; - if (typeof relationship.javadoc != 'undefined') { _%> -<%- formatAsFieldJavadoc(relationship.javadoc) %> - @ApiModelProperty(value = "<%- formatAsApiDescription(relationship.javadoc) %>") - <%_ } - if ((relationshipType === 'many-to-many' && ownerSide === true) - || (relationshipType === 'one-to-many' && otherEntityIsEmbedded)) { _%> + let property = ''; + + if (reference.field && reference.field.fieldTypeBlobContent === 'text') { + property = `var ${reference.name}: String? = null`; + } else if (reference.collection && reference.relationship) { + property = `var ${reference.name}: MutableSet<${asDto(reference.relationship.otherEntity.entityNameCapitalized)}> = mutableSetOf()`; + } else if (reference.relationship) { + property = `var ${reference.name}: ${asDto(reference.relationship.otherEntity.entityNameCapitalized)}? = null`; + } else if (reference.type === 'byte[]') { + property = `var ${reference.name}: ByteArray? = null`; + } else if (reference.type === 'Integer') { + property = `var ${reference.name}: Int? = null`; + } else { + property = `var ${reference.name}: ${reference.type}? = null`; + } - var <%= relationshipFieldNamePlural %>: MutableSet<<%= asDto(otherEntityNameCapitalized) %>> = mutableSetOf()<%= comma %> - <%_ } else if (relationshipType === 'one-to-one' && ownerSide === true && otherEntityIsEmbedded) { _%> - var <%= relationshipFieldName %>: <%= asDto(otherEntityNameCapitalized) %><%= comma %> - <%_ } else if (!embedded && (relationshipType === 'many-to-one' || (relationshipType === 'one-to-one' && ownerSide === true))) { - if(index === (mappedRels.length - 1) && otherEntityFieldCapitalized !== 'Id' && otherEntityFieldCapitalized !== '') { - comma = ','; + if (reference.field && reference.field.fieldWithContentType) { + property += `,\n var ${reference.name}ContentType: String? = null`; } - _%> - var <%= relationshipFieldName %>Id: <%= otherEntityPrimaryKeyType %>? = null<%= comma %> - <%_ if (otherEntityFieldCapitalized !== 'Id' && otherEntityFieldCapitalized !== '') { - comma = index === (mappedRels.length - 1) ? '' : ','; - _%> + classProperty.push(property); - var <%= relationshipFieldName %><%= otherEntityFieldCapitalized %>: String? = null<%= comma %> - <%_ } } }); _%> + entityClassProperties.push(classProperty.join(' ')); + }); + _%> + <%- entityClassProperties.join(',\n\n ') %> ) : Serializable { + <%_ const idNames = primaryKey ? [...primaryKey.fields.map(f => f.fieldName)] : [] _%> + override fun equals(other: Any?): Boolean { if (this === other) return true - if (other !is <%= asDto(entityClass) %>) return false + if (other !is <%= dtoClass %>) return false <%_ if (!embedded) { _%> - return id!= null && id == other.id + val <%= dtoInstance %> = other + if (<%- idNames.map(n => `this.${n} == null`).join(' && ') %>){ + return false; + } + return <%- idNames.map(n => `Objects.equals(this.${n}, ${dtoInstance}.${n})`).join(' &&\n ') %>; <%_ } else { _%> return false <%_ } _%> } - override fun hashCode() = 31 + override fun hashCode() = <%_ if (!embedded) { _%> + Objects.hash(<%- idNames.map(n => `this.${n}`).join(', ') %>) + <%_ } else { _%> + <%# Todo: Fix this %> + 31 + <%_ } _%> } diff --git a/generators/entity-server/templates/src/main/kotlin/package/service/impl/EntityServiceImpl.kt.ejs b/generators/entity-server/templates/src/main/kotlin/package/service/impl/EntityServiceImpl.kt.ejs index 700e56efc..0a1ae097e 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/service/impl/EntityServiceImpl.kt.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/service/impl/EntityServiceImpl.kt.ejs @@ -17,10 +17,11 @@ limitations under the License. -%> package <%= packageName %>.service<% if (service === 'serviceImpl') { %>.impl<% } %> + <%_ const serviceClassName = service === 'serviceImpl' ? entityClass + 'ServiceImpl' : entityClass + 'Service'; - const instanceType = (dto === 'mapstruct') ? asDto(entityClass) : asEntity(entityClass); - const instanceName = (dto === 'mapstruct') ? asDto(entityInstance) : asEntity(entityInstance); + const instanceType = restClass; + const instanceName = restInstance; const optionalOrMono = (reactive === true) ? 'Mono' : 'Optional'; const listOrFlux = (reactive === true) ? 'Flux' : 'MutableList'; const pageOrFlux = (reactive === true) ? 'Flux' : 'Page'; @@ -30,20 +31,11 @@ package <%= packageName %>.service<% if (service === 'serviceImpl') { %>.impl<% const entityToDtoReference = mapper + '::'+ 'toDto'; const repository = entityInstance + 'Repository'; const searchRepository = entityInstance + 'SearchRepository'; - let isUsingMapsId = false; - let mapsIdAssoc; - for (idx in relationships) { - isUsingMapsId = relationships[idx].useJPADerivedIdentifier === true; - if (isUsingMapsId) { - mapsIdAssoc = relationships[idx]; - break; - } - } _%> <%_ if (service === 'serviceImpl') { %> import <%= packageName %>.service.<%= entityClass %>Service <%_ } _%> -import <%= packageName %>.domain.<%= asEntity(entityClass) %> +import <%= packageName %>.domain.<%= persistClass %> import <%= packageName %>.repository.<%= entityClass %>Repository <%_ if (isUsingMapsId === true) { _%> import <%= packageName %>.repository.<%= mapsIdAssoc.otherEntityNameCapitalized %>Repository @@ -52,12 +44,12 @@ import <%= packageName %>.repository.<%= mapsIdAssoc.otherEntityNameCapitalized import <%= packageName %>.repository.search.<%= entityClass %>SearchRepository <%_ } _%> <%_ if (dto === 'mapstruct') { _%> -import <%= packageName %>.service.dto.<%= asDto(entityClass) %> +import <%= packageName %>.service.dto.<%= dtoClass %> import <%= packageName %>.service.mapper.<%= entityClass %>Mapper <%_ } _%> import org.slf4j.LoggerFactory -<%_ if (pagination !== 'no' || fieldsContainOwnerManyToMany === true) { _%> +<%_ if (pagination !== 'no' || relationshipsContainEagerLoad) { _%> <%_ if (!reactive) { _%> import org.springframework.data.domain.Page <%_ } _%> @@ -67,14 +59,14 @@ import org.springframework.stereotype.Service <%_ if (databaseType === 'sql') { _%> import org.springframework.transaction.annotation.Transactional <%_ } _%> -<%_ if (reactiveRepositories) { _%> +<%_ if (reactive) { _%> import reactor.core.publisher.Flux import reactor.core.publisher.Mono <%_ } _%> <%_ if (!reactive) { _%> import java.util.Optional <%_ } _%> -<%_ if (databaseType === 'cassandra') { _%> +<%_ if (primaryKey.type === 'UUID') { _%> import java.util.UUID <%_ } _%> <%_ if (fieldsContainNoOwnerOneToOne === true || (pagination === 'no' && ((searchEngine !== false) || dto === 'mapstruct'))) { _%> @@ -89,12 +81,12 @@ import org.elasticsearch.index.query.QueryBuilders.queryStringQuery <%_ } _%> /** - * Service Implementation for managing [<%= asEntity(entityClass) %>]. + * Service Implementation for managing [<%= persistClass %>]. */ @Service<% if (databaseType === 'sql') { %> @Transactional<% } %> class <%= serviceClassName %>( - <%- include('../../common/inject_template', {asEntity, asDto, viaService: false, constructorName: serviceClassName, queryService: false, isUsingMapsId: isUsingMapsId, mapsIdAssoc: mapsIdAssoc, isController: false}); -%> + <%- include('../../common/inject_template', {asEntity, asDto, viaService: false, constructorName: serviceClassName, queryService: false, isUsingMapsId: isUsingMapsId, mapsIdAssoc: mapsIdAssoc, isController: false, noReturn: false}); -%> )<% if (service === 'serviceImpl') { %> : <%= entityClass %>Service<% } %> { private val log = LoggerFactory.getLogger(javaClass) @@ -109,11 +101,20 @@ class <%= serviceClassName %>( <%_ } _%> <% if (service === 'serviceImpl') { _%>override <% } %>fun save(<%= instanceName %>: <%= instanceType %>): <% if (reactive) { %>Mono<<% } %><%= instanceType %><% if (reactive) { %>><% } %> { log.debug("Request to save <%= entityClass %> : $<%= instanceName %>") - <%_ if (!reactive) { _%> -<%- include('../../common/save_template', {asEntity, asDto, viaService: false, returnDirectly: true, isUsingMapsId: isUsingMapsId, mapsIdAssoc: mapsIdAssoc, isController: false}); -%> - <%_ } else { _%> -<%- include('../../common/save_reactive_template', {asEntity, asDto, viaService: false, returnDirectly: true}); -%> - <%_ } _%> +<%- include('/partials/save_template', {asEntity, asDto, viaService: false, returnDirectly: true, isUsingMapsId: isUsingMapsId, mapsIdAssoc: mapsIdAssoc, isController: false, noReturn: false}); -%> + } + + <%_ if (service !== 'serviceImpl') { _%> + /** + * Partially updates a <%= entityInstance %>. + * + * @param <%= instanceName %> the entity to update partially. + * @return the persisted entity. + */ + <%_ } _%> + <% if (service === 'serviceImpl') { %>override <% } %>fun partialUpdate(<%= instanceName %>: <%= instanceType %>): <% if (!reactive) { %>Optional<<% } %><% if (reactive) { %>Mono<<% } %><%= instanceType %>> { + log.debug("Request to partially update <%= entityClass %> : {}", <%= instanceName %>) +<%- include('../../common/patch_template', {asEntity, asDto, isService: true, viaService: false}); -%> } <%_ if (service !== 'serviceImpl') { _%> @@ -130,15 +131,15 @@ class <%= serviceClassName %>( <% if (service === 'serviceImpl') { %>override <% } %>fun findAll(<% if (pagination !== 'no') { %>pageable: Pageable<% } %>): <% if (pagination !== 'no') { %><%= pageOrFlux %><<%= instanceType %><% } else { %><%= listOrFlux %><<%= instanceType %><% } %>> { log.debug("Request to get all <%= entityClassPlural %>") <%_ if (pagination === 'no') { _%> - return <%= entityInstance %>Repository.<% if (fieldsContainOwnerManyToMany === true) { %>findAllWithEagerRelationships<% } else { %>findAll<% } %>()<% if (dto === 'mapstruct') { %><% if (reactive !== true) { %> - .mapTo(mutableListOf(), <%= entityToDtoReference %>)<% } else { %>.map(<%= entityToDtoReference %> )<% } %><% } %> + return <%= entityInstance %>Repository.<% if (relationshipsContainEagerLoad) { %>findAllWithEagerRelationships<% } else { %>findAll<% } %>()<% if (dto === 'mapstruct') { %><% if (reactive !== true) { %> + .mapTo(mutableListOf(), <%= entityToDtoReference %>)<% } else { %>.map(<%= entityToDtoReference %> )<% } %><% } %> <%_ } else { _%> return <%= entityInstance %>Repository.findAll<% if (reactive) { %>By<% } %>(pageable)<% if (dto === 'mapstruct') { %> .map(<%= entityToDtoReference %>)<% } %> <%_ } _%> } - <%_ if (fieldsContainOwnerManyToMany === true) { _%> + <%_ if (relationshipsContainEagerLoad) { _%> <%_ if (service !== 'serviceImpl') { _%> /** @@ -156,7 +157,7 @@ class <%= serviceClassName %>( <%_ if (service !== 'serviceImpl') { _%> /** * Returns the number of <%= entityInstancePlural %> available. - * + * @return the number of entities in the database. */ <%_ } _%> <% if (service === 'serviceImpl') { %>override <% } %>fun countAll() = <%= entityInstance %>Repository.count() @@ -183,7 +184,7 @@ class <%= serviceClassName %>( <%_ if (databaseType === 'sql') { _%> @Transactional(readOnly = true) <%_ } _%> - <% if (service === 'serviceImpl') { %>override <% } %>fun findOne(id: <%= primaryKeyType %>): <%= optionalOrMono %><<%= instanceType %>> { + <% if (service === 'serviceImpl') { %>override <% } %>fun findOne(id: <%= primaryKey.type %>): <%= optionalOrMono %><<%= instanceType %>> { log.debug("Request to get <%= entityClass %> : $id")<%- include('../../common/get_template', {asEntity, asDto, viaService: false, returnDirectly:true}); -%> } @@ -192,9 +193,12 @@ class <%= serviceClassName %>( * Delete the <%= entityInstance %> by id. * * @param id the id of the entity. + <%_ if (reactive) { _%> + * @return a Mono to signal the deletion + <%_ } _%> */ <%_ } _%> - <% if (service === 'serviceImpl') { %>override <% } %>fun delete(id: <%= primaryKeyType %>): <%- reactive ? 'Mono' : 'Unit' %> { + <% if (service === 'serviceImpl') { %>override <% } %>fun delete(id: <%= primaryKey.type %>): <%- reactive ? 'Mono' : 'Unit' %> { log.debug("Request to delete <%= entityClass %> : $id") <%- include('../../common/delete_template', {viaService: false, fromResource: false}); -%> } diff --git a/generators/entity-server/templates/src/main/kotlin/package/service/mapper/BaseEntityMapper.kt.ejs b/generators/entity-server/templates/src/main/kotlin/package/service/mapper/BaseEntityMapper.kt.ejs index 932d26a44..cce257544 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/service/mapper/BaseEntityMapper.kt.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/service/mapper/BaseEntityMapper.kt.ejs @@ -18,6 +18,11 @@ -%> package <%= packageName %>.service.mapper +import org.mapstruct.BeanMapping +import org.mapstruct.MappingTarget +import org.mapstruct.Named +import org.mapstruct.NullValuePropertyMappingStrategy + /** * Contract for a generic dto to entity mapper. * @@ -34,4 +39,8 @@ interface EntityMapper { fun toEntity(dtoList: MutableList): MutableList fun toDto(entityList: MutableList): MutableList + + @Named("partialUpdate") + @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) + fun partialUpdate(@MappingTarget entity: E, dto: D) } diff --git a/generators/entity-server/templates/src/main/kotlin/package/service/mapper/EntityMapper.kt.ejs b/generators/entity-server/templates/src/main/kotlin/package/service/mapper/EntityMapper.kt.ejs index 73146af53..6e022e784 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/service/mapper/EntityMapper.kt.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/service/mapper/EntityMapper.kt.ejs @@ -20,36 +20,20 @@ package <%= packageName %>.service.mapper <%_ let existingMappings = []; -let uuidMapMethod = false; -let byteMapMethod = false; -for (idx in relationships) { - if ((relationships[idx].relationshipType === 'many-to-many' && relationships[idx].ownerSide === true) || relationships[idx].relationshipType === 'many-to-one' || (relationships[idx].relationshipType === 'one-to-one' && relationships[idx].ownerSide === true)) { - // if the entity is mapped twice, we should implement the mapping once - if (!existingMappings.includes(relationships[idx].otherEntityNameCapitalized) && asEntity(relationships[idx].otherEntityNameCapitalized) !== asEntity(entityClass)) { - existingMappings.push(relationships[idx].otherEntityNameCapitalized); - } - let otherEntity = getExistingEntities().find(e => e.name === relationships[idx].otherEntityNameCapitalized); - if (otherEntity) { - let otherEntityField = otherEntity.definition.fields.find(f => f.fieldName === relationships[idx].otherEntityField); - if (otherEntityField) { - if (otherEntityField.fieldType === 'UUID') { - uuidMapMethod = true; - } - if (otherEntityField.fieldType === 'byte[]') { - byteMapMethod = true; - } - } - } - } -} +let uuidMapMethod = dtoReferences.some(reference => reference.valueReference && reference.valueReference.field && reference.valueReference.field.fieldType === 'UUID'); +let byteMapMethod = dtoReferences.some(reference => reference.valueReference && reference.valueReference.field && reference.valueReference.field.fieldType === 'byte[]'); +for (reference of dtoReferences) { + // if the entity is mapped twice, we should implement the mapping once + if (reference.relationship && !reference.relationship.otherEntity.embedded && !existingMappings.includes(reference.name) && asEntity(reference.relationship.otherEntityNameCapitalized) !== persistClass) { + existingMappings.push(reference.relationship.otherEntity.entityNameCapitalized); + } + } _%> -import <%= packageName %>.domain.<%= asEntity(entityClass) %> -import <%= packageName %>.service.dto.<%= asDto(entityClass) %> +import <%= packageName %>.domain.<%= persistClass %> +import <%= packageName %>.service.dto.<%= dtoClass %> -import org.mapstruct.Mapper -import org.mapstruct.Mapping -import org.mapstruct.Mappings +import org.mapstruct.* <%_ if (uuidMapMethod) { _%> import java.util.Objects; @@ -57,82 +41,140 @@ import java.util.UUID; <%_ } _%> /** - * Mapper for the entity [<%= asEntity(entityClass) %>] and its DTO [<%= asDto(entityClass) %>]. + * Mapper for the entity [<%= persistClass %>] and its DTO [<%= dtoClass %>]. */ -@Mapper(componentModel = "spring", uses = [<%= existingMappings.map(otherEntityNameCapitalized => otherEntityNameCapitalized + 'Mapper::class').join(', ') %>]) +@Mapper(componentModel = "spring", uses = [<%= [...new Set(existingMappings.map(otherEntityNameCapitalized => otherEntityNameCapitalized + 'Mapper::class'))].join(', ') %>]) interface <%= entityClass %>Mapper : - EntityMapper<<%= asDto(entityClass) %>, <%= asEntity(entityClass) %>> { - -<%_ -if (!embedded) { -// entity -> DTO mapping -const entityToDTOMapping = []; -var renMapAnotEnt = false; //Render Mapping Annotation during Entity to DTO conversion? -relationships.forEach((relationship, index) => { - const relationshipType = relationship.relationshipType; - const relationshipName = relationship.relationshipName; - const addComma = index !== 0 ? ',': ''; - const ownerSide = relationship.ownerSide || false; - if (relationshipType === 'many-to-one' || (relationshipType === 'one-to-one' && ownerSide === true)) { - renMapAnotEnt = true; - entityToDTOMapping.push(`Mapping(source = "${relationshipName}.id", target = "${relationship.relationshipFieldName}Id")`); - - if (relationship.otherEntityFieldCapitalized !='Id' && relationship.otherEntityFieldCapitalized !== '') { - entityToDTOMapping.push(`Mapping(source = "${relationshipName}.${relationship.otherEntityField}", target = "${relationship.relationshipFieldName}${relationship.otherEntityFieldCapitalized}")`); + EntityMapper<<%= dtoClass %>, <%= persistClass %>> { +<%_ /***** Basic dto mapping *****/ + if (!embedded) { + const entityToDTOMapping = []; + var renMapAnotEnt = false; //Render Mapping Annotation during Entity to DTO conversion? + for (reference of dtoReferences.filter(reference => reference.relationship && !reference.relationship.otherEntity.embedded)) { + renMapAnotEnt = true; + let qualifiedByName = reference.relationship.otherEntityField; + qualifiedByName = qualifiedByName + (reference.collection ? 'Set' : ''); + entityToDTOMapping.push(`Mapping(target = "${reference.name}", source = "${reference.name}", qualifiedByName = ["${qualifiedByName}"])`) } - } -}); _%> - <%_ if (relationships.length !== 0 && renMapAnotEnt === true) { _%> +_%> + +<%_ for (reference of dtoReferences.filter(reference => reference.field && reference.field.mapstructExpression)) { + renMapAnotEnt = true; + entityToDTOMapping.push(`Mapping( target = "${reference.name}", expression = "${reference.field.mapstructExpression}")`) +} _%> + + <%_ if (renMapAnotEnt === true) { _%> + <%_ if (entityToDTOMapping.length !== 0) { _%> @Mappings( <%- entityToDTOMapping.join(',\n ') %> ) + <%_ } _%> + override fun toDto(s: <%= persistClass %>): <%= dtoClass %> <%_ } _%> - <%_ if (renMapAnotEnt === true) { _%> - override fun toDto(<%= asEntity(entityInstance) %>: <%= asEntity(entityClass) %>): <%= asDto(entityClass) %> +<%_ } _%> + +<%_ /***** Id mapping *****/ +const otherIdReferences = otherDtoReferences.filter(r => !r.relatedReference || r.relatedReference.id); +if (!embedded && otherIdReferences.length > 0) { + if (otherIdReferences.some(r => !r.collection)) { _%> + @Named("<%= primaryKey.name %>") + @BeanMapping(ignoreByDefault = true) + <%_ + let renMapAnotEnt = false; //Render Mapping Annotation during Entity to DTO conversion? + const mapping = []; + for (reference of dtoReferences.filter(reference => reference.id)) { + renMapAnotEnt = true; + mapping.push(`Mapping(target = "${reference.name}", source = "${reference.name}")`); + } + _%> + <%_ if (renMapAnotEnt === true) { _%> + <%_ if (mapping.length !== 0) { _%> + @Mappings( + <%- mapping.join(',\n ') %> + ) + <%_ } _%> + fun toDtoId(<%= persistInstance %>: <%= persistClass %>): <%= dtoClass %> + <%_ } _%> + <%_ } _%> + <%_ if (otherIdReferences.some(r => r.collection)) { _%> + + @Named("<%= primaryKey.name %>Set") + @BeanMapping(ignoreByDefault = true) + <%_ let renMapAnotEnt = false; //Render Mapping Annotation during Entity to DTO conversion? + const oMapping = []; + for (reference of dtoReferences.filter(reference => reference.id)) { + renMapAnotEnt = true; + oMapping.push(`Mapping(target = "${reference.name}", source = "${reference.name}")`); + } + _%> + <%_ if (renMapAnotEnt === true) { _%> + <%_ if (oMapping.length !== 0) { _%> + @Mappings( + <%- oMapping.join(',\n ') %> + ) + <%_ } _%> + fun toDtoIdSet(<%= persistInstance %>: Set<<%= persistClass %>>): Set<<%= dtoClass %>> + <%_ } _%> <%_ } _%> <%_ } _%> + <%_ if (!embedded) { -// DTO -> entity mapping -// var hasOAuthUser = false; // if OAuthUser, use a String id in fromId() method -const dtoToEntityMapping = []; -relationships.forEach((relationship, index) => { - const relationshipType = relationship.relationshipType; - const relationshipName = relationship.relationshipName; - const relationshipNamePlural = relationship.relationshipNamePlural; - const relationshipNameCapitalized = relationship.relationshipNameCapitalized; - const ownerSide = relationship.ownerSide; - const addComma = index !== 0 ? ',': ''; - if (relationshipType === 'many-to-one' || (relationshipType === 'one-to-one' && ownerSide === true)) { - dtoToEntityMapping.push(`Mapping(source = "${relationshipName}Id", target = "${relationshipName}")`); - } else if (relationshipType === 'many-to-many' && ownerSide === false) { - dtoToEntityMapping.push(`Mapping(target = "${relationshipNamePlural}", ignore = true)`); - } else if (relationshipType === 'one-to-many') { - dtoToEntityMapping.push(`Mapping(target = "${relationshipNamePlural}", ignore = true)`); - } else if (relationshipType === 'one-to-one' && ownerSide === false) { - dtoToEntityMapping.push(`Mapping(target = "${relationshipName}", ignore = true)`); + // DTO -> entity mapping + const dtoToEntityMapping = []; + var renMapAnotDto = false; //Render Mapping Annotation during DTO to Entity conversion? + if(primaryKey.ids.length > 1) { + renMapAnotDto = true; + primaryKey.ids.forEach(id => { + dtoToEntityMapping.push(`Mapping(target = "${id.name}", source="${id.nameDotted}")`) + }) } - - if ((relationshipType === 'one-to-many' || relationshipType === 'many-to-many') && fluentMethods) { - dtoToEntityMapping.push(`Mapping(target = "remove${relationshipNameCapitalized}", ignore = true)`); + for (reference of dtoReferences.filter(reference => reference.relationship)) { + if (reference.owned === false) { + renMapAnotDto = true; + dtoToEntityMapping.push(`Mapping(target = "${reference.name}", ignore = true)`); + } + if (reference.collection && fluentMethods) { + renMapAnotDto = true; + dtoToEntityMapping.push(`Mapping(target = "remove${reference.relationship.relationshipNameCapitalized}", ignore = true)`); + } } -}); _ %> - <%_ if (relationships.length !== 0 && renMapAnotEnt === true) { _%> +_%> + <%_ if (renMapAnotDto === true) { _%> + <%_ if (dtoToEntityMapping.length !== 0) { _%> @Mappings( <%- dtoToEntityMapping.join(',\n ') %> ) + <%_ } _%> + override fun toEntity(<%= dtoInstance %>: <%= dtoClass %>): <%= persistClass %> <%_ } _%> - override fun toEntity(<%= asDto(entityInstance) %>: <%= asDto(entityClass) %>): <%= asEntity(entityClass) %> + <%_ /***** Add filtered backreference *****/ + const addedMappers = []; + for (const otherReference of otherDtoReferences.filter(r => r.relatedReference && !r.relatedReference.id)) { + const reference = otherReference.relationship.otherRelationship && otherReference.relationship.otherRelationship.reference; + const collection = otherReference.collection; + const mapperName = otherReference.relationship.otherEntityField + (collection ? 'Set' : ''); + if (addedMappers.includes(mapperName)) continue; + addedMappers.push(mapperName); + const backReferenceDtoClass = collection ? `Set<${dtoClass}>` : dtoClass; + const backReferenceEntityClass = collection ? `Set<${persistClass}>` : persistClass; _%> + + _%> + @Named("<%= mapperName %>") + @BeanMapping(ignoreByDefault = true) + <%_ + let mapping = []; + dtoReferences.filter(r => r.id && r != reference).forEach(r => { + mapping.push(`Mapping(target = "${r.name}", source = "${r.name}")`) + }); + if (otherReference.relationship.relatedField && !otherReference.relationship.relatedField.id) { + mapping.push(`Mapping(target = "${otherReference.relationship.relatedField.reference.name}", source = "${otherReference.relationship.relatedField.reference.name}")`); + } + _%> + fun toDto<%= _.upperFirst(mapperName) %>(<%= persistInstance %>: <%- backReferenceEntityClass %>): <%- backReferenceDtoClass %> + <%_ }; _%> - <%_ if ((databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'couchbase') && !embedded) { _%> - @JvmDefault - fun fromId(id: <%= primaryKeyType %>?) = id?.let { - val <%= asEntity(entityInstance) %> = <%= asEntity(entityClass) %>() - <%= asEntity(entityInstance) %>.id = id - <%= asEntity(entityInstance) %> - } -<%_ } _%> <%_ if (uuidMapMethod) { _%> @JvmDefault fun map(value: UUID) = Objects.toString(value, null) diff --git a/generators/entity-server/templates/src/main/kotlin/package/web/rest/EntityResource.kt.ejs b/generators/entity-server/templates/src/main/kotlin/package/web/rest/EntityResource.kt.ejs index 0fdd37761..303ff02c7 100644 --- a/generators/entity-server/templates/src/main/kotlin/package/web/rest/EntityResource.kt.ejs +++ b/generators/entity-server/templates/src/main/kotlin/package/web/rest/EntityResource.kt.ejs @@ -20,30 +20,21 @@ package <%= packageName %>.web.rest <%_ const viaService = service !== 'no'; - let isUsingMapsId = false; - let mapsIdAssoc; - for (idx in relationships) { - isUsingMapsId = relationships[idx].useJPADerivedIdentifier === true; - if (isUsingMapsId) { - mapsIdAssoc = relationships[idx]; - break; - } - } let manyToManyWithUser = false; - for (idx in relationships) { - if (relationships[idx].otherEntityName === 'user' && relationships[idx].relationshipType === 'many-to-many') { + for (const relationship in relationships) { + if (relationship.otherEntityName === 'user' && relationship.relationshipType === 'many-to-many') { manyToManyWithUser = true; break; } } _%> <%_ if (dto !== 'mapstruct' || service === 'no') { _%> -import <%= packageName %>.domain.<%= asEntity(entityClass) %> +import <%= packageName %>.domain.<%= persistClass %> <%_ } _%> +import <%= packageName %>.repository.<%= entityClass %>Repository <%_ if (service !== 'no') { _%> import <%= packageName %>.service.<%= entityClass %>Service <%_ } else { _%> -import <%= packageName %>.repository.<%= entityClass %>Repository <%_ if (isUsingMapsId === true) { _%> import <%= packageName %>.repository.<%= mapsIdAssoc.otherEntityNameCapitalized %>Repository <%_ } _%> @@ -56,20 +47,20 @@ import <%= packageName %>.repository.UserRepository <%_ } _%> import <%= packageName %>.web.rest.errors.BadRequestAlertException <%_ if (dto === 'mapstruct') { _%> -import <%= packageName %>.service.dto.<%= asDto(entityClass) %> +import <%= packageName %>.service.dto.<%= dtoClass %> <%_ if (service === 'no') { _%> import <%= packageName %>.service.mapper.<%= entityClass %>Mapper <%_ } } _%> <%_ if (jpaMetamodelFiltering) { _%> -import <%= packageName %>.service.dto.<%= entityClass %>Criteria +import <%= packageName %>.service.criteria.<%= entityClass %>Criteria import <%= packageName %>.service.<%= entityClass %>QueryService <%_ } _%> -import io.github.jhipster.web.util.HeaderUtil +import tech.jhipster.web.util.HeaderUtil <%_ if (pagination !== 'no') { _%> -import io.github.jhipster.web.util.PaginationUtil +import tech.jhipster.web.util.PaginationUtil <%_ } _%> -import io.github.jhipster.web.util.<% if (reactive) { %>reactive.<% } %>ResponseUtil +import tech.jhipster.web.util.<% if (reactive) { %>reactive.<% } %>ResponseUtil import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Value <%_ if (pagination !== 'no') { _%> @@ -87,18 +78,18 @@ import org.springframework.web.servlet.support.ServletUriComponentsBuilder <%_ } else { _%> import org.springframework.web.util.UriComponentsBuilder <%_ } _%> -<%_ } else if (reactiveRepositories) { _%> +<%_ } else if (reactive) { _%> import org.springframework.http.HttpStatus <%_ } _%> -<%_ if (reactiveRepositories) { _%> +<%_ if (reactive) { _%> import org.springframework.http.MediaType <%_ } _%> import org.springframework.http.ResponseEntity -<%_ if (!viaService && !saveUserSnapshot) { %> +<%_ if (databaseType === 'sql' && !viaService && (!saveUserSnapshot || isUsingMapsId === true)) { _%> import org.springframework.transaction.annotation.Transactional <%_ } _%> import org.springframework.web.bind.annotation.* -<%_ if (reactiveRepositories) { _%> +<%_ if (reactive) { _%> import org.springframework.web.server.ResponseStatusException import reactor.core.publisher.Flux import reactor.core.publisher.Mono @@ -106,17 +97,23 @@ import reactor.core.publisher.Mono <%_ if (validation) { _%> import javax.validation.Valid +import javax.validation.constraints.NotNull <%_ } _%> import java.net.URI -import java.net.URISyntaxException<% if (isUsingMapsId === true) { %> -import java.util.Objects<% } %> -<%_ if (databaseType === 'cassandra') { _%> +import java.net.URISyntaxException +import java.util.Objects +<%_ if (primaryKey.fields.some(f => f.fieldType === 'UUID')) { _%> import java.util.UUID <%_ } _%> -<%_ if (searchEngine === 'elasticsearch' && !reactive) { _%> +<%_ if ((searchEngine !== false || fieldsContainNoOwnerOneToOne === true) && !reactive) { _%> + <%_ if (!viaService) { _%> import java.util.stream.Collectors + <%_ } _%> + <%_ if (databaseType !== 'sql' || !reactive) { _%> import java.util.stream.StreamSupport - + <%_ } _%> +<%_ } _%> +<%_ if (searchEngine === 'elasticsearch' && !reactive) { _%> import org.elasticsearch.index.query.QueryBuilders.queryStringQuery <%_ } _%> <%_ if (!readOnly) { _%> @@ -130,7 +127,7 @@ _%> private const val ENTITY_NAME = "<%= entityName %>" <%_ } _%> /** - * REST controller for managing [<%= packageName %>.domain.<%= asEntity(entityClass) %>]. + * REST controller for managing [<%= packageName %>.domain.<%= persistClass %>]. */ @RestController @RequestMapping("/api") @@ -139,18 +136,25 @@ private const val ENTITY_NAME = "<%= entityName %>" <%_ } _%> class <%= entityClass %>Resource( <%_ - const instanceType = (dto === 'mapstruct') ? asDto(entityClass) : asEntity(entityClass); - const instanceName = (dto === 'mapstruct') ? asDto(entityInstance) : asEntity(entityInstance); + const instanceType = restClass; + const instanceName = restInstance; const mapper = entityInstance + 'Mapper'; const entityToDtoReference = mapper + '::' + 'toDto'; _%><%- include('../../common/inject_template', {viaService: viaService, constructorName: entityClass + 'Resource', queryService: jpaMetamodelFiltering, isUsingMapsId: isUsingMapsId, mapsIdAssoc: mapsIdAssoc, isController: true}); -%> ) { private val log = LoggerFactory.getLogger(javaClass) - <%_ if (!readOnly) { _%> + + companion object { + <%_ let entityName = entityInstance; + if (clientRootFolder && !skipUiGrouping) { + entityName = _.camelCase(`${clientRootFolder}${entityClass}`); + } _%> + const val ENTITY_NAME = "<%= entityName %>" + } + @Value("\${jhipster.clientApp.name}") private var applicationName: String? = null - <%_ } _%> <%_ if (!readOnly) { _%> /** @@ -163,7 +167,7 @@ _%><%- include('../../common/inject_template', {viaService: viaService, construc @PostMapping("/<%= entityApiUrl %>") fun create<%= entityClass %>(<% if (validation) { %>@Valid <% } %>@RequestBody <%= instanceName %>: <%= instanceType %>): <% if (reactive) { %>Mono<<% } %>ResponseEntity<<%= instanceType %>><% if (reactive) { %>><% } %> { log.debug("REST request to save <%= entityClass %> : $<%= instanceName %>") - if (<%= instanceName %>.id != null) { + if (<%= instanceName %>.<%= primaryKey.name %> != null) { throw BadRequestAlertException( "A new <%= entityInstance %> cannot already have an ID", ENTITY_NAME, "idexists" @@ -182,20 +186,19 @@ _%><%- include('../../common/inject_template', {viaService: viaService, construc } <%_ } _%> <%_ } _%> - <%_ if (databaseType === 'cassandra') { _%> - <%= instanceName %>.id = UUID.randomUUID() + <%_ if (primaryKey.type === 'UUID' && databaseType !== 'sql') { _%> + <%= instanceName %>.<%= primaryKey.name %> = UUID.randomUUID() <%_ } _%> +<%- include('/partials/save_template', {asEntity, asDto, viaService: viaService, returnDirectly: false, isUsingMapsId: isUsingMapsId, mapsIdAssoc: mapsIdAssoc, isController: true, noReturn: false}); -%> <%_ if (!reactive) { _%> -<%- include('../../common/save_template', {asEntity, asDto, viaService: viaService, returnDirectly: false, isUsingMapsId: isUsingMapsId, mapsIdAssoc: mapsIdAssoc, isController: true}); -%> - return ResponseEntity.created(URI("/api/<%= entityApiUrl %>/${result.id}")) - .headers(HeaderUtil.createEntityCreationAlert(applicationName, <%= enableTranslation %>, ENTITY_NAME, result.id<% if (primaryKeyType !== 'String') { %>.toString()<% } %>)) + return ResponseEntity.created(URI("/api/<%= entityApiUrl %>/${result.<%= primaryKey.name %>}")) + .headers(HeaderUtil.createEntityCreationAlert(applicationName, <%= enableTranslation %>, ENTITY_NAME, result.<%= primaryKey.name %><% if (primaryKey.type !== 'String') { %>.toString()<% } %>)) .body(result) <%_ } else { _%> -<%- include('../../common/save_reactive_template', {asEntity, asDto, viaService: viaService, returnDirectly: false}); -%> .map { result -> try { - ResponseEntity.created(URI("/api/<%= entityApiUrl %>/${result.id}")) - .headers(HeaderUtil.createEntityCreationAlert(applicationName, <%= enableTranslation %>, ENTITY_NAME, result.id<% if (primaryKeyType !== 'String') { %>.toString()<% } %>)) + ResponseEntity.created(URI("/api/<%= entityApiUrl %>/${result.<%= primaryKey.name %>}")) + .headers(HeaderUtil.createEntityCreationAlert(applicationName, <%= enableTranslation %>, ENTITY_NAME, result.<%= primaryKey.name %><% if (primaryKey.type !== 'String') { %>.toString()<% } %>)) .body(result) } catch (e: URISyntaxException) { throw RuntimeException(e) @@ -205,20 +208,41 @@ _%><%- include('../../common/inject_template', {viaService: viaService, construc } /** - * `PUT /<%= entityApiUrl %>` : Updates an existing <%= entityInstance %>. + * {@code PUT /<%= entityApiUrl %>/:<%= primaryKey.name %>} : Updates an existing <%= entityInstance %>. * + * @param <%= primaryKey.name %> the id of the <%= instanceName %> to save. * @param <%= instanceName %> the <%= instanceName %> to update. * @return the [ResponseEntity] with status `200 (OK)` and with body the updated <%= instanceName %>, * or with status `400 (Bad Request)` if the <%= instanceName %> is not valid, * or with status `500 (Internal Server Error)` if the <%= instanceName %> couldn't be updated. * @throws URISyntaxException if the Location URI syntax is incorrect. */ - @PutMapping("/<%= entityApiUrl %>") - fun update<%= entityClass %>(<% if (validation) { %>@Valid <% } %>@RequestBody <%= instanceName %>: <%= instanceType %>): <% if (reactive) { %>Mono<<% } %>ResponseEntity<<%= instanceType %>><% if (reactive) { %>><% } %> { - log.debug("REST request to update <%= entityClass %> : $<%= instanceName %>") - if (<%= instanceName %>.id == null) { + @PutMapping("/<%= entityApiUrl %>/{<%= primaryKey.name %>}") + fun update<%= entityClass %>( + @PathVariable(value = "<%= primaryKey.name %>", required = false) <%= primaryKey.name %>: <%= primaryKey.type %>, + <% if (validation) { %>@Valid <% } %>@RequestBody <%= instanceName %>: <%= instanceType %> + ): <% if (reactive) { %>Mono<<% } %>ResponseEntity<<%= instanceType %>><% if (reactive) { %>><% } %> { + log.debug("REST request to update <%= entityClass %> : {}, {}", <%= primaryKey.name %>, <%= instanceName %>) + if (<%= instanceName %>.<%= primaryKey.name %> == null) { throw BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull") } + + if (!Objects.equals(<%= primaryKey.name %>, <%= instanceName %>.<%= primaryKey.name %>)) { + throw BadRequestAlertException("Invalid ID", ENTITY_NAME, "idinvalid") + } + + + <%_ if (!reactive) { _%> + if (!<%= entityInstance %>Repository.existsById(<%= primaryKey.name %>)) { + throw BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound") + } + <%_ } else { _%> + return <%= entityInstance %>Repository.existsById(<%= primaryKey.name %>).flatMap{ + if (!it) { + return@flatMap Mono.error(BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound")) + } + <%_ } _%> + <%_ if (saveUserSnapshot) { %> <%_ if (manyToManyWithUser) { _%> if (<%= instanceName %>.users != null) { @@ -232,26 +256,94 @@ _%><%- include('../../common/inject_template', {viaService: viaService, construc } <%_ } _%> <%_ } _%> +<%- include('/partials/save_template', {asEntity, asDto, viaService: viaService, returnDirectly: false, isUsingMapsId: false, mapsIdAssoc: mapsIdAssoc, noReturn: true}); -%> <%_ if (!reactive) { _%> -<%- include('../../common/save_template', {asEntity, asDto, viaService: viaService, returnDirectly: false, isUsingMapsId: false, mapsIdAssoc: mapsIdAssoc}); -%> return ResponseEntity.ok() .headers( HeaderUtil.createEntityUpdateAlert( applicationName, <%= enableTranslation %>, ENTITY_NAME, - <%= instanceName %>.id<% if (primaryKeyType !== 'String') { %>.toString()<% } %> + <%= instanceName %>.<%= primaryKey.name %><% if (primaryKey.type !== 'String') { %>.toString()<% } %> ) ) .body(result) <%_ } else { _%> -<%- include('../../common/save_reactive_template', {asEntity, asDto, viaService: viaService, returnDirectly: false}); -%> - .switchIfEmpty(Mono.error(ResponseStatusException(HttpStatus.NOT_FOUND))) - .map { result -> ResponseEntity.ok() - .headers(HeaderUtil.createEntityUpdateAlert(applicationName, <%= enableTranslation %>, ENTITY_NAME, result.id<% if (primaryKeyType !== 'String') { %>.toString()<% } %>)) - .body(result) - } + .switchIfEmpty(Mono.error(ResponseStatusException(HttpStatus.NOT_FOUND))) + .map { result -> ResponseEntity.ok() + .headers(HeaderUtil.createEntityUpdateAlert(applicationName, <%= enableTranslation %>, ENTITY_NAME, result.<%= primaryKey.name %><% if (primaryKey.type !== 'String') { %>.toString()<% } %>)) + .body(result) + } + } <%_ } _%> } <%_ } _%> + + /** + * {@code PATCH /<%= entityApiUrl %>/:<%= primaryKey.name %>} : Partial updates given fields of an existing <%= entityInstance %>, field will ignore if it is null + * + * @param <%= primaryKey.name %> the id of the <%= instanceName %> to save. + * @param <%= instanceName %> the <%= instanceName %> to update. + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated <%= instanceName %>, + * or with status {@code 400 (Bad Request)} if the <%= instanceName %> is not valid, + * or with status {@code 404 (Not Found)} if the <%= instanceName %> is not found, + * or with status {@code 500 (Internal Server Error)} if the <%= instanceName %> couldn't be updated. + * @throws URISyntaxException if the Location URI syntax is incorrect. + */ + @PatchMapping(value = ["/<%= entityApiUrl %>/{<%= primaryKey.name %>}"], consumes = ["application/merge-patch+json"]) + @Throws(URISyntaxException::class) + fun partialUpdate<%= entityClass %>( + @PathVariable(value = "<%= primaryKey.name %>", required = false) <%= primaryKey.name %>: <%= primaryKey.type %>, + <% if (validation) { %>@NotNull <% } %>@RequestBody <%= instanceName %>:<%= instanceType %> + ): <% if (reactive) { %>Mono<<% } %>ResponseEntity<<%= instanceType %>><% if (reactive) { %>><% } %> { + log.debug("REST request to partial update <%= entityClass %> partially : {}, {}", <%= primaryKey.name %>, <%= instanceName %>) + if (<%= instanceName %>.<%= primaryKey.name %> == null) { + throw BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull") + } + if (!Objects.equals(<%= primaryKey.name %>, <%= instanceName %>.<%= primaryKey.name %>)) { + throw BadRequestAlertException("Invalid ID", ENTITY_NAME, "idinvalid") + } + + <%_ if (!reactive) { _%> + if (!<%= entityInstance %>Repository.existsById(<%= primaryKey.name %>)) { + throw BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound") + } + <%_ } else { _%> + return <%= entityInstance %>Repository.existsById(<%= primaryKey.name %>).flatMap { + if (!it) { + return@flatMap Mono.error(BadRequestAlertException("Entity not found", ENTITY_NAME, "idnotfound")) + } + <%_ } _%> + + <%_ if (saveUserSnapshot) { _%> + <%_ if (manyToManyWithUser) { _%> + if (<%= instanceName %>.users != null) { + // Save users in case they are new and only exists in gateway + userRepository.saveAll(<%= instanceName %>.users) + } + <%_ } else { _%> + if (<%= instanceName %>.user != null) { + // Save user in case it's new and only exists in gateway + userRepository.save(<%= instanceName %>.user) + } + <%_ } _%> + <%_ } _%> +<%- include('../../common/patch_template', {asEntity, asDto, isService: false, viaService: viaService}); -%> + <%_ if (!reactive) { _%> + return ResponseUtil.wrapOrNotFound( + result, + HeaderUtil.createEntityUpdateAlert(applicationName, <%= enableTranslation %>, ENTITY_NAME, <%= instanceName %>.<%= primaryKey.name %><% if (primaryKey.type !== 'String') { %>.toString()<% } %>) + ) + <%_ } else { _%> + result + .switchIfEmpty(Mono.error(ResponseStatusException(HttpStatus.NOT_FOUND))) + .map { + ResponseEntity.ok() + .headers(HeaderUtil.createEntityUpdateAlert(applicationName, <%= enableTranslation %>, ENTITY_NAME, it.<%= primaryKey.name %><% if (primaryKey.type !== 'String') { %>.toString()<% } %>)) + .body(it) + } + } + <%_ } _%> + } + /** * `GET /<%= entityApiUrl %>` : get all the <%= entityInstancePlural %>. * @@ -261,7 +353,7 @@ _%><%- include('../../common/inject_template', {viaService: viaService, construc * @param request a [ServerHttpRequest] request. <%_ } _%> <%_ } _%> - <%_ if (!jpaMetamodelFiltering && fieldsContainOwnerManyToMany) { _%> + <%_ if (!jpaMetamodelFiltering && relationshipsContainEagerLoad) { _%> * @param eagerload flag to eager load entities from relationships (This is applicable for many-to-many).<% } if (jpaMetamodelFiltering) { %> * @param criteria the criteria which the requested entities should match.<% } else if (fieldsContainNoOwnerOneToOne) { %> * @param filter the filter of the request.<% } %> @@ -271,12 +363,12 @@ _%><%- include('../../common/inject_template', {viaService: viaService, construc @Transactional(readOnly = true)<%_ } _%> <%- include('../../common/get_all_template', {asEntity, asDto, viaService}); -%> - <%_ if (reactiveRepositories && pagination === 'no') { _%> + <%_ if (reactive && pagination === 'no') { _%> /** * `GET /<%= entityApiUrl %>` : get all the <%= entityInstancePlural %> as a stream. * @return the [Flux] of <%= entityInstancePlural %>. */ - @GetMapping(value = ["/<%= entityApiUrl %>"], produces = [MediaType.APPLICATION_STREAM_JSON_VALUE]) + @GetMapping(value = ["/<%= entityApiUrl %>"], produces = [MediaType.APPLICATION_NDJSON_VALUE]) <%_ if (databaseType === 'sql' && isUsingMapsId === true && !viaService) { _%> @Transactional(readOnly = true) <%_ } _%> @@ -300,7 +392,7 @@ _%><%- include('../../common/inject_template', {viaService: viaService, construc <%_ if (databaseType === 'sql' && isUsingMapsId === true && !viaService) { _%> @Transactional(readOnly = true) <%_ } _%> - fun get<%= entityClass %>(@PathVariable id: <%= primaryKeyType %>): <% if (reactive) { %>Mono<<% } %>ResponseEntity<<%= instanceType %>><% if (reactive) { %>><% } %> { + fun get<%= entityClass %>(@PathVariable id: <%= primaryKey.type %>): <% if (reactive) { %>Mono<<% } %>ResponseEntity<<%= instanceType %>><% if (reactive) { %>><% } %> { log.debug("REST request to get <%= entityClass %> : $id")<%- include('../../common/get_template', {asEntity, asDto, viaService, returnDirectly:false}); -%> return ResponseUtil.wrapOrNotFound(<%= instanceName %>) } @@ -315,21 +407,21 @@ _%><%- include('../../common/inject_template', {viaService: viaService, construc <%_ if (reactive) { _%> @ResponseStatus(code = HttpStatus.NO_CONTENT) <%_ } _%> - fun delete<%= entityClass %>(@PathVariable id: <%= primaryKeyType %>): <% if (reactive) { %>Mono<<% } %>ResponseEntity<% if (reactive) { %>><% } %> { + fun delete<%= entityClass %>(@PathVariable id: <%= primaryKey.type %>): <% if (reactive) { %>Mono<<% } %>ResponseEntity<% if (reactive) { %>><% } %> { log.debug("REST request to delete <%= entityClass %> : $id") <%- include('../../common/delete_template', {viaService: viaService, fromResource: true}); -%> <%_ if (!reactive) { _%> return ResponseEntity.noContent() - .headers(HeaderUtil.createEntityDeletionAlert(applicationName, <%= enableTranslation %>, ENTITY_NAME, id<% if (primaryKeyType !== 'String') { %>.toString()<% } %>)).build() + .headers(HeaderUtil.createEntityDeletionAlert(applicationName, <%= enableTranslation %>, ENTITY_NAME, id<% if (primaryKey.type !== 'String') { %>.toString()<% } %>)).build() <%_ } else { _%> <%_ if (databaseType === 'couchbase') { _%> .then(Mono.just(ResponseEntity.noContent() - .headers(HeaderUtil.createEntityDeletionAlert(applicationName, <%= enableTranslation %>, ENTITY_NAME, id<% if (primaryKeyType !== 'String') { %>.toString()<% } %>)).build()) + .headers(HeaderUtil.createEntityDeletionAlert(applicationName, <%= enableTranslation %>, ENTITY_NAME, id<% if (primaryKey.type !== 'String') { %>.toString()<% } %>)).build()) ) <%_ } else { _%> .map { ResponseEntity.noContent() - .headers(HeaderUtil.createEntityDeletionAlert(applicationName, <%= enableTranslation %>, ENTITY_NAME, id<% if (primaryKeyType !== 'String') { %>.toString()<% } %>)).build() + .headers(HeaderUtil.createEntityDeletionAlert(applicationName, <%= enableTranslation %>, ENTITY_NAME, id<% if (primaryKey.type !== 'String') { %>.toString()<% } %>)).build() } <%_ } _%> <%_ } _%> diff --git a/generators/entity-server/templates/src/test/kotlin/package/domain/EntityTest.kt.ejs b/generators/entity-server/templates/src/test/kotlin/package/domain/EntityTest.kt.ejs index cc808e266..6544128d8 100644 --- a/generators/entity-server/templates/src/test/kotlin/package/domain/EntityTest.kt.ejs +++ b/generators/entity-server/templates/src/test/kotlin/package/domain/EntityTest.kt.ejs @@ -21,35 +21,23 @@ package <%= packageName %>.domain import org.junit.jupiter.api.Test import org.assertj.core.api.Assertions.assertThat import <%= packageName %>.web.rest.equalsVerifier -<%_ -let hasOauthUser = false; -for (idx in relationships) { - isUsingMapsId = relationships[idx].useJPADerivedIdentifier === true; - if (isUsingMapsId) { - hasOauthUser = relationships[idx].otherEntityName === 'user' && authenticationType === 'oauth2'; - break; - } -} -_%> -<%_ if (databaseType === 'cassandra' || (databaseType === 'sql' && hasOauthUser === true)) { _%> import java.util.UUID -<%_ } _%> -class <%= entityClass %>Test { +class <%= persistClass %>Test { @Test fun equalsVerifier() { - equalsVerifier(<%= asEntity(entityClass) %>::class) + equalsVerifier(<%= persistClass %>::class) <%_if (!embedded) { _%> - val <%= asEntity(entityInstance) %>1 = <%= asEntity(entityClass) %>() - <%= asEntity(entityInstance) %>1.id = <% if (databaseType === 'sql' && hasOauthUser === true) { %>UUID.randomUUID().toString()<% } else if (databaseType === 'sql') { %>1L<% } else if (databaseType === 'mongodb' || databaseType === 'couchbase') { %>"id1"<% } else if (databaseType === 'cassandra') { %>UUID.randomUUID()<% } %> - val <%= asEntity(entityInstance) %>2 = <%= asEntity(entityClass) %>() - <%= asEntity(entityInstance) %>2.id = <%= asEntity(entityInstance) %>1.id - assertThat(<%= asEntity(entityInstance) %>1).isEqualTo(<%= asEntity(entityInstance) %>2) - <%= asEntity(entityInstance) %>2.id = <% if (databaseType === 'sql' && hasOauthUser === true) { %>UUID.randomUUID().toString()<% } else if (databaseType === 'sql') { %>2L<% } else if (databaseType === 'mongodb' || databaseType === 'couchbase') { %>"id2"<% } else if (databaseType === 'cassandra') { %>UUID.randomUUID()<% } %> - assertThat(<%= asEntity(entityInstance) %>1).isNotEqualTo(<%= asEntity(entityInstance) %>2) - <%= asEntity(entityInstance) %>1.id = null - assertThat(<%= asEntity(entityInstance) %>1).isNotEqualTo(<%= asEntity(entityInstance) %>2) - <%_} _%> + val <%= persistInstance %>1 = <%= persistClass %>() + <%= persistInstance %>1.<%= primaryKey.name %> = <% if (databaseType === 'sql' && hasOauthUser === true) { %>UUID.randomUUID().toString()<% } else if (primaryKey.type === 'Long') { %>1L<% } else if (primaryKey.type === 'String') { %>"id1"<% } else if (primaryKey.type === 'UUID') { %>UUID.randomUUID()<% } %> + val <%= persistInstance %>2 = <%= persistClass %>() + <%= persistInstance %>2.<%= primaryKey.name %> = <%= persistInstance %>1.<%= primaryKey.name %> + assertThat(<%= persistInstance %>1).isEqualTo(<%= persistInstance %>2) + <%= persistInstance %>2.<%= primaryKey.name %> = <% if (databaseType === 'sql' && hasOauthUser === true) { %>UUID.randomUUID().toString()<% } else if (primaryKey.type === 'Long') { %>2L<% } else if (primaryKey.type === 'String') { %>"id2"<% } else if (primaryKey.type === 'UUID') { %>UUID.randomUUID()<% } %> + assertThat(<%= persistInstance %>1).isNotEqualTo(<%= persistInstance %>2) + <%= persistInstance %>1.<%= primaryKey.name %> = null + assertThat(<%= persistInstance %>1).isNotEqualTo(<%= persistInstance %>2) + <%_ } _%> } } diff --git a/generators/entity-server/templates/src/test/kotlin/package/service/dto/EntityDTOTest.kt.ejs b/generators/entity-server/templates/src/test/kotlin/package/service/dto/EntityDTOTest.kt.ejs index 2bf384a6b..a05118889 100644 --- a/generators/entity-server/templates/src/test/kotlin/package/service/dto/EntityDTOTest.kt.ejs +++ b/generators/entity-server/templates/src/test/kotlin/package/service/dto/EntityDTOTest.kt.ejs @@ -22,29 +22,32 @@ import org.junit.jupiter.api.Test import org.assertj.core.api.Assertions.assertThat import <%= packageName %>.web.rest.equalsVerifier <%_ -let id1 = getPrimaryKeyValue(primaryKeyType, databaseType, '1'); -let id2 = getPrimaryKeyValue(primaryKeyType, databaseType, '2'); -_%> -<%_ if (id1.includes('UUID')) { _%> -import java.util.UUID; +let id1; +let id2; +if (!embedded) { + id1 = getPrimaryKeyValue(primaryKey.type, databaseType, '1'); + id2 = getPrimaryKeyValue(primaryKey.type, databaseType, '2'); +} %> +<%_ if (primaryKey && primaryKey.fields.some(field => field.fieldType === 'UUID')) { _%> +import java.util.UUID <%_ } _%> -class <%= asDto(entityClass) %>Test { +class <%= dtoClass %>Test { @Test fun dtoEqualsVerifier(){ - equalsVerifier(<%= asDto(entityClass) %>::class) + equalsVerifier(<%= dtoClass %>::class) <%_if (!embedded) { _%> - val <%= asDto(entityInstance) %>1 = <%= asDto(entityClass) %>() - <%= asDto(entityInstance) %>1.id = <%- id1 %> - val <%= asDto(entityInstance) %>2 = <%= asDto(entityClass) %>() - assertThat(<%= asDto(entityInstance) %>1).isNotEqualTo(<%= asDto(entityInstance) %>2) - <%= asDto(entityInstance) %>2.id = <%= asDto(entityInstance) %>1.id - assertThat(<%= asDto(entityInstance) %>1).isEqualTo(<%= asDto(entityInstance) %>2) - <%= asDto(entityInstance) %>2.id = <%- id2 %> - assertThat(<%= asDto(entityInstance) %>1).isNotEqualTo(<%= asDto(entityInstance) %>2) - <%= asDto(entityInstance) %>1.id = null - assertThat(<%= asDto(entityInstance) %>1).isNotEqualTo(<%= asDto(entityInstance) %>2) + val <%= dtoInstance %>1 = <%= dtoClass %>() + <%= dtoInstance %>1.<%= primaryKey.name %> = <%- id1 %> + val <%= dtoInstance %>2 = <%= dtoClass %>() + assertThat(<%= dtoInstance %>1).isNotEqualTo(<%= dtoInstance %>2) + <%= dtoInstance %>2.<%= primaryKey.name %> = <%= dtoInstance %>1.<%= primaryKey.name %> + assertThat(<%= dtoInstance %>1).isEqualTo(<%= dtoInstance %>2) + <%= dtoInstance %>2.<%= primaryKey.name %> = <%- id2 %> + assertThat(<%= dtoInstance %>1).isNotEqualTo(<%= dtoInstance %>2) + <%= dtoInstance %>1.<%= primaryKey.name %> = null + assertThat(<%= dtoInstance %>1).isNotEqualTo(<%= dtoInstance %>2) <%_ } _%> } } diff --git a/generators/entity-server/templates/src/test/kotlin/package/service/mapper/EntityMapperTest.kt.ejs b/generators/entity-server/templates/src/test/kotlin/package/service/mapper/EntityMapperTest.kt.ejs index a28f20f0e..38032579d 100644 --- a/generators/entity-server/templates/src/test/kotlin/package/service/mapper/EntityMapperTest.kt.ejs +++ b/generators/entity-server/templates/src/test/kotlin/package/service/mapper/EntityMapperTest.kt.ejs @@ -21,11 +21,8 @@ package <%= packageName %>.service.mapper import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.assertj.core.api.Assertions.assertThat -<%_ -let id = getPrimaryKeyValue(primaryKeyType, databaseType, '1'); -_%> -<%_ if (id.includes('UUID')) { _%> -import java.util.UUID; +<%_ if (primaryKey && primaryKey.fields.some(field => field.fieldType === 'UUID')) { _%> +import java.util.UUID <%_ } _%> class <%= entityClass %>MapperTest { @@ -36,13 +33,4 @@ class <%= entityClass %>MapperTest { fun setUp() { <%= entityInstance %>Mapper = <%= entityClass %>MapperImpl() } - - <%_if (!embedded) { _%> - @Test - fun testEntityFromId() { - val id = <%- id %> - assertThat(<%= entityInstance %>Mapper.fromId(id)?.id).isEqualTo(id) - assertThat(<%= entityInstance %>Mapper.fromId(null)).isNull() - } - <%_} _%> } diff --git a/generators/entity-server/templates/src/test/kotlin/package/web/rest/EntityResourceIT.kt.ejs b/generators/entity-server/templates/src/test/kotlin/package/web/rest/EntityResourceIT.kt.ejs index 90b0dccf4..8c116d177 100644 --- a/generators/entity-server/templates/src/test/kotlin/package/web/rest/EntityResourceIT.kt.ejs +++ b/generators/entity-server/templates/src/test/kotlin/package/web/rest/EntityResourceIT.kt.ejs @@ -19,22 +19,33 @@ package <%= packageName %>.web.rest <%_ -let isUsingMapsId = false; -let mapsIdAssoc; + +/** + * Returns a Java generator that randomizes a value. + * + * @param {string} type - Java type + * @returns {string} java primary key value + */ + function getJavaValueGeneratorForType(type) { + if (type === 'String') { + return 'UUID.randomUUID().toString()' + } + if (type === 'UUID') { + return 'UUID.randomUUID()' + } + if (type === 'Long') { + return 'count.incrementAndGet()' + } + throw Error(`Java type ${type} does not have a random generator implemented`) + } + let mapsIdEntity; let mapsIdEntityInstance; let mapsIdRepoInstance; -let hasOauthUser = false; -for (idx in relationships) { - isUsingMapsId = relationships[idx].useJPADerivedIdentifier === true; - if (isUsingMapsId) { - mapsIdAssoc = relationships[idx]; - mapsIdEntity = mapsIdAssoc.otherEntityNameCapitalized; - mapsIdEntityInstance = mapsIdEntity.charAt(0).toLowerCase() + mapsIdEntity.slice(1); - mapsIdRepoInstance = `${mapsIdEntityInstance}Repository`; - hasOauthUser = relationships[idx].otherEntityName === 'user' && authenticationType === 'oauth2'; - break; - } +if (isUsingMapsId) { + mapsIdEntity = mapsIdAssoc.otherEntityNameCapitalized; + mapsIdEntityInstance = mapsIdEntity.charAt(0).toLowerCase() + mapsIdEntity.slice(1); + mapsIdRepoInstance = `${mapsIdEntityInstance}Repository`; } let callBlock = ''; @@ -47,10 +58,18 @@ let saveMethod = 'save'; if (!reactive && databaseType === 'sql') { saveMethod = 'saveAndFlush'; } -let idValue = `${asEntity(entityInstance)}.id`; -if (primaryKeyType === 'Long') { + +let createEntityPrefix = ''; +let createEntityPostfix = ''; +if (databaseType === 'sql' && reactive) { + createEntityPrefix = 'em.insert('; + createEntityPostfix = ').block()'; +} + +let idValue = `${persistInstance}.${primaryKey.name}`; +if (primaryKey.type === 'Long') { idValue = idValue + '?.toInt()'; -} else if (primaryKeyType === 'UUID') { +} else if (primaryKey.type === 'UUID') { idValue = idValue + '.toString()'; } let transactionalAnnotation = ''; @@ -61,24 +80,15 @@ _%> <%_ if (databaseType === 'cassandra') { _%> import <%= packageName %>.AbstractCassandraTest <%_ } _%> -<%_ if (cacheProvider === 'redis') { _%> -import <%= packageName %>.RedisTestContainerExtension -<%_ } _%> -import <%= packageName %>.<%= mainClass %> -<%_ if (authenticationType === 'uaa') { _%> -import <%= packageName %>.config.SecurityBeanOverrideConfiguration -<%_ } _%> -<%_ if (authenticationType === 'oauth2') { _%> -import <%= packageName %>.config.TestSecurityConfiguration -<%_ } _%> -import <%= packageName %>.domain.<%= asEntity(entityClass) %> +import <%= packageName %>.IntegrationTest +import <%= packageName %>.domain.<%= persistClass %> <%_ var imported = []; - for (idx in relationships) { // import entities in required relationships - const relationshipValidate = relationships[idx].relationshipValidate; - const otherEntityNameCapitalized = relationships[idx].otherEntityNameCapitalized; - const isUsingMapsIdL1 = relationships[idx].useJPADerivedIdentifier; - if(imported.indexOf(otherEntityNameCapitalized) === -1 && asEntity(entityClass) !== asEntity(otherEntityNameCapitalized)) { + for (relationship of relationships) { // import entities in required relationships + const relationshipValidate = relationship.relationshipValidate; + const otherEntityNameCapitalized = relationship.otherEntityNameCapitalized; + const isUsingMapsIdL1 = relationship.id; + if(imported.indexOf(otherEntityNameCapitalized) === -1 && persistClass !== asEntity(otherEntityNameCapitalized)) { if ((relationshipValidate !== null && relationshipValidate === true) || jpaMetamodelFiltering || (isUsingMapsIdL1 === true)) { _%> import <%= packageName %>.domain.<%= asEntity(otherEntityNameCapitalized) %> <%_ imported.push(otherEntityNameCapitalized); @@ -87,6 +97,9 @@ import <%= packageName %>.domain.<%= asEntity(otherEntityNameCapitalized) %> import <%= packageName %>.repository.UserRepository <%_ } _%> import <%= packageName %>.repository.<%= entityClass %>Repository +<%_ if (databaseType === 'sql' && reactive) { _%> +import <%= packageName %>.service.EntityManager +<%_ } _%> <%_ if (isUsingMapsId === true && ( dto !== 'mapstruct' && service === 'no')) { _%> import <%= packageName %>.repository.<%= mapsIdAssoc.otherEntityNameCapitalized %>Repository <%_ } _%> @@ -97,25 +110,27 @@ import <%= packageName %>.repository.search.<%= entityClass %>SearchRepository import <%= packageName %>.service.<%= entityClass %>Service <%_ } _%> <%_ if (dto === 'mapstruct') { _%> -import <%= packageName %>.service.dto.<%= asDto(entityClass) %> +import <%= packageName %>.service.dto.<%= dtoClass %> import <%= packageName %>.service.mapper.<%= entityClass %>Mapper <%_ } _%> import <%= packageName %>.web.rest.errors.ExceptionTranslator <%_ if (jpaMetamodelFiltering) { _%> -import <%= packageName %>.service.dto.<%= entityClass %>Criteria -import <%= packageName %>.service.<%= entityClass %>QueryService +import <%= packageName %>.service.criteria.<%= entityClass %>Criteria <%_ } _%> import kotlin.test.assertNotNull +<%_ if (databaseType === 'sql' && reactive) { _%> +import org.junit.jupiter.api.AfterEach +<%_ } _%> import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test -<%_ if (cacheProvider === 'redis' || (searchEngine === 'elasticsearch' || fieldsContainOwnerManyToMany === true) || databaseType === 'neo4j') { _%> -import org.mockito.Mock +<%_ if (searchEngine === 'elasticsearch' || fieldsContainOwnerManyToMany || cacheProvider === 'redis' || databaseType === 'neo4j' || reactiveSqlTestContainers) { _%> import org.junit.jupiter.api.extension.Extensions import org.junit.jupiter.api.extension.ExtendWith import org.mockito.junit.jupiter.MockitoExtension <%_ } _%> +import org.mockito.Mock import org.mockito.MockitoAnnotations import org.springframework.beans.factory.annotation.Autowired <%_ if (!reactive) { _%> @@ -123,8 +138,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock <%_ } else { _%> import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient <%_ } _%> -import org.springframework.boot.test.context.SpringBootTest -<%_ if (searchEngine === 'elasticsearch' && pagination !== 'no' || fieldsContainOwnerManyToMany) { _%> +<%_ if (searchEngine === 'elasticsearch' && pagination !== 'no' || relationshipsContainEagerLoad) { _%> import org.springframework.data.domain.PageImpl <%_ } _%> <%_ if (searchEngine === 'elasticsearch' && pagination !== 'no') { _%> @@ -137,7 +151,7 @@ import org.springframework.security.core.context.SecurityContextHolder import org.springframework.security.test.context.TestSecurityContextHolder <%_ } _%> import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter -<%_ if (reactiveRepositories) { _%> +<%_ if (reactive) { _%> import org.springframework.test.web.reactive.server.WebTestClient <%_ } _%> <%_ if (!reactive) { _%> @@ -145,31 +159,52 @@ import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.setup.MockMvcBuilders <%_ } _%> import org.springframework.security.test.context.support.WithMockUser -<%_ if (databaseType === 'sql') { _%> +<%_ if (databaseType === 'sql' && !reactive) { _%> import org.springframework.transaction.annotation.Transactional <%_ } _%> <%_ if (fieldsContainBlob === true) { _%> import org.springframework.util.Base64Utils <%_ } _%> -<%_ if (reactive && (fieldsContainOwnerManyToMany === true || searchEngine === 'elasticsearch')) { _%> +<%_ if (reactive && (relationshipsContainEagerLoad || searchEngine === 'elasticsearch')) { _%> import reactor.core.publisher.Flux import reactor.core.publisher.Mono <%_ } _%> import org.springframework.validation.Validator -<%_ if (databaseType === 'sql') { _%> -import javax.persistence.EntityManager<% } %><% if (fieldsContainBigDecimal === true) { %> -import java.math.BigDecimal<% } %><% if (fieldsContainBlob === true && databaseType === 'cassandra') { %> -import java.nio.ByteBuffer<% } %><% if (reactiveRepositories || fieldsContainDuration === true) { %> -import java.time.Duration<% } %><% if (fieldsContainLocalDate === true) { %> -import java.time.LocalDate<% } %><% if (fieldsContainInstant === true || fieldsContainZonedDateTime === true) { %> -import java.time.Instant<% } %><% if (fieldsContainZonedDateTime === true) { %> +<%_ if (databaseType === 'sql' && !reactive) { _%> +import javax.persistence.EntityManager +<%_ } _%> +<%_ if (fieldsContainBigDecimal === true) { _%> +import java.math.BigDecimal +<%_ } _%> +<%_ if (fieldsContainBlob === true && databaseType === 'cassandra') { _%> +import java.nio.ByteBuffer +<%_ } _%> +<%_ if (reactive || fieldsContainDuration === true) { _%> +import java.time.Duration +<%_ } _%> +<%_ if (fieldsContainLocalDate === true) { _%> +import java.time.LocalDate +<%_ } _%> +<%_ if (fieldsContainInstant === true || fieldsContainZonedDateTime === true) { _%> +import java.time.Instant +<%_ } _%> +<%_ if (fieldsContainZonedDateTime === true) { _%> import java.time.ZonedDateTime -import java.time.ZoneOffset<% } %><% if (fieldsContainLocalDate === true || fieldsContainZonedDateTime === true) { %> -import java.time.ZoneId<% } %><% if (fieldsContainInstant === true) { %> -import java.time.temporal.ChronoUnit<% } %> -<%_ if (databaseType === 'cassandra' || fieldsContainUUID === true || (databaseType === 'sql' && hasOauthUser === true)) { _%> +import java.time.ZoneOffset +<%_ } _%> +<%_ if (fieldsContainLocalDate === true || fieldsContainZonedDateTime === true) { _%> +import java.time.ZoneId +<%_ } _%> +<%_ if (fieldsContainInstant === true) { _%> +import java.time.temporal.ChronoUnit +<%_ } _%> +<%_ if (fieldsContainUUID || primaryKey.type === 'String' || otherEntityPrimaryKeyTypes.includes('UUID')) { _%> import java.util.UUID <%_ } _%> +<%_ if (!embedded && primaryKey.fields.some(field => field.fieldType === 'Long')) { _%> +import java.util.Random +import java.util.concurrent.atomic.AtomicLong +<%_ } _%> import org.assertj.core.api.Assertions.assertThat <%_ if (searchEngine === 'elasticsearch' && !reactive) { _%> @@ -186,37 +221,26 @@ import org.springframework.security.test.web.reactive.server.SecurityMockServerC import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf <%_ } _%> <%_ } _%> -<%_ if (searchEngine === 'elasticsearch' || fieldsContainOwnerManyToMany === true) { _%> +<%_ if (searchEngine === 'elasticsearch' || relationshipsContainEagerLoad) { _%> import org.mockito.ArgumentMatchers.* -import org.mockito.Mockito.`when` -import org.mockito.Mockito.reset -import org.mockito.Mockito.times -import org.mockito.Mockito.verify +import org.mockito.Mockito.* <%_ } _%> <%_ if (!reactive) { _%> -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put -import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content -import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath -import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.* +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.* <%_ } _%> -<%_ for (idx in fields) { if (fields[idx].fieldIsEnum === true) { _%>import <%= packageName %>.domain.enumeration.<%= fields[idx].fieldType %> +<%_ for (const field of fields.filter(field => !field.transient)) { if (field.fieldIsEnum === true) { _%>import <%= packageName %>.domain.enumeration.<%= field.fieldType %> <%_ } } _%> /** * Integration tests for the [<%= entityClass %>Resource] REST controller. - * - * @see <%= entityClass %>Resource */ -<%_ if (authenticationType === 'oauth2') { _%> -@SpringBootTest(classes = [<%= mainClass %>::class, TestSecurityConfiguration::class]) -<%_ } else if (authenticationType === 'uaa' && applicationType !== 'uaa') { _%> -@SpringBootTest(classes = [SecurityBeanOverrideConfiguration::class, <%= mainClass %>::class]) -<%_ } else { _%> -@SpringBootTest(classes = [<%= mainClass %>::class]) +@IntegrationTest +<%_ if (cacheProvider === 'redis' || searchEngine === 'elasticsearch' || fieldsContainOwnerManyToMany === true) { _%> +@Extensions( + ExtendWith(MockitoExtension::class) +) <%_ } _%> <%_ if (!reactive) { _%> @AutoConfigureMockMvc @@ -224,21 +248,7 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status @AutoConfigureWebTestClient <%_ } _%> @WithMockUser -<%_ if (cacheProvider === 'redis' || (searchEngine === 'elasticsearch' || fieldsContainOwnerManyToMany === true) || databaseType === 'neo4j') { _%> -@Extensions( - <%_ if (cacheProvider === 'redis') { _%> - ExtendWith(RedisTestContainerExtension::class), - ExtendWith(MockitoExtension::class)<% if (databaseType === 'neo4j') { %>,<% } %> - <%_ } else if (searchEngine === 'elasticsearch' || fieldsContainOwnerManyToMany === true) { _%> - ExtendWith(MockitoExtension::class)<% if (databaseType === 'neo4j') { %>,<% } %> - <%_ } _%> - <%_ if (databaseType === 'neo4j') { _%> - ExtendWith(AbstractNeo4jIT::class) - <%_ } _%> -) -<%_ } _%> class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassandraTest() <% } %> { - @Autowired private lateinit var <%= entityInstance %>Repository: <%= entityClass %>Repository <%_ if (isUsingMapsId === true && ( dto !== 'mapstruct' && service === 'no')) { _%> @@ -265,9 +275,6 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab @Mock private lateinit var <%= entityInstance %>ServiceMock: <%= entityClass %>Service <%_ } _%> - - @Autowired - private lateinit var <%= entityInstance %>Service: <%= entityClass %>Service <%_ } if (searchEngine === 'elasticsearch') { _%> /** @@ -278,11 +285,6 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab @Autowired private lateinit var mock<%= entityClass %>SearchRepository: <%= entityClass %>SearchRepository <%_ } _%> - <%_ if (jpaMetamodelFiltering) { _%> - - @Autowired - private lateinit var <%= entityInstance %>QueryService: <%= entityClass %>QueryService - <%_ } _%> <%_ if (!reactive) { _%> @Autowired @@ -298,14 +300,15 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab private lateinit var validator: Validator <%_ } _%> -<%_ if (databaseType === 'sql') { _%> + <%_ if (databaseType === 'sql') { _%> @Autowired private lateinit var em: EntityManager -<%_ } _%> + <%_ } _%> <%_ if (!reactive) { _%> + @Autowired private lateinit var rest<%= entityClass %>MockMvc: MockMvc <%_ } else { _%> @@ -313,41 +316,32 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab private lateinit var webTestClient: WebTestClient <%_ } _%> - private lateinit var <%= asEntity(entityInstance) %>: <%= asEntity(entityClass) %> + private lateinit var <%= persistInstance %>: <%= persistClass %> - <%_ if (reactive && testsNeedCsrf) { _%> - @BeforeEach - fun setupCsrf() { - webTestClient = webTestClient.mutateWith(csrf()); + <%_ if (databaseType === 'sql' && reactive) { _%> + @AfterEach + fun cleanup() { + deleteEntities(em) } <%_ } _%> - - <%_ if (!reactive) { _%> + <%_ if (reactive && testsNeedCsrf) { _%> @BeforeEach - fun setup() { - MockitoAnnotations.initMocks(this) - <%_ if (service !== 'no') { _%> - val <%= entityInstance %>Resource = <%= entityClass %>Resource(<%= entityInstance %>Service<% if (jpaMetamodelFiltering) { %>, <%= entityInstance %>QueryService<% } %><% if (saveUserSnapshot) { %>, userRepository<% } %>) - <%_ } else { _%> - val <%= entityInstance %>Resource = <%= entityClass %>Resource(<%= entityInstance %>Repository<% if (dto === 'mapstruct') { %>, <%= entityInstance %>Mapper<% } %><% if (searchEngine === 'elasticsearch') { %>, mock<%= entityClass %>SearchRepository<% } %><% if (saveUserSnapshot) { %>, userRepository<% } %><% if (isUsingMapsId === true && dto !== 'mapstruct') { %>, <%= mapsIdRepoInstance _%> <% } %>) - <%_ } _%> - this.rest<%= entityClass %>MockMvc = MockMvcBuilders.standaloneSetup(<%= entityInstance %>Resource) - .setCustomArgumentResolvers(pageableArgumentResolver) - .setControllerAdvice(exceptionTranslator) - .setConversionService(createFormattingConversionService()) - .setMessageConverters(jacksonMessageConverter) - .setValidator(validator).build() + fun setupCsrf() { + webTestClient = webTestClient.mutateWith(csrf()) } - <%_ } _%> + <%_ } _%> @BeforeEach fun initTest() { - <%_ if (databaseType === 'mongodb' || databaseType === 'couchbase' || databaseType === 'cassandra' || databaseType === 'neo4j' ) { _%> + <%_ if (databaseType === 'mongodb' || databaseType === 'couchbase' || databaseType === 'cassandra' || databaseType === 'neo4j') { _%> <%= entityInstance %>Repository.deleteAll()<%= callBlock %> <%_ } _%> - <%= asEntity(entityInstance) %> = createEntity(<% if (databaseType === 'sql') { %>em<% } %>) + <%_ if (databaseType === 'sql' && reactive) { _%> + deleteEntities(em) + <%_ } _%> + <%= persistInstance %> = createEntity(<% if (databaseType === 'sql') { %>em<% } %>) } <%_ if (!readOnly) { _%> @@ -363,45 +357,45 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab // Create the <%= entityClass %> <%_ if (dto === 'mapstruct') { _%> - val <%= asDto(entityInstance) %> = <%= entityInstance %>Mapper.toDto(<%= asEntity(entityInstance) %>) + val <%= dtoInstance %> = <%= entityInstance %>Mapper.toDto(<%= persistInstance %>) <%_ } _%> <%_ if (!reactive) { _%> rest<%= entityClass %>MockMvc.perform( - post("/api/<%= entityApiUrl %>") + post(ENTITY_API_URL)<% if (testsNeedCsrf) { %>.with(csrf())<% }%> .contentType(MediaType.APPLICATION_JSON) - .content(convertObjectToJsonBytes(<%=(dto === 'mapstruct' ? asDto(entityInstance) : asEntity(entityInstance))%>)) + .content(convertObjectToJsonBytes(<%= restInstance %>)) ).andExpect(status().isCreated) <%_ } else { _%> - webTestClient.post().uri("/api/<%= entityApiUrl %>") + webTestClient.post().uri(ENTITY_API_URL) .contentType(MediaType.APPLICATION_JSON) - .bodyValue(convertObjectToJsonBytes(<%= (dto === 'mapstruct' ? asDto(entityInstance) : asEntity(entityInstance))%>)) + .bodyValue(convertObjectToJsonBytes(<%= restInstance %>)) .exchange() .expectStatus().isCreated <%_ } _%> // Validate the <%= entityClass %> in the database <%_ if (databaseType === 'couchbase') { _%> - SecurityContextHolder.setContext(TestSecurityContextHolder.getContext()); + SecurityContextHolder.setContext(TestSecurityContextHolder.getContext()) <%_ } _%> val <%= entityInstance %>List = <%= entityInstance %>Repository.findAll()<%= callListBlock %> assertThat(<%= entityInstance %>List).hasSize(databaseSizeBeforeCreate + 1) - <%_ if ( fields.length>0 || searchEngine === 'elasticsearch') { _%> val test<%= entityClass %> = <%= entityInstance %>List[<%= entityInstance %>List.size - 1] - <%_ } _%> - <%_ for (idx in fields) { if (fields[idx].fieldType === 'ZonedDateTime') { _%> - assertThat(test<%= entityClass %>.<%=fields[idx].fieldName%>).isEqualTo(<%='DEFAULT_' + fields[idx].fieldNameUnderscored.toUpperCase()%>) - <%_ } else if ((fields[idx].fieldType === 'byte[]' || fields[idx].fieldType === 'ByteBuffer') && fields[idx].fieldTypeBlobContent !== 'text') { _%> - assertThat(test<%= entityClass %>.<%=fields[idx].fieldName%>).isEqualTo(<%='DEFAULT_' + fields[idx].fieldNameUnderscored.toUpperCase()%>) - assertThat(test<%= entityClass %>.<%=fields[idx].fieldName%>ContentType).isEqualTo(<%='DEFAULT_' + fields[idx].fieldNameUnderscored.toUpperCase()%>_CONTENT_TYPE) - <%_ } else if (fields[idx].fieldType.toLowerCase() === 'boolean') { _%> - assertThat(test<%= entityClass %>.<%=fields[idx].fieldName%>).isEqualTo(<%='DEFAULT_' + fields[idx].fieldNameUnderscored.toUpperCase()%>) + + <%_ for (const field of fields.filter(field => !field.id && !field.transient)) { + if (field.fieldType === 'ZonedDateTime') { _%> + assertThat(test<%= entityClass %>.<%=field.fieldName%>).isEqualTo(<%='DEFAULT_' + field.fieldNameUnderscored.toUpperCase()%>) + <%_ } else if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { _%> + assertThat(test<%= entityClass %>.<%=field.fieldName%>).isEqualTo(<%='DEFAULT_' + field.fieldNameUnderscored.toUpperCase()%>) + assertThat(test<%= entityClass %>.<%=field.fieldName%>ContentType).isEqualTo(<%='DEFAULT_' + field.fieldNameUnderscored.toUpperCase()%>_CONTENT_TYPE) + <%_ } else if (field.fieldType === 'BigDecimal') { _%> + assertThat(test<%= entityClass %>.<%=field.fieldName%>?.stripTrailingZeros()).isEqualTo(<%='DEFAULT_' + field.fieldNameUnderscored.toUpperCase()%>.stripTrailingZeros()) <%_ } else { _%> - assertThat(test<%= entityClass %>.<%=fields[idx].fieldName%>).isEqualTo(<%='DEFAULT_' + fields[idx].fieldNameUnderscored.toUpperCase()%>) + assertThat(test<%= entityClass %>.<%=field.fieldName%>).isEqualTo(<%='DEFAULT_' + field.fieldNameUnderscored.toUpperCase()%>) <%_ }} _%> <%_ if (isUsingMapsId === true) { _%> // Validate the id for MapsId, the ids must be same - assertThat(test<%= entityClass %>.id).isEqualTo(test<%= entityClass %>.<%= mapsIdEntityInstance %>?.id) + assertThat(test<%= entityClass %>.<%= primaryKey.name %>).isEqualTo(test<%= entityClass %>.<%= mapsIdEntityInstance %>?.<%= primaryKey.name %>) <%_ } _%> <%_ if (searchEngine === 'elasticsearch') { _%> @@ -413,37 +407,45 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab } @Test<%= transactionalAnnotation %> + @Throws(Exception::class) fun create<%= entityClass %>WithExistingId() { - val databaseSizeBeforeCreate = <%= entityInstance %>Repository.findAll()<%= callListBlock %>.size - // Create the <%= entityClass %> with an existing ID - <%= asEntity(entityInstance) %>.id = <% if (databaseType === 'sql' && hasOauthUser === true) { %>UUID.randomUUID().toString()<% } else if (databaseType === 'sql') { %>1L<% } else if (databaseType === 'mongodb' || databaseType === 'couchbase') { %>"existing_id"<% } else if (databaseType === 'cassandra') { %>UUID.randomUUID()<% } %> + <%_ if (primaryKey.type === 'UUID' && databaseType === 'sql') { _%> + <%= entityInstance %>Repository.<%= saveMethod %>(<%= persistInstance %>)<%= callBlock %> + <%_ } else { _%> + <%= persistInstance %>.<%= primaryKey.name %> = <% if (primaryKey.type === 'UUID') { %>UUID.randomUUID()<% } else if (primaryKey.type === 'Long') { %>1L<% } else { %>"existing_id"<% } %> + <%_ } _%> <%_ if (dto === 'mapstruct') { _%> - val <%= asDto(entityInstance) %> = <%= entityInstance %>Mapper.toDto(<%= asEntity(entityInstance) %>) + val <%= dtoInstance %> = <%= entityInstance %>Mapper.toDto(<%= persistInstance %>) <%_ } _%> + val databaseSizeBeforeCreate = <%= entityInstance %>Repository.findAll()<%= callListBlock %>.size + // An entity with an existing ID cannot be created, so this API call must fail <%_ if (!reactive) { _%> rest<%= entityClass %>MockMvc.perform( - post("/api/<%= entityApiUrl %>") + post(ENTITY_API_URL)<% if (testsNeedCsrf) { %>.with(csrf())<% }%> .contentType(MediaType.APPLICATION_JSON) - .content(convertObjectToJsonBytes(<%=(dto === 'mapstruct' ? asDto(entityInstance) : asEntity(entityInstance))%>)) + .content(convertObjectToJsonBytes(<%= restInstance %>)) ).andExpect(status().isBadRequest) <%_ } else { _%> - webTestClient.post().uri("/api/<%= entityApiUrl %>") + webTestClient.post().uri(ENTITY_API_URL) .contentType(MediaType.APPLICATION_JSON) - .bodyValue(convertObjectToJsonBytes(<%= (dto === 'mapstruct' ? asDto(entityInstance) : asEntity(entityInstance))%>)) + .bodyValue(convertObjectToJsonBytes(<%= restInstance %>)) .exchange() .expectStatus().isBadRequest <%_ } _%> // Validate the <%= entityClass %> in the database + <%_ if (databaseType === 'couchbase') { _%> + SecurityContextHolder.setContext(TestSecurityContextHolder.getContext()) + <%_ } _%> val <%= entityInstance %>List = <%= entityInstance %>Repository.findAll()<%= callListBlock %> assertThat(<%= entityInstance %>List).hasSize(databaseSizeBeforeCreate) <%_ if (searchEngine === 'elasticsearch') { _%> // Validate the <%= entityClass %> in Elasticsearch - verify(mock<%= entityClass %>SearchRepository, times(0)).save(<%= asEntity(entityInstance) %>) + verify(mock<%= entityClass %>SearchRepository, times(0)).save(<%= persistInstance %>) <%_ } _%> } @@ -452,90 +454,99 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab @Throws(Exception::class) fun update<%= entityClass %>MapsIdAssociationWithNewId() { // Initialize the database -<%_ if (service !== 'no' && dto !== 'mapstruct') { _%> - <%= entityInstance %>Service.save(<%= asEntity(entityInstance) %>) -<%_ } else { _%> - <%= entityInstance %>Repository.<%= saveMethod %>(<%= asEntity(entityInstance) %>) -<%_ } _%> + <%= entityInstance %>Repository.<%= saveMethod %>(<%= persistInstance %>)<%= callBlock %> <%_ const alreadyGeneratedEntities = []; _%> - val databaseSizeBeforeCreate = <%= entityInstance %>Repository.findAll().size + val databaseSizeBeforeCreate = <%= entityInstance %>Repository.findAll()<%= callListBlock %>.size - <%_ for (idx in relationships) { - const relationshipValidate = relationships[idx].relationshipValidate; - const otherEntityName = relationships[idx].otherEntityName; - const otherEntityNameCapitalized = relationships[idx].otherEntityNameCapitalized; - const mapsIdUse = relationships[idx].useJPADerivedIdentifier; + <%_ for (relationship of relationships) { + const relationshipValidate = relationship.relationshipValidate; + const otherEntityName = relationship.otherEntityName; + const otherEntityNameCapitalized = relationship.otherEntityNameCapitalized; + const mapsIdUse = relationship.id; if (mapsIdUse === true) { _%> // Add a new parent entity <%_ if (alreadyGeneratedEntities.indexOf(otherEntityName) == -1) { _%> - val <%= otherEntityName %> = <%= otherEntityNameCapitalized %>ResourceIT.createEntity(em) + val <%= otherEntityName %> = <%= otherEntityNameCapitalized %>ResourceIT.create<% if (otherEntityName !== 'user') { _%>Updated<%_ } %>Entity(<% if (databaseType === 'sql') { %>em<% } %>) + <%_ if (databaseType === 'sql' && !reactive) { _%> em.persist(<%= otherEntityName %>) em.flush() <%_ } _%> + <%_ } _%> <%_ alreadyGeneratedEntities.push(otherEntityName) _%> <%_ } break; } _%> // Load the <%= entityInstance %> - val updated<%= asEntity(entityClass) %> = <%= entityInstance %>Repository.findById(<%= asEntity(entityInstance) %>.id).get()<% if (databaseType === 'sql') { %> - // Disconnect from session so that the updates on updated<%= asEntity(entityClass) %> are not directly saved in db - em.detach(updated<%= asEntity(entityClass) %>)<% } %> + val updated<%= persistClass %> = <%= entityInstance %>Repository.findById(<%= persistInstance %>.<%= primaryKey.name %>)<%= reactive ? '.block()' : '.get()' %> + assertThat(updated<%= persistClass %>).isNotNull<% if (databaseType === 'sql' && !reactive) { %> + // Disconnect from session so that the updates on updated<%= persistClass %> are not directly saved in db + em.detach(updated<%= persistClass %>)<% } %> // Update the <%= mapsIdEntity %> with new association value - updated<%= asEntity(entityClass) %>.<%= mapsIdEntityInstance %> = <%= alreadyGeneratedEntities.pop() %> + updated<%= persistClass %>.<%= mapsIdEntityInstance %> = <%= alreadyGeneratedEntities.pop() %> <%_ if (dto === 'mapstruct') { _%> - val updated<%= asDto(entityClass) %> = <%= entityInstance %>Mapper.toDto(updated<%= asEntity(entityClass) %>) + val updated<%= dtoClass %> = <%= entityInstance %>Mapper.toDto(updated<%= persistClass %>) + assertThat(updated<%= dtoClass %>).isNotNull <%_ } _%> // Update the entity - rest<%= entityClass %>MockMvc.perform(put("/api/<%= entityApiUrl %>") + <%_ if (reactive) { _%> + webTestClient.put().uri(ENTITY_API_URL_ID, <%_ if (dto === 'mapstruct') { _%>updated<%= dtoClass %> <%_ } else { _%> updated<%= persistClass %> <%_ } _%>.<%= primaryKey.name %>) + .contentType(MediaType.APPLICATION_JSON) + .bodyValue(convertObjectToJsonBytes(<%_ if (dto === 'mapstruct') { _%>updated<%= dtoClass %> <%_ } else { _%> updated<%= persistClass %> <%_ } _%>)) + .exchange() + .expectStatus().isOk + <%_ } else { _%> + rest<%= entityClass %>MockMvc.perform(put(ENTITY_API_URL_ID, <%_ if (dto === 'mapstruct') { _%>updated<%= dtoClass %> <%_ } else { _%> updated<%= persistClass %> <%_ } _%>.<%= primaryKey.name %>)<% if (testsNeedCsrf) { %>.with(csrf())<% }%> .contentType(MediaType.APPLICATION_JSON) - .content(convertObjectToJsonBytes(<%_ if (dto === 'mapstruct') { _%>updated<%= asDto(entityClass) %> <%_ } else { _%> updated<%= asEntity(entityClass) %> <%_ } _%>))) + .content(convertObjectToJsonBytes(<%_ if (dto === 'mapstruct') { _%>updated<%= dtoClass %> <%_ } else { _%> updated<%= persistClass %> <%_ } _%>))) .andExpect(status().isOk) + <%_ } _%> // Validate the <%= entityClass %> in the database + <%_ if (databaseType === 'couchbase') { _%> + SecurityContextHolder.setContext(TestSecurityContextHolder.getContext()) + <%_ } _%> val <%= entityInstance %>List = <%= entityInstance %>Repository.findAll()<%= callListBlock %> assertThat(<%= entityInstance %>List).hasSize(databaseSizeBeforeCreate) - val test<%= entityClass %> = <%= entityInstance %>List.get(<%= entityInstance %>List.size - 1) + val test<%= entityClass %> = <%= entityInstance %>List[<%= entityInstance %>List.size - 1] // Validate the id for MapsId, the ids must be same // Uncomment the following line for assertion. However, please note that there is a known issue and uncommenting will fail the test. // Please look at https://github.com/jhipster/generator-jhipster/issues/9100. You can modify this test as necessary. - // assertThat(test<%= entityClass %>.id).isEqualTo(test<%= entityClass %>.<%= mapsIdEntityInstance %>?.id) + // assertThat(test<%= entityClass %>.<%= primaryKey.name %>).isEqualTo(test<%= entityClass %>.<%= mapsIdEntityInstance %>?.<%= primaryKey.name %>) <%_ if (searchEngine === 'elasticsearch') { _%> + // Validate the <%= entityClass %> in Elasticsearch - <%_ if (service !== 'no' && dto !== 'mapstruct') { _%> - verify(mock<%= entityClass %>SearchRepository, times(2)).save(<%= asEntity(entityInstance) %>) - <%_ } else { _%> - verify(mock<%= entityClass %>SearchRepository, times(1)).save(<%= asEntity(entityInstance) %>) - <%_ } _%> + verify(mock<%= entityClass %>SearchRepository).save(<%= persistInstance %>) <%_ } _%> } <%_ } _%> -<% for (idx in fields) { %><% if (fields[idx].fieldValidate === true) { +<% for (field of fields.filter(field => !field.id && !field.transient)) { %><% if (field.fieldValidate === true) { let required = false; - if (fields[idx].fieldType !== 'byte[]' && fields[idx].fieldValidate === true && fields[idx].fieldValidateRules.includes('required')) { + if (field.fieldType !== 'byte[]' && field.fieldValidate === true && field.fieldValidateRules.includes('required')) { required = true; } if (required) { %> @Test<%= transactionalAnnotation %> - fun check<%= fields[idx].fieldInJavaBeanMethod %>IsRequired() { + @Throws(Exception::class) + fun check<%= field.fieldInJavaBeanMethod %>IsRequired() { val databaseSizeBeforeTest = <%= entityInstance %>Repository.findAll()<%= callListBlock %>.size // set the field null - <%= asEntity(entityInstance) %>.<%= fields[idx].fieldName %> = null + <%= persistInstance %>.<%= field.fieldName %> = null // Create the <%= entityClass %>, which fails.<% if (dto === 'mapstruct') { %> - val <%= asDto(entityInstance) %> = <%= entityInstance %>Mapper.toDto(<%= asEntity(entityInstance) %>)<% } %> + val <%= dtoInstance %> = <%= entityInstance %>Mapper.toDto(<%= persistInstance %>)<% } %> <%_ if (!reactive) { _%> rest<%= entityClass %>MockMvc.perform( - post("/api/<%= entityApiUrl %>") + post(ENTITY_API_URL)<% if (testsNeedCsrf) { %>.with(csrf())<% }%> .contentType(MediaType.APPLICATION_JSON) - .content(convertObjectToJsonBytes(<%=(dto === 'mapstruct' ? asDto(entityInstance) : asEntity(entityInstance))%>)) + .content(convertObjectToJsonBytes(<%= restInstance %>)) ).andExpect(status().isBadRequest) <%_ } else { _%> - webTestClient.post().uri("/api/<%= entityApiUrl %>") + webTestClient.post().uri(ENTITY_API_URL) .contentType(MediaType.APPLICATION_JSON) - .bodyValue(convertObjectToJsonBytes(<%= (dto === 'mapstruct' ? asDto(entityInstance) : asEntity(entityInstance))%>)) + .bodyValue(convertObjectToJsonBytes(<%= restInstance %>)) .exchange() .expectStatus().isBadRequest <%_ } _%> @@ -548,60 +559,62 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab } <% } } } %> <%_ } _%> -<%_ if (reactiveRepositories && pagination === 'no') { _%> +<%_ if (reactive && pagination === 'no') { _%> + @Test fun getAll<%= entityClassPlural %>AsStream() { // Initialize the database - <%_ if (databaseType === 'cassandra') { _%> - <%= asEntity(entityInstance) %>.id = UUID.randomUUID() + <%_ if (primaryKey.type === 'UUID' && databaseType !== 'sql') { _%> + <%= persistInstance %>.<%= primaryKey.name %> = UUID.randomUUID() <%_ } _%> - <%= entityInstance %>Repository.save(<%= asEntity(entityInstance) %>)<%= callBlock %> + <%= entityInstance %>Repository.save(<%= persistInstance %>)<%= callBlock %> - val <%= entityInstance %>List = webTestClient.get().uri("/api/<%= entityApiUrl %>") - .accept(MediaType.APPLICATION_STREAM_JSON) + val <%= entityInstance %>List = webTestClient.get().uri(ENTITY_API_URL) + .accept(MediaType.APPLICATION_NDJSON) .exchange() .expectStatus().isOk - .expectHeader().contentTypeCompatibleWith(MediaType.APPLICATION_STREAM_JSON) - .returnResult(<%= dto !== 'no' ? asDto(entityClass) : asEntity(entityClass) %>::class.java) + .expectHeader().contentTypeCompatibleWith(MediaType.APPLICATION_NDJSON) + .returnResult(<%= restClass %>::class.java) .responseBody <%_ if (dto !== 'no') { _%> .map(<%= entityInstance %>Mapper::toEntity) <%_ } _%> - .filter(<%= asEntity(entityInstance) %>::equals) + .filter(<%= persistInstance %>::equals) .collectList() .block(Duration.ofSeconds(5)) assertThat(<%= entityInstance %>List).isNotNull assertThat(<%= entityInstance %>List).hasSize(1) val test<%= entityClass %> = <%= entityInstance %>List[0] - <%_ for (idx in fields) { if (fields[idx].fieldType === 'ZonedDateTime') { _%> - assertThat(test<%= entityClass %>.<%= fields[idx].fieldName %>).isEqualTo(<%= 'DEFAULT_' + fields[idx].fieldNameUnderscored.toUpperCase() %>) - <%_ } else if ((fields[idx].fieldType === 'byte[]' || fields[idx].fieldType === 'ByteBuffer') && fields[idx].fieldTypeBlobContent !== 'text') { _%> - assertThat(test<%= entityClass %>.<%= fields[idx].fieldName %>).isEqualTo(<%= 'DEFAULT_' + fields[idx].fieldNameUnderscored.toUpperCase() %>) - assertThat(test<%= entityClass %>.<%= fields[idx].fieldName %>ContentType).isEqualTo(<%= 'DEFAULT_' + fields[idx].fieldNameUnderscored.toUpperCase() %>_CONTENT_TYPE) - <%_ } else if (fields[idx].fieldType.toLowerCase() === 'boolean') { _%> - assertThat(test<%= entityClass %>.<%= fields[idx].fieldName %>).isEqualTo(<%= 'DEFAULT_' + fields[idx].fieldNameUnderscored.toUpperCase() %>) + <%_ for (field of fields.filter(field => !field.id && !field.transient)) { if (field.fieldType === 'ZonedDateTime') { _%> + assertThat(test<%= entityClass %>.<%= field.fieldName %>).isEqualTo(<%= 'DEFAULT_' + field.fieldNameUnderscored.toUpperCase() %>) + <%_ } else if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { _%> + assertThat(test<%= entityClass %>.<%= field.fieldName %>).isEqualTo(<%= 'DEFAULT_' + field.fieldNameUnderscored.toUpperCase() %>) + assertThat(test<%= entityClass %>.<%= field.fieldName %>ContentType).isEqualTo(<%= 'DEFAULT_' + field.fieldNameUnderscored.toUpperCase() %>_CONTENT_TYPE) + <%_ } else if (field.fieldType === 'BigDecimal') { _%> + assertThat(test<%= entityClass %>.<%= field.fieldName %>?.stripTrailingZeros()).isEqualTo(<%= 'DEFAULT_' + field.fieldNameUnderscored.toUpperCase() %>.stripTrailingZeros()) <%_ } else { _%> - assertThat(test<%= entityClass %>.<%= fields[idx].fieldName %>).isEqualTo(<%= 'DEFAULT_' + fields[idx].fieldNameUnderscored.toUpperCase() %>) + assertThat(test<%= entityClass %>.<%= field.fieldName %>).isEqualTo(<%= 'DEFAULT_' + field.fieldNameUnderscored.toUpperCase() %>) <%_ }} _%> } <%_ } _%> + @Test<%= transactionalAnnotation %> <% if (!reactive) { %>@Throws(Exception::class)<% } %> fun getAll<%= entityClassPlural %>() { // Initialize the database - <%_ if (databaseType === 'cassandra') { _%> - <%= asEntity(entityInstance) %>.id = UUID.randomUUID() + <%_ if (primaryKey.type === 'UUID' && databaseType !== 'sql') { _%> + <%= persistInstance %>.<%= primaryKey.name %> = UUID.randomUUID() <%_ } _%> - <%= entityInstance %>Repository.<%= saveMethod %>(<%= asEntity(entityInstance) %>)<%= callBlock %> + <%= entityInstance %>Repository.<%= saveMethod %>(<%= persistInstance %>)<%= callBlock %> <%_ if (!reactive) { _%> // Get all the <%= entityInstance %>List - rest<%= entityClass %>MockMvc.perform(get("/api/<%= entityApiUrl %><% if (databaseType !== 'cassandra') { %>?sort=id,desc<% } %>")) + rest<%= entityClass %>MockMvc.perform(get(ENTITY_API_URL<% if (databaseType !== 'cassandra') { %>+ "?sort=<%= primaryKey.name %>,desc"<% } %>)) .andExpect(status().isOk) .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) <%_ } else { _%> - webTestClient.get().uri("/api/<%= entityApiUrl %>?sort=id,desc") + webTestClient.get().uri(ENTITY_API_URL + "?sort=<%= primaryKey.name %>,desc") .accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isOk @@ -610,18 +623,29 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab <%_ } _%> <%_ if (['sql', 'mongodb', 'couchbase', 'cassandra'].includes(databaseType)) { _%> - <%= !reactive ? '.andExpect(' : '.' %>jsonPath("$.[*].id").value(hasItem(<%= idValue %>))<%= !reactive ? ')' : '' %><%_ } _%><% for (idx in fields) { %> - <%_ if ((fields[idx].fieldType === 'byte[]' || fields[idx].fieldType === 'ByteBuffer') && fields[idx].fieldTypeBlobContent !== 'text') { _%> - <%= !reactive ? '.andExpect(' : '.' %>jsonPath("$.[*].<%= fields[idx].fieldName %>ContentType").value(hasItem(<%= 'DEFAULT_' + fields[idx].fieldNameUnderscored.toUpperCase() %>_CONTENT_TYPE))<%= !reactive ? ')' : '' %> + <%= !reactive ? '.andExpect(' : '.' %>jsonPath("$.[*].<%= primaryKey.name %>").value(hasItem(<%= idValue %>))<%= !reactive ? ')' : '' %><%_ } _%><% for (field of fields.filter(field => !field.id && !field.transient)) { %> + <%_ if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { _%> + <%= !reactive ? '.andExpect(' : '.' %>jsonPath("$.[*].<%= field.fieldName %>ContentType").value(hasItem(<%= 'DEFAULT_' + field.fieldNameUnderscored.toUpperCase() %>_CONTENT_TYPE))<%= !reactive ? ')' : '' %> <%_ } _%> - <%= !reactive ? '.andExpect(' : '.' %>jsonPath("$.[*].<%= fields[idx].fieldName %>").value(hasItem(<% if ((fields[idx].fieldType === 'byte[]' || fields[idx].fieldType === 'ByteBuffer') && fields[idx].fieldTypeBlobContent !== 'text') { %>Base64Utils.encodeToString(<% } else if (fields[idx].fieldType === 'ZonedDateTime') { %>sameInstant(<% } %><%= 'DEFAULT_' + fields[idx].fieldNameUnderscored.toUpperCase() %><% if ((fields[idx].fieldType === 'byte[]' || fields[idx].fieldType === 'ByteBuffer') && fields[idx].fieldTypeBlobContent !== 'text') { %><% if (databaseType === 'cassandra') { %>.array()<% } %>)<% } else if (fields[idx].fieldType === 'Integer') { %><% } else if (fields[idx].fieldType === 'Long') { %>?.toInt()<% } else if (fields[idx].fieldType === 'Float' || fields[idx].fieldType === 'Double') { %>.toDouble()<% } else if (fields[idx].fieldType === 'BigDecimal') { %>?.toInt()<% } else if (fields[idx].fieldType === 'Boolean') { %><% } else if (fields[idx].fieldType === 'ZonedDateTime') { %>)<% } else if (fields[idx].fieldType !== 'String') { %>.toString()<% } %>))<%= !reactive ? ')' : '' %><%_ } _%> + <%= !reactive ? '.andExpect(' : '.' %>jsonPath("$.[*].<%= field.fieldName %>").value(hasItem(<% + if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { %>Base64Utils.encodeToString(<% } else + if (field.fieldType === 'ZonedDateTime') { %>sameInstant(<% } else + if (field.fieldType === 'BigDecimal') { %>sameNumber(<% } %><%= 'DEFAULT_' + field.fieldNameUnderscored.toUpperCase() %><% + if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { %><% + if (databaseType === 'cassandra') { %>.array()<% } %>)<% } else + if (field.fieldType === 'Integer') { %><% } else + if (field.fieldType === 'Long') { %>?.toInt()<% } else + if (field.fieldType === 'Float' || field.fieldType === 'Double') { %>.toDouble()<% } else + if (field.fieldType === 'BigDecimal') { %>)<% } else + if (field.fieldType === 'Boolean') { %><% } else + if (field.fieldType === 'ZonedDateTime') { %>)<% } else + if (field.fieldType !== 'String') { %>.toString()<% } %>))<%= !reactive ? ')' : '' %><%_ } _%> } - <% if (fieldsContainOwnerManyToMany === true) { %> + <% if (fieldsContainOwnerManyToMany === true && databaseType !== 'neo4j') { %> @Suppress("unchecked") <% if (!reactive) { %>@Throws(Exception::class)<% } %> fun getAll<%= entityClassPlural %>WithEagerRelationshipsIsEnabled() { <%_ if (service !== 'no') { _%> - val <%= entityInstance %>Resource = <%= entityClass %>Resource(<%= entityInstance %>ServiceMock<% if (jpaMetamodelFiltering) { %>, <%= entityInstance %>QueryService<% } %>) `when`(<%= entityInstance %>ServiceMock.findAllWithEagerRelationships(any())).thenReturn(<% if (!reactive) { %>PageImpl(mutableListOf())<% } else { %>Flux.empty()<% }%>) <%_ } else { _%> val <%= entityInstance %>Resource = <%= entityClass %>Resource(<%= entityInstance %>RepositoryMock<% if (dto === 'mapstruct') { %>, <%= entityInstance %>Mapper<% } %><% if (searchEngine === 'elasticsearch') { %>, mock<%= entityClass %>SearchRepository<% } %><% if (saveUserSnapshot) { %>, userRepository<% } %><% if (isUsingMapsId === true && dto !== 'mapstruct') { %>, <%= mapsIdRepoInstance _%> <% } %>) @@ -629,16 +653,10 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab <%_ } _%> <%_ if (!reactive) { _%> - val rest<%= entityClass %>MockMvc = MockMvcBuilders.standaloneSetup(<%= entityInstance %>Resource) - .setCustomArgumentResolvers(pageableArgumentResolver) - .setControllerAdvice(exceptionTranslator) - .setConversionService(createFormattingConversionService()) - .setMessageConverters(jacksonMessageConverter).build() - - rest<%= entityClass %>MockMvc.perform(get("/api/<%= entityApiUrl %>?eagerload=true")) + rest<%= entityClass %>MockMvc.perform(get(ENTITY_API_URL + "?eagerload=true")) .andExpect(status().isOk) <%_ } else { _%> - webTestClient.get().uri("/api/<%= entityApiUrl %>?eagerload=true") + webTestClient.get().uri(ENTITY_API_URL + "?eagerload=true") .exchange() .expectStatus().isOk <%_ } _%> @@ -654,7 +672,6 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab <% if (!reactive) { %>@Throws(Exception::class)<% } %> fun getAll<%= entityClassPlural %>WithEagerRelationshipsIsNotEnabled() { <%_ if (service !== 'no') { _%> - val <%= entityInstance %>Resource = <%= entityClass %>Resource(<%= entityInstance %>ServiceMock<% if (jpaMetamodelFiltering) { %>, <%= entityInstance %>QueryService<% } %>) `when`(<%= entityInstance %>ServiceMock.findAllWithEagerRelationships(any())).thenReturn(<% if (!reactive) { %>PageImpl(mutableListOf())<% } else { %>Flux.empty()<% }%>) <%_ } else { _%> val <%= entityInstance %>Resource = <%= entityClass %>Resource(<%= entityInstance %>RepositoryMock<% if (dto === 'mapstruct') { %>, <%= entityInstance %>Mapper<% } %><% if (searchEngine === 'elasticsearch') { %>, mock<%= entityClass %>SearchRepository<% } %><% if (saveUserSnapshot) { %>, userRepository<% } %><% if (isUsingMapsId === true && dto !== 'mapstruct') { %>, <%= mapsIdRepoInstance _%> <% } %>) @@ -662,16 +679,10 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab <%_ } _%> <%_ if (!reactive) { _%> - val rest<%= entityClass %>MockMvc = MockMvcBuilders.standaloneSetup(<%= entityInstance %>Resource) - .setCustomArgumentResolvers(pageableArgumentResolver) - .setControllerAdvice(exceptionTranslator) - .setConversionService(createFormattingConversionService()) - .setMessageConverters(jacksonMessageConverter).build() - - rest<%= entityClass %>MockMvc.perform(get("/api/<%= entityApiUrl %>?eagerload=true")) + rest<%= entityClass %>MockMvc.perform(get(ENTITY_API_URL + "?eagerload=true")) .andExpect(status().isOk) <%_ } else { _%> - webTestClient.get().uri("/api/<%= entityApiUrl %>?eagerload=true") + webTestClient.get().uri(ENTITY_API_URL + "?eagerload=true") .exchange() .expectStatus().isOk <%_ } _%> @@ -688,21 +699,21 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab <% if (!reactive) { %>@Throws(Exception::class)<% } %> fun get<%= entityClass %>() { // Initialize the database - <%_ if (databaseType === 'cassandra') { _%> - <%= asEntity(entityInstance) %>.id =UUID.randomUUID() + <%_ if (primaryKey.type === 'UUID' && databaseType !== 'sql') { _%> + <%= persistInstance %>.<%= primaryKey.name %> =UUID.randomUUID() <%_ } _%> - <%= entityInstance %>Repository.<%= saveMethod %>(<%= asEntity(entityInstance) %>)<%= callBlock %> + <%= entityInstance %>Repository.<%= saveMethod %>(<%= persistInstance %>)<%= callBlock %> - val id = <%= asEntity(entityInstance) %>.id + val id = <%= persistInstance %>.<%= primaryKey.name %> assertNotNull(id) // Get the <%= entityInstance %> <%_ if (!reactive) { _%> - rest<%= entityClass %>MockMvc.perform(get("/api/<%= entityApiUrl %>/{id}", id)) + rest<%= entityClass %>MockMvc.perform(get(ENTITY_API_URL_ID, <%= persistInstance %>.<%= primaryKey.name %>)) .andExpect(status().isOk) .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) <%_ } else { _%> - webTestClient.get().uri("/api/<%= entityApiUrl %>/{id}", id) + webTestClient.get().uri(ENTITY_API_URL_ID, <%= persistInstance %>.<%= primaryKey.name %>) .accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isOk @@ -710,31 +721,44 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab .expectBody() <%_ } _%> <%_ if (['sql', 'mongodb', 'couchbase', 'cassandra'].includes(databaseType)) { _%> - <%= !reactive ? '.andExpect(' : '.' %>jsonPath("$.id").value(<%= reactive ? '`is`(' : '' %><%= idValue %>))<%_ } _%><% for (idx in fields) { %> - <%_ if ((fields[idx].fieldType === 'byte[]' || fields[idx].fieldType === 'ByteBuffer') && fields[idx].fieldTypeBlobContent !== 'text') { _%> - <%= !reactive ? '.andExpect(' : '.' %>jsonPath("$.<%= fields[idx].fieldName %>ContentType").value(<%= reactive ? '`is`(' : '' %><%= 'DEFAULT_' + fields[idx].fieldNameUnderscored.toUpperCase() %>_CONTENT_TYPE)) + <%= !reactive ? '.andExpect(' : '.' %>jsonPath("$.<%= primaryKey.name %>").value(<%= reactive ? '`is`(' : '' %><%= idValue %>))<%_ } _%><% for (field of fields.filter(field => !field.id && !field.transient)) { %> + <%_ if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { _%> + <%= !reactive ? '.andExpect(' : '.' %>jsonPath("$.<%= field.fieldName %>ContentType").value(<%= reactive ? '`is`(' : '' %><%= 'DEFAULT_' + field.fieldNameUnderscored.toUpperCase() %>_CONTENT_TYPE)) <%_ } _%> - <%= !reactive ? '.andExpect(' : '.' %>jsonPath("$.<%= fields[idx].fieldName %>").value(<%= reactive ? '`is`(' : '' %><% if ((fields[idx].fieldType === 'byte[]' || fields[idx].fieldType === 'ByteBuffer') && fields[idx].fieldTypeBlobContent !== 'text') { %>Base64Utils.encodeToString(<% } else if (fields[idx].fieldType === 'ZonedDateTime') { %>sameInstant(<% } %><%= 'DEFAULT_' + fields[idx].fieldNameUnderscored.toUpperCase() %><% if ((fields[idx].fieldType === 'byte[]' || fields[idx].fieldType === 'ByteBuffer') && fields[idx].fieldTypeBlobContent !== 'text') { %><% if (databaseType === 'cassandra') { %>.array()<% } %>)<% } else if (fields[idx].fieldType === 'Integer') { %><% } else if (fields[idx].fieldType === 'Long') { %>?.toInt()<% } else if (fields[idx].fieldType === 'Float' || fields[idx].fieldType === 'Double') { %>.toDouble()<% } else if (fields[idx].fieldType === 'BigDecimal') { %>?.toInt()<% } else if (fields[idx].fieldType === 'Boolean') { %><% } else if (fields[idx].fieldType === 'ZonedDateTime') { %>)<% } else if (fields[idx].fieldType !== 'String') { %>.toString()<% } %>))<%_ } _%> + <%= !reactive ? '.andExpect(' : '.' %>jsonPath("$.<%= field.fieldName %>").value(<%= reactive ? '`is`(' : '' %><% + if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { %>Base64Utils.encodeToString(<% } else + if (field.fieldType === 'ZonedDateTime') { %>sameInstant(<% } else + if(field.fieldType === 'BigDecimal') { %>sameNumber(<% } %><%= 'DEFAULT_' + field.fieldNameUnderscored.toUpperCase() %><% + if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { %><% + if (databaseType === 'cassandra') { %>.array()<% } %>)<% } else + if (field.fieldType === 'Integer') { %><% } else + if (field.fieldType === 'Long') { %>?.toInt()<% } else + if (field.fieldType === 'Float' || field.fieldType === 'Double') { %>.toDouble()<% } else + if (field.fieldType === 'BigDecimal') { %>)<% } else + if (field.fieldType === 'Boolean') { %><% } else + if (field.fieldType === 'ZonedDateTime') { %>)<% } else + if (field.fieldType !== 'String') { %>.toString()<% } %>))<%_ } _%> } <%_ if (jpaMetamodelFiltering) { %> @Test<%= transactionalAnnotation %> <% if (!reactive) { %>@Throws(Exception::class)<% } %> fun get<%= entityClassPlural %>ByIdFiltering() { // Initialize the database - <%= entityInstance %>Repository.<%= saveMethod %>(<%= asEntity(entityInstance) %>) - val id = <%= asEntity(entityInstance) %>.id - - default<%= entityClass %>ShouldBeFound("id.equals=" + id) - default<%= entityClass %>ShouldNotBeFound("id.notEquals=" + id) - - default<%= entityClass %>ShouldBeFound("id.greaterThanOrEqual=" + id) - default<%= entityClass %>ShouldNotBeFound("id.greaterThan=" + id) - - default<%= entityClass %>ShouldBeFound("id.lessThanOrEqual=" + id) - default<%= entityClass %>ShouldNotBeFound("id.lessThan=" + id) + <%= entityInstance %>Repository.<%= saveMethod %>(<%= persistInstance %>)<%= callBlock %> + val id = <%= persistInstance %>.<%= primaryKey.name %> + + default<%= entityClass %>ShouldBeFound("<%= primaryKey.name %>.equals=" + id) + default<%= entityClass %>ShouldNotBeFound("<%= primaryKey.name %>.notEquals=" + id) + <%_ if (primaryKey.type === 'Long') { _%> + default<%= entityClass %>ShouldBeFound("<%= primaryKey.name %>.greaterThanOrEqual=" + id) + default<%= entityClass %>ShouldNotBeFound("<%= primaryKey.name %>.greaterThan=" + id) + + default<%= entityClass %>ShouldBeFound("<%= primaryKey.name %>.lessThanOrEqual=" + id) + default<%= entityClass %>ShouldNotBeFound("<%= primaryKey.name %>.lessThan=" + id) + <%_ } _%> } <%_ - fields.forEach((searchBy) => { + fields.filter(field => !field.id && !field.transient).forEach((searchBy) => { // we can't filter by all the fields. if (isFilterableType(searchBy.fieldType)) { _%> @@ -743,7 +767,7 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab <% if (!reactive) { %>@Throws(Exception::class)<% } %> fun getAll<%= entityClassPlural %>By<%= searchBy.fieldInJavaBeanMethod %>IsEqualToSomething() { // Initialize the database - <%= entityInstance %>Repository.<%= saveMethod %>(<%= asEntity(entityInstance) %>) + <%= entityInstance %>Repository.<%= saveMethod %>(<%= persistInstance %>)<%= callBlock %> // Get all the <%= entityInstance %>List where <%= searchBy.fieldName %> equals to <%='DEFAULT_' + searchBy.fieldNameUnderscored.toUpperCase()%> default<%= entityClass %>ShouldBeFound("<%= searchBy.fieldName %>.equals=$<%='DEFAULT_' + searchBy.fieldNameUnderscored.toUpperCase()%>") @@ -756,7 +780,7 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab <% if (!reactive) { %>@Throws(Exception::class)<% } %> fun getAll<%= entityClassPlural %>By<%= searchBy.fieldInJavaBeanMethod %>IsNotEqualToSomething() { // Initialize the database - <%= entityInstance %>Repository.<%= saveMethod %>(<%= asEntity(entityInstance) %>) + <%= entityInstance %>Repository.<%= saveMethod %>(<%= persistInstance %>)<%= callBlock %> // Get all the <%= entityInstance %>List where <%= searchBy.fieldName %> not equals to <%='DEFAULT_' + searchBy.fieldNameUnderscored.toUpperCase()%> default<%= entityClass %>ShouldNotBeFound("<%= searchBy.fieldName %>.notEquals=" + <%='DEFAULT_' + searchBy.fieldNameUnderscored.toUpperCase()%>) @@ -769,7 +793,7 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab <% if (!reactive) { %>@Throws(Exception::class)<% } %> fun getAll<%= entityClassPlural %>By<%= searchBy.fieldInJavaBeanMethod %>IsInShouldWork() { // Initialize the database - <%= entityInstance %>Repository.<%= saveMethod %>(<%= asEntity(entityInstance) %>) + <%= entityInstance %>Repository.<%= saveMethod %>(<%= persistInstance %>)<%= callBlock %> // Get all the <%= entityInstance %>List where <%= searchBy.fieldName %> in <%='DEFAULT_' + searchBy.fieldNameUnderscored.toUpperCase()%> or <%='UPDATED_' + searchBy.fieldNameUnderscored.toUpperCase()%> default<%= entityClass %>ShouldBeFound("<%= searchBy.fieldName %>.in=$<%='DEFAULT_' + searchBy.fieldNameUnderscored.toUpperCase()%>,$<%='UPDATED_' + searchBy.fieldNameUnderscored.toUpperCase()%>") @@ -782,7 +806,7 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab <% if (!reactive) { %>@Throws(Exception::class)<% } %> fun getAll<%= entityClassPlural %>By<%= searchBy.fieldInJavaBeanMethod %>IsNullOrNotNull() { // Initialize the database - <%= entityInstance %>Repository.<%= saveMethod %>(<%= asEntity(entityInstance) %>) + <%= entityInstance %>Repository.<%= saveMethod %>(<%= persistInstance %>)<%= callBlock %> // Get all the <%= entityInstance %>List where <%= searchBy.fieldName %> is not null default<%= entityClass %>ShouldBeFound("<%= searchBy.fieldName %>.specified=true") @@ -798,7 +822,7 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab <% if (!reactive) { %>@Throws(Exception::class)<% } %> fun getAll<%= entityClassPlural %>By<%= searchBy.fieldInJavaBeanMethod %>ContainsSomething(){ // Initialize the database - <%= entityInstance %>Repository.<%= saveMethod %>(<%= asEntity(entityInstance) %>) + <%= entityInstance %>Repository.<%= saveMethod %>(<%= persistInstance %>)<%= callBlock %> // Get all the <%= entityInstance %>List where <%= searchBy.fieldName %> contains <%='DEFAULT_' + searchBy.fieldNameUnderscored.toUpperCase()%> default<%= entityClass %>ShouldBeFound("<%= searchBy.fieldName %>.contains=" + <%='DEFAULT_' + searchBy.fieldNameUnderscored.toUpperCase()%>) @@ -811,7 +835,7 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab <% if (!reactive) { %>@Throws(Exception::class)<% } %> fun getAll<%= entityClassPlural %>By<%= searchBy.fieldInJavaBeanMethod %>NotContainsSomething() { // Initialize the database - <%= entityInstance %>Repository.<%= saveMethod %>(<%= asEntity(entityInstance) %>) + <%= entityInstance %>Repository.<%= saveMethod %>(<%= persistInstance %>)<%= callBlock %> // Get all the <%= entityInstance %>List where <%= searchBy.fieldName %> does not contain <%='DEFAULT_' + searchBy.fieldNameUnderscored.toUpperCase()%> default<%= entityClass %>ShouldNotBeFound("<%= searchBy.fieldName %>.doesNotContain=" + <%='DEFAULT_' + searchBy.fieldNameUnderscored.toUpperCase()%>) @@ -846,7 +870,7 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab <% if (!reactive) { %>@Throws(Exception::class)<% } %> fun getAll<%= entityClassPlural %>By<%= searchBy.fieldInJavaBeanMethod %>IsGreaterThanOrEqualToSomething() { // Initialize the database - <%= entityInstance %>Repository.<%= saveMethod %>(<%= asEntity(entityInstance) %>) + <%= entityInstance %>Repository.<%= saveMethod %>(<%= persistInstance %>)<%= callBlock %> // Get all the <%= entityInstance %>List where <%= searchBy.fieldName %> is greater than or equal to <%= defaultValue %> default<%= entityClass %>ShouldBeFound("<%= searchBy.fieldName %>.greaterThanOrEqual=$<%= defaultValue %>") @@ -859,7 +883,7 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab <% if (!reactive) { %>@Throws(Exception::class)<% } %> fun getAll<%= entityClassPlural %>By<%= searchBy.fieldInJavaBeanMethod %>IsLessThanOrEqualToSomething() { // Initialize the database - <%= entityInstance %>Repository.<%= saveMethod %>(<%= asEntity(entityInstance) %>) + <%= entityInstance %>Repository.<%= saveMethod %>(<%= persistInstance %>)<%= callBlock %> // Get all the <%= entityInstance %>List where <%= searchBy.fieldName %> is less than or equal to <%= defaultValue %> default<%= entityClass %>ShouldBeFound("<%= searchBy.fieldName %>.lessThanOrEqual=$<%= defaultValue %>") @@ -872,7 +896,7 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab <% if (!reactive) { %>@Throws(Exception::class)<% } %> fun getAll<%= entityClassPlural %>By<%= searchBy.fieldInJavaBeanMethod %>IsLessThanSomething() { // Initialize the database - <%= entityInstance %>Repository.<%= saveMethod %>(<%= asEntity(entityInstance) %>) + <%= entityInstance %>Repository.<%= saveMethod %>(<%= persistInstance %>)<%= callBlock %> // Get all the <%= entityInstance %>List where <%= searchBy.fieldName %> is less than <%= defaultValue %> default<%= entityClass %>ShouldNotBeFound("<%= searchBy.fieldName %>.lessThan=$<%= defaultValue %>") @@ -885,7 +909,7 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab <% if (!reactive) { %>@Throws(Exception::class)<% } %> fun getAll<%= entityClassPlural %>By<%= searchBy.fieldInJavaBeanMethod %>IsGreaterThanSomething() { // Initialize the database - <%= entityInstance %>Repository.<%= saveMethod %>(<%= asEntity(entityInstance) %>) + <%= entityInstance %>Repository.<%= saveMethod %>(<%= persistInstance %>)<%= callBlock %> // Get all the <%= entityInstance %>List where <%= searchBy.fieldName %> is greater than <%= defaultValue %> default<%= entityClass %>ShouldNotBeFound("<%= searchBy.fieldName %>.greaterThan=$<%= defaultValue %>") @@ -901,78 +925,167 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab @Test<%= transactionalAnnotation %> <% if (!reactive) { %>@Throws(Exception::class)<% } %> fun getAll<%= entityClassPlural %>By<%= relationship.relationshipNameCapitalized %>IsEqualToSomething() { + <%_ if ((relationship.relationshipValidate === true && relationship.relationshipType === 'one-to-one') || relationship.id === true) { _%> + // Get already existing entity + val <%= relationship.relationshipFieldName %> = <%= persistInstance %>.<%= relationship.relationshipName %> + <%_ } else { _%> // Initialize the database + <%= entityInstance %>Repository.saveAndFlush(<%= persistInstance %>) val <%= relationship.relationshipFieldName %> = <%= relationship.otherEntityNameCapitalized %>ResourceIT.createEntity(em) em.persist(<%= relationship.relationshipFieldName %>) em.flush() -<%_ if (relationship.relationshipType === 'many-to-many' || relationship.relationshipType === 'one-to-many') { _%> - <%= asEntity(entityInstance) %>.add<%= relationship.relationshipNameCapitalized %>(<%= relationship.relationshipFieldName %>) -<%_ } else { _%> - <%= asEntity(entityInstance) %>.<%= relationship.relationshipName %> = <%= relationship.relationshipFieldName %> -<%_ if (relationship.ownerSide === false) { _%> - <%= relationship.relationshipFieldName %>.<%= relationship.otherEntityRelationshipName %> = <%= asEntity(entityInstance) %> -<%_ } _%> -<%_ } _%> - <%= entityInstance %>Repository.<%= saveMethod %>(<%= asEntity(entityInstance) %>) - val <%= relationship.relationshipFieldName %>Id = <%= relationship.relationshipFieldName %>.id + <%_ if (relationship.relationshipType === 'many-to-many' || relationship.relationshipType === 'one-to-many') { _%> + <%= persistInstance %>.add<%= relationship.relationshipNameCapitalized %>(<%= relationship.relationshipFieldName %>) + <%_ } else { _%> + <%= persistInstance %>.<%= relationship.relationshipName %> = <%= relationship.relationshipFieldName %> + <%_ if (relationship.ownerSide === false) { _%> + <%= relationship.relationshipFieldName %>.<%= relationship.otherEntityRelationshipName %> = <%= persistInstance %> + <%_ } _%> + <%_ } _%> + <%= entityInstance %>Repository.saveAndFlush(<%= persistInstance %>) + val <%= relationship.relationshipFieldName %>Id = <%= relationship.relationshipFieldName %>.<%= relationship.otherEntity.primaryKey.name %> // Get all the <%= entityInstance %>List where <%= relationship.relationshipFieldName %> equals to <%= relationship.relationshipFieldName %>Id default<%= entityClass %>ShouldBeFound("<%= relationship.relationshipFieldName %>Id.equals=$<%= relationship.relationshipFieldName %>Id") + <%_ + const initInvalidPrimaryKey = { + 'String' : '"invalid-id"', + 'Long' : '(' + relationship.relationshipFieldName + 'Id?.plus(1))', + 'UUID' : 'UUID.randomUUID()' + }[relationship.otherEntity.primaryKey.type]; + _%> - // Get all the <%= entityInstance %>List where <%= relationship.relationshipFieldName %> equals to <%= relationship.relationshipFieldName %>Id + 1 - default<%= entityClass %>ShouldNotBeFound("<%= relationship.relationshipFieldName %>Id.equals=${<%= relationship.relationshipFieldName %>Id?.plus(1)}") + // Get all the <%= entityInstance %>List where <%= relationship.relationshipFieldName %> equals to <%- initInvalidPrimaryKey %> + default<%= entityClass %>ShouldNotBeFound("<%= relationship.relationshipFieldName %>Id.equals=${<%- initInvalidPrimaryKey %>}") + <%_ } _%> } <%_ }); _%> /** * Executes the search, and checks that the default entity is returned */ - <% if (!reactive) { %>@Throws(Exception::class)<% } %> + <% if (reactive) { %> private fun default<%= entityClass %>ShouldBeFound(filter: String) { - rest<%= entityClass %>MockMvc.perform(get("/api/<%= entityApiUrl %>?sort=id,desc&$filter")) + webTestClient.get().uri(ENTITY_API_URL + "?sort=<%= primaryKey.name %>,desc&" + filter) + .accept(MediaType.APPLICATION_JSON) + .exchange() + .expectStatus().isOk + .expectHeader().contentType(MediaType.APPLICATION_JSON) + .expectBody() + .jsonPath("$.[*].<%= primaryKey.name %>").value(hasItem(<%= idValue %>))<% for (field of fields.filter(field => !field.id && !field.transient)) { %> + <%_ if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { _%> + .jsonPath("$.[*].<%= field.fieldName %>ContentType").value(hasItem(<%= 'DEFAULT_' + field.fieldNameUnderscored.toUpperCase() %>_CONTENT_TYPE)) + <%_ } _%> + .jsonPath("$.[*].<%= field.fieldName %>").value(hasItem(<% if + ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { %>Base64Utils.encodeToString(<% } else + if (field.fieldType === 'ZonedDateTime') { %>sameInstant(<% } else + if (field.fieldType === 'BigDecimal') { %>sameNumber(<% } %><%= 'DEFAULT_' + field.fieldNameUnderscored.toUpperCase() %><% + if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { %><% if (databaseType === 'cassandra') { %>.array()<% } %>)<% } else + if (field.fieldType === 'Integer') { %><% } else + if (field.fieldType === 'Long') { %>?.toInt()<% } else + if (field.fieldType === 'Float') { %>?.toDouble()<% } else + if (field.fieldType === 'Double') { %><% } else + if (field.fieldType === 'BigDecimal') { %>))<% } else + if (field.fieldType === 'Boolean') { %><% } else + if (field.fieldType === 'ZonedDateTime') { %>)<% } else + if (field.fieldType !== 'String') { %>.toString()<% } %>)))<% }; %> + + // Check, that the count call also returns 1 + webTestClient.get().uri(ENTITY_API_URL + "/count?sort=<%= primaryKey.name %>,desc&" + filter) + .accept(MediaType.APPLICATION_JSON) + .exchange() + .expectStatus().isOk + .expectHeader().contentType(MediaType.APPLICATION_JSON) + .expectBody().json("1") + } + <% } else { %> + @Throws(Exception::class) + private fun default<%= entityClass %>ShouldBeFound(filter: String) { + rest<%= entityClass %>MockMvc.perform(get(ENTITY_API_URL + "?sort=<%= primaryKey.name %>,desc&$filter")) .andExpect(status().isOk) .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) - .andExpect(jsonPath("$.[*].id").value(hasItem(<%= asEntity(entityInstance) %><% if (databaseType === 'sql' && hasOauthUser === true) { %>.id?<% } else { %>.id?.toInt()<% } %>)))<% fields.forEach((field) => { %> + <%_ + const primaryKeyConversion = { + 'Long' : '?.toInt()', + 'UUID' : '?.toString()' + }[primaryKey.type] || ''; + _%> + .andExpect(jsonPath("$.[*].<%= primaryKey.name %>").value(hasItem(<%= persistInstance %>.<%= primaryKey.name %><%= primaryKeyConversion %>)))<% fields.filter(field => !field.id && !field.transient).forEach((field) => { %> <%_ if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { _%> .andExpect(jsonPath("$.[*].<%=field.fieldName%>ContentType").value(hasItem(<%='DEFAULT_' + field.fieldNameUnderscored.toUpperCase()%>_CONTENT_TYPE))) <%_ } _%> - .andExpect(jsonPath("$.[*].<%=field.fieldName%>").value(hasItem(<% if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { %>Base64Utils.encodeToString(<% } else if (field.fieldType === 'ZonedDateTime') { %>sameInstant(<% } %><%='DEFAULT_' + field.fieldNameUnderscored.toUpperCase()%><% if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { %><% if (databaseType === 'cassandra') { %>.array()<% } %>)<% } else if (field.fieldType === 'Integer') { %><% } else if (field.fieldType === 'Long') { %>?.toInt()<% } else if (field.fieldType === 'Float') { %>.toDouble()<% } else if (field.fieldType === 'Double') { %><% } else if (field.fieldType === 'BigDecimal') { %>?.toInt()<% } else if (field.fieldType === 'Boolean') { %><% } else if (field.fieldType === 'ZonedDateTime') { %>)<% } else if (field.fieldType === 'String' || field.fieldTypeBlobContent === 'text') { %><% } else if (field.fieldType !== 'String') { %>.toString()<% } %>)))<% }); %>; + .andExpect(jsonPath("$.[*].<%=field.fieldName%>").value(hasItem(<% + if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { %>Base64Utils.encodeToString(<% } else + if (field.fieldType === 'ZonedDateTime') { %>sameInstant(<% } else + if (field.fieldType === 'BigDecimal') { %>sameNumber(<% } %><%='DEFAULT_' + field.fieldNameUnderscored.toUpperCase()%><% + if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { %><% + if (databaseType === 'cassandra') { %>.array()<% } %>)<% } else + if (field.fieldType === 'Integer') { %><% } else + if (field.fieldType === 'Long') { %>?.toInt()<% } else + if (field.fieldType === 'Float') { %>?.toDouble()<% } else + if (field.fieldType === 'Double') { %><% } else + if (field.fieldType === 'BigDecimal') { %>)<% } else + if (field.fieldType === 'Boolean') { %><% } else + if (field.fieldType === 'ZonedDateTime') { %>)<% } else + if (field.fieldType !== 'String') { %>.toString()<% } %>)))<% }); %> + // Check, that the count call also returns 1 - rest<%= entityClass %>MockMvc.perform(get("/api/<%= entityApiUrl %>/count?sort=id,desc&$filter")) + rest<%= entityClass %>MockMvc.perform(get(ENTITY_API_URL + "/count?sort=<%= primaryKey.name %>,desc&$filter")) .andExpect(status().isOk) .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) .andExpect(content().string("1")) } + <% } %> /** * Executes the search, and checks that the default entity is not returned */ - <% if (!reactive) { %>@Throws(Exception::class)<% } %> +<% if (reactive) { %> private fun default<%= entityClass %>ShouldNotBeFound(filter: String) { - rest<%= entityClass %>MockMvc.perform(get("/api/<%= entityApiUrl %>?sort=id,desc&$filter")) + webTestClient.get().uri(ENTITY_API_URL + "?sort=<%= primaryKey.name %>,desc&" + filter) + .accept(MediaType.APPLICATION_JSON) + .exchange() + .expectStatus().isOk + .expectHeader().contentType(MediaType.APPLICATION_JSON) + .expectBody() + .jsonPath("$").isArray() + .jsonPath("$").isEmpty + + // Check, that the count call also returns 0 + webTestClient.get().uri(ENTITY_API_URL + "/count?sort=<%= primaryKey.name %>,desc&" + filter) + .accept(MediaType.APPLICATION_JSON) + .exchange() + .expectStatus().isOk + .expectHeader().contentType(MediaType.APPLICATION_JSON) + .expectBody().json("0") + } +<%_ } else { _%> + @Throws(Exception::class) + private fun default<%= entityClass %>ShouldNotBeFound(filter: String) { + rest<%= entityClass %>MockMvc.perform(get(ENTITY_API_URL + "?sort=<%= primaryKey.name %>,desc&$filter")) .andExpect(status().isOk) .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) .andExpect(jsonPath("$").isArray) .andExpect(jsonPath("$").isEmpty) // Check, that the count call also returns 0 - rest<%= entityClass %>MockMvc.perform(get("/api/<%= entityApiUrl %>/count?sort=id,desc&$filter")) + rest<%= entityClass %>MockMvc.perform(get(ENTITY_API_URL + "/count?sort=<%= primaryKey.name %>,desc&$filter")) .andExpect(status().isOk) .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) .andExpect(content().string("0")) } <%_ } _%> - +<%_ } _%> @Test<%= transactionalAnnotation %> <% if (!reactive) { %>@Throws(Exception::class)<% } %> fun getNonExisting<%= entityClass %>() { // Get the <%= entityInstance %> <%_ if (!reactive) { _%> - rest<%= entityClass %>MockMvc.perform(get("/api/<%= entityApiUrl %>/{id}", <% if (['sql', 'mongodb', 'neo4j', 'couchbase'].includes(databaseType)) { %>Long.MAX_VALUE<% } else if (databaseType === 'cassandra') { %>UUID.randomUUID().toString()<% } %>)) + rest<%= entityClass %>MockMvc.perform(get(ENTITY_API_URL_ID, <% if (['Long', 'String'].includes(primaryKey.type)) { %>Long.MAX_VALUE<% } else if (primaryKey.type === 'UUID') { %>UUID.randomUUID().toString()<% } %>)) .andExpect(status().isNotFound) <%_ } else { _%> - webTestClient.get().uri("/api/<%= entityApiUrl %>/{id}", <% if (['sql', 'mongodb', 'neo4j', 'couchbase'].includes(databaseType)) { %>Long.MAX_VALUE<% } else if (databaseType === 'cassandra') { %>UUID.randomUUID().toString()<% } %>) + webTestClient.get().uri(ENTITY_API_URL_ID, <% if (['Long', 'String'].includes(primaryKey.type)) { %>Long.MAX_VALUE<% } else if (primaryKey.type === 'UUID') { %>UUID.randomUUID().toString()<% } %>) .accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isNotFound @@ -980,52 +1093,46 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab } <%_ if (!readOnly) { _%> @Test<%= transactionalAnnotation %> - fun update<%= entityClass %>() { + fun putNew<%= entityClass %>() { <%_ if (reactive && searchEngine === 'elasticsearch') { _%> // Configure the mock search repository `when`(mock<%= entityClass %>SearchRepository.save(any(<%= entityClass %>::class.java))) .thenAnswer { Mono.just(it.arguments[0] as <%= entityClass %>) } <%_ } _%> // Initialize the database - <%_ if (databaseType === 'cassandra') { _%> - <%= asEntity(entityInstance) %>.id = UUID.randomUUID() + <%_ if (primaryKey.type === 'UUID' && databaseType !== 'sql') { _%> + <%= persistInstance %>.<%= primaryKey.name %> = UUID.randomUUID() <%_ } _%> -<%_ if (service !== 'no' && dto !== 'mapstruct') { _%> - <%= entityInstance %>Service.save(<%= asEntity(entityInstance) %>)<%= callBlock %> -<%_ } else { _%> - <%= entityInstance %>Repository.<%= saveMethod %>(<%= asEntity(entityInstance) %>)<%= callBlock %> -<%_ } _%> + <%= entityInstance %>Repository.<%= saveMethod %>(<%= persistInstance %>)<%= callBlock %> val databaseSizeBeforeUpdate = <%= entityInstance %>Repository.findAll()<%= callListBlock %>.size // Update the <%= entityInstance %> - val id = <%= asEntity(entityInstance) %>.id - assertNotNull(id) - val updated<%= entityClass %> = <%= entityInstance %>Repository.findById(id)<%= reactive ? '.block()' : '.get()' %> - <%_ if (databaseType === 'sql') { _%> - // Disconnect from session so that the updates on updated<%= entityClass %> are not directly saved in db - em.detach(updated<%= entityClass %>) - <%_ } _%> - <%_ for (idx in fields) { _%> - updated<%= entityClass %>.<%= fields[idx].fieldName %> = <%='UPDATED_' + fields[idx].fieldNameUnderscored.toUpperCase()%> - <%_ if ((fields[idx].fieldType === 'byte[]' || fields[idx].fieldType === 'ByteBuffer') && fields[idx].fieldTypeBlobContent !== 'text') { _%> - updated<%= entityClass %>.<%= fields[idx].fieldName %>ContentType = <%='UPDATED_' + fields[idx].fieldNameUnderscored.toUpperCase()%>_CONTENT_TYPE + val updated<%= persistClass %> = <%= entityInstance %>Repository.findById(<%= persistInstance %>.<%= primaryKey.name %>)<%= reactive ? '.block()' : '.get()' %> + <%_ if (databaseType === 'sql' && !reactive) { _%> + // Disconnect from session so that the updates on updated<%= persistClass %> are not directly saved in db + em.detach(updated<%= persistClass %>) + <%_ } _%> + <%_ for (field of fields.filter(field => !field.id && !field.transient)) { _%> + updated<%= persistClass %>.<%= field.fieldName %> = <%='UPDATED_' + field.fieldNameUnderscored.toUpperCase()%> + <%_ if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { _%> + updated<%= persistClass %>.<%= field.fieldName %>ContentType = <%='UPDATED_' + field.fieldNameUnderscored.toUpperCase()%>_CONTENT_TYPE <%_ } _%> <%_ } _%> <%_ if (dto === 'mapstruct') { _%> - val <%= asDto(entityInstance) %> = <%= entityInstance %>Mapper.toDto(updated<%= entityClass %>) + val <%= dtoInstance %> = <%= entityInstance %>Mapper.toDto(updated<%= persistClass %>) <%_ } _%> <%_ if (!reactive) { _%> rest<%= entityClass %>MockMvc.perform( - put("/api/<%= entityApiUrl %>") + put(ENTITY_API_URL_ID, <%= (dto === 'mapstruct' ? asDto(entityInstance) : 'updated' + persistClass) %>.<%= primaryKey.name %>)<% if (testsNeedCsrf) { %>.with(csrf())<% }%> .contentType(MediaType.APPLICATION_JSON) - .content(convertObjectToJsonBytes(<% if (dto === 'mapstruct') { %><%= asDto(entityInstance) %><% } else { %>updated<%= entityClass %><% } %>)) + .content(convertObjectToJsonBytes(<% if (dto === 'mapstruct') { %><%= dtoInstance %><% } else { %>updated<%= persistClass %><% } %>)) ).andExpect(status().isOk) <%_ } else { _%> - webTestClient.put().uri("/api/<%= entityApiUrl %>") + webTestClient.put().uri(ENTITY_API_URL_ID, <%= (dto === 'mapstruct' ? asDto(entityInstance) : 'updated' + persistClass) %>.<%= primaryKey.name %>) .contentType(MediaType.APPLICATION_JSON) - .bodyValue(convertObjectToJsonBytes(<%= (dto === 'mapstruct' ? asDto(entityInstance) : 'updated' + asEntity(entityClass)) %>)) + .bodyValue(convertObjectToJsonBytes(<%= (dto === 'mapstruct' ? dtoInstance : 'updated' + persistClass) %>)) .exchange() .expectStatus().isOk <%_ } _%> @@ -1034,48 +1141,264 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab val <%= entityInstance %>List = <%= entityInstance %>Repository.findAll()<%= callListBlock %> assertThat(<%= entityInstance %>List).hasSize(databaseSizeBeforeUpdate) val test<%= entityClass %> = <%= entityInstance %>List[<%= entityInstance %>List.size - 1] - <%_ for (idx in fields) { if (fields[idx].fieldType === 'ZonedDateTime') { _%> - assertThat(test<%= entityClass %>.<%=fields[idx].fieldName%>).isEqualTo(<%='UPDATED_' + fields[idx].fieldNameUnderscored.toUpperCase()%>) - <%_ } else if ((fields[idx].fieldType === 'byte[]' || fields[idx].fieldType === 'ByteBuffer') && fields[idx].fieldTypeBlobContent !== 'text') { _%> - assertThat(test<%= entityClass %>.<%=fields[idx].fieldName%>).isEqualTo(<%='UPDATED_' + fields[idx].fieldNameUnderscored.toUpperCase()%>) - assertThat(test<%= entityClass %>.<%=fields[idx].fieldName%>ContentType).isEqualTo(<%='UPDATED_' + fields[idx].fieldNameUnderscored.toUpperCase()%>_CONTENT_TYPE) - <%_ } else if (fields[idx].fieldType.toLowerCase() === 'boolean') { _%> - assertThat(test<%= entityClass %>.<%=fields[idx].fieldName%>).isEqualTo(<%='UPDATED_' + fields[idx].fieldNameUnderscored.toUpperCase()%>) + <%_ for (field of fields.filter(field => !field.id && !field.transient)) { if (field.fieldType === 'ZonedDateTime') { _%> + assertThat(test<%= entityClass %>.<%=field.fieldName%>).isEqualTo(<%='UPDATED_' + field.fieldNameUnderscored.toUpperCase()%>) + <%_ } else if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { _%> + assertThat(test<%= entityClass %>.<%=field.fieldName%>).isEqualTo(<%='UPDATED_' + field.fieldNameUnderscored.toUpperCase()%>) + assertThat(test<%= entityClass %>.<%=field.fieldName%>ContentType).isEqualTo(<%='UPDATED_' + field.fieldNameUnderscored.toUpperCase()%>_CONTENT_TYPE) + <%_ } else if (field.fieldType === 'BigDecimal') { _%> + assertThat(test<%= entityClass %>.<%=field.fieldName%>?.stripTrailingZeros()).isEqualTo(<%='UPDATED_' + field.fieldNameUnderscored.toUpperCase()%>.stripTrailingZeros()) <%_ } else { _%> - assertThat(test<%= entityClass %>.<%=fields[idx].fieldName%>).isEqualTo(<%='UPDATED_' + fields[idx].fieldNameUnderscored.toUpperCase()%>) + assertThat(test<%= entityClass %>.<%=field.fieldName%>).isEqualTo(<%='UPDATED_' + field.fieldNameUnderscored.toUpperCase()%>) <%_ } } _%> <%_ if (searchEngine === 'elasticsearch') { _%> // Validate the <%= entityClass %> in Elasticsearch - verify(mock<%= entityClass %>SearchRepository, times(<%= service !== 'no' && dto !== 'mapstruct' ? '2' : '1' %>)).save(test<%= entityClass %>); + verify(mock<%= entityClass %>SearchRepository).save(test<%= entityClass %>) <%_ } _%> } @Test<%= transactionalAnnotation %> - fun updateNonExisting<%= entityClass %>() { + fun putNonExisting<%= entityClass %>() { val databaseSizeBeforeUpdate = <%= entityInstance %>Repository.findAll()<%= callListBlock %>.size + <%= persistInstance %>.<%= primaryKey.name %> = <%= getJavaValueGeneratorForType(primaryKey.type) %> <%_ if (dto === 'mapstruct') { _%> // Create the <%= entityClass %> - val <%= asDto(entityInstance) %> = <%= entityInstance %>Mapper.toDto(<%= asEntity(entityInstance) %>) + val <%= dtoInstance %> = <%= entityInstance %>Mapper.toDto(<%= persistInstance %>) <%_ } _%> // If the entity doesn't have an ID, it will throw BadRequestAlertException + <%_ if (!reactive) { _%> + rest<%= entityClass %>MockMvc.perform(put(ENTITY_API_URL_ID, <%= restInstance %>.<%= primaryKey.name %>)<% if (testsNeedCsrf) { %>.with(csrf())<% }%> + .contentType(MediaType.APPLICATION_JSON) + .content(convertObjectToJsonBytes(<%= restInstance %>))) + .andExpect(status().isBadRequest) + <%_ } else { _%> + webTestClient.put().uri(ENTITY_API_URL_ID, <%= restInstance %>.<%= primaryKey.name %>) + .contentType(MediaType.APPLICATION_JSON) + .bodyValue(convertObjectToJsonBytes(<%= restInstance %>)) + .exchange() + .expectStatus().isBadRequest + <%_ } _%> + + // Validate the <%= entityClass %> in the database + <%_ if (databaseType === 'couchbase') { _%> + SecurityContextHolder.setContext(TestSecurityContextHolder.getContext()) + <%_ } _%> + val <%= entityInstance %>List = <%= entityInstance %>Repository.findAll()<%= callListBlock %> + assertThat(<%= entityInstance %>List).hasSize(databaseSizeBeforeUpdate) + <%_ if (searchEngine === 'elasticsearch') { _%> + + // Validate the <%= entityClass %> in Elasticsearch + verify(mock<%= entityClass %>SearchRepository, times(0)).save(<%= persistInstance %>) + <%_ } _%> + } + + @Test<%= transactionalAnnotation %> + @Throws(Exception::class) + fun putWithIdMismatch<%= entityClass %>() { + val databaseSizeBeforeUpdate = <%= entityInstance %>Repository.findAll()<%= callListBlock %>.size + <%= persistInstance %>.<%= primaryKey.name %> = <%= getJavaValueGeneratorForType(primaryKey.type) %> + + <%_ if (dto === 'mapstruct') { _%> + // Create the <%= entityClass %> + val <%= dtoInstance %> = <%= entityInstance %>Mapper.toDto(<%= persistInstance %>) + + <%_ } _%> + // If url ID doesn't match entity ID, it will throw BadRequestAlertException <%_ if (!reactive) { _%> rest<%= entityClass %>MockMvc.perform( - put("/api/<%= entityApiUrl %>") + put(ENTITY_API_URL_ID, <%= getJavaValueGeneratorForType(primaryKey.type) %>)<% if (testsNeedCsrf) { %>.with(csrf())<% }%> .contentType(MediaType.APPLICATION_JSON) - .content(convertObjectToJsonBytes(<%=(dto === 'mapstruct' ? asDto(entityInstance) : asEntity(entityInstance))%>)) + .content(convertObjectToJsonBytes(<%= restInstance %>)) ).andExpect(status().isBadRequest) <%_ } else { _%> - webTestClient.put().uri("/api/<%= entityApiUrl %>") + webTestClient.put().uri(ENTITY_API_URL_ID, <%= getJavaValueGeneratorForType(primaryKey.type) %>) + .contentType(MediaType.APPLICATION_JSON) + .bodyValue(convertObjectToJsonBytes(<%= restInstance %>)) + .exchange() + .expectStatus().isBadRequest + <%_ } _%> + + // Validate the <%= entityClass %> in the database + <%_ if (databaseType === 'couchbase') { _%> + SecurityContextHolder.setContext(TestSecurityContextHolder.getContext()) + <%_ } _%> + val <%= entityInstance %>List = <%= entityInstance %>Repository.findAll()<%= callListBlock %> + assertThat(<%= entityInstance %>List).hasSize(databaseSizeBeforeUpdate) + <%_ if (searchEngine === 'elasticsearch') { _%> + + // Validate the <%= entityClass %> in Elasticsearch + verify(mock<%= entityClass %>SearchRepository, times(0)).save(<%= persistInstance %>) + <%_ } _%> + } + + @Test<%= transactionalAnnotation %> + @Throws(Exception::class) + fun putWithMissingIdPathParam<%= entityClass %>() { + val databaseSizeBeforeUpdate = <%= entityInstance %>Repository.findAll()<%= callListBlock %>.size + <%= persistInstance %>.<%= primaryKey.name %> = <%= getJavaValueGeneratorForType(primaryKey.type) %> + + <%_ if (dto === 'mapstruct') { _%> + // Create the <%= entityClass %> + val <%= dtoInstance %> = <%= entityInstance %>Mapper.toDto(<%= persistInstance %>) + + <%_ } _%> + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + <%_ if (!reactive) { _%> + rest<%= entityClass %>MockMvc.perform(put(ENTITY_API_URL)<% if (testsNeedCsrf) { %>.with(csrf())<% } %> + .contentType(MediaType.APPLICATION_JSON) + .content(convertObjectToJsonBytes(<%= restInstance %>))) + .andExpect(status().isMethodNotAllowed) + <%_ } else { _%> + webTestClient.put().uri(ENTITY_API_URL) .contentType(MediaType.APPLICATION_JSON) + .bodyValue(convertObjectToJsonBytes(<%= restInstance %>)) + .exchange() + .expectStatus().isEqualTo(405) + <%_ } _%> + + // Validate the <%= entityClass %> in the database + <%_ if (databaseType === 'couchbase') { _%> + SecurityContextHolder.setContext(TestSecurityContextHolder.getContext()) + <%_ } _%> + val <%= entityInstance %>List = <%= entityInstance %>Repository.findAll()<%= callListBlock %> + assertThat(<%= entityInstance %>List).hasSize(databaseSizeBeforeUpdate) + <%_ if (searchEngine === 'elasticsearch') { _%> + + // Validate the <%= entityClass %> in Elasticsearch + verify(mock<%= entityClass %>SearchRepository, times(0)).save(<%= persistInstance %>) + <%_ } _%> + } + + <% + const prepareFieldForPatchTest = (field, includeCb) => { + const includeField = includeCb(); + const fieldNameUnderscoreUppercased = field.fieldNameUnderscored.toUpperCase(); + const updateWithValue = includeField ? `UPDATED_${fieldNameUnderscoreUppercased}` : 'null'; + const testWithConstant = includeField ? `UPDATED_${fieldNameUnderscoreUppercased}` : `DEFAULT_${fieldNameUnderscoreUppercased}`; + return { includeField, updateWithValue, testWithConstant, ...field}; + }; + %> + @Test<%= transactionalAnnotation %> + @Throws(Exception::class) + fun partialUpdate<%= entityClass %>WithPatch() { + <% const fieldsToIncludeInPartialPatchTest = fields.filter(field => !field.id && !field.transient).map(field => prepareFieldForPatchTest(field, () => faker.random.boolean())); %> + <%- include('/partials/it_patch_update.partial.kt.ejs', {fields: fieldsToIncludeInPartialPatchTest, saveMethod, asEntity, callBlock, callListBlock}); -%> + } + + @Test<%= transactionalAnnotation %> + @Throws(Exception::class) + fun fullUpdate<%= entityClass %>WithPatch() { + <% const fieldsToIncludeInFullPatchTest = fields.filter(field => !field.id && !field.transient).map(field => prepareFieldForPatchTest(field, () => true)); %> + <%- include('/partials/it_patch_update.partial.kt.ejs', {fields: fieldsToIncludeInFullPatchTest, saveMethod, asEntity, callBlock, callListBlock}); -%> + } + + @Throws(Exception::class) + fun patchNonExisting<%= entityClass %>() { + val databaseSizeBeforeUpdate = <%= entityInstance %>Repository.findAll()<%= callListBlock %>.size + <%= asEntity(entityInstance) %>.<%= primaryKey.name %> = <%= getJavaValueGeneratorForType(primaryKey.type) %> + + <%_ if (dto === 'mapstruct') { _%> + // Create the <%= entityClass %> + val <%= asDto(entityInstance) %> = <%= entityInstance %>Mapper.toDto(<%= asEntity(entityInstance) %>) + + <%_ } _%> + // If the entity doesn't have an ID, it will throw BadRequestAlertException + <%_ if (!reactive) { _%> + rest<%= entityClass %>MockMvc.perform(patch(ENTITY_API_URL_ID, <%= (dto === 'mapstruct' ? asDto(entityInstance) : asEntity(entityInstance)) %>.<%= primaryKey.name %>)<% if (testsNeedCsrf) { %>.with(csrf())<% }%> + .contentType("application/merge-patch+json") + .content(convertObjectToJsonBytes(<%= (dto === 'mapstruct' ? asDto(entityInstance) : asEntity(entityInstance)) %>))) + .andExpect(status().isBadRequest) + <%_ } else { _%> + webTestClient.patch().uri(ENTITY_API_URL_ID, <%= (dto === 'mapstruct' ? asDto(entityInstance) : asEntity(entityInstance)) %>.<%= primaryKey.name %>) + .contentType(MediaType.valueOf("application/merge-patch+json")) + .bodyValue(convertObjectToJsonBytes(<%= (dto === 'mapstruct' ? asDto(entityInstance) : asEntity(entityInstance)) %>)) + .exchange() + .expectStatus().isBadRequest + <%_ } _%> + + // Validate the <%= entityClass %> in the database + <%_ if (databaseType === 'couchbase') { _%> + SecurityContextHolder.setContext(TestSecurityContextHolder.getContext()); + <%_ } _%> + val <%= entityInstance %>List = <%= entityInstance %>Repository.findAll()<%= callListBlock %> + assertThat(<%= entityInstance %>List).hasSize(databaseSizeBeforeUpdate) + <%_ if (searchEngine === 'elasticsearch') { _%> + + // Validate the <%= entityClass %> in Elasticsearch + verify(mock<%= entityClass %>SearchRepository, times(0)).save(<%= asEntity(entityInstance) %>) + <%_ } _%> + } + + @Test<%= transactionalAnnotation %> + @Throws(Exception::class) + fun patchWithIdMismatch<%= entityClass %>() { + val databaseSizeBeforeUpdate = <%= entityInstance %>Repository.findAll()<%= callListBlock %>.size + <%= asEntity(entityInstance) %>.<%= primaryKey.name %> = <%= getJavaValueGeneratorForType(primaryKey.type) %> + + <%_ if (dto === 'mapstruct') { _%> + // Create the <%= entityClass %> + val <%= asDto(entityInstance) %> = <%= entityInstance %>Mapper.toDto(<%= asEntity(entityInstance) %>) + + <%_ } _%> + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + <%_ if (!reactive) { _%> + rest<%= entityClass %>MockMvc.perform(patch(ENTITY_API_URL_ID, <%= getJavaValueGeneratorForType(primaryKey.type) %>)<% if (testsNeedCsrf) { %>.with(csrf())<% } %> + .contentType("application/merge-patch+json") + .content(convertObjectToJsonBytes(<%= (dto === 'mapstruct' ? asDto(entityInstance) : asEntity(entityInstance)) %>))) + .andExpect(status().isBadRequest) + <%_ } else { _%> + webTestClient.patch().uri(ENTITY_API_URL_ID, <%= getJavaValueGeneratorForType(primaryKey.type) %>) + .contentType(MediaType.valueOf("application/merge-patch+json")) .bodyValue(convertObjectToJsonBytes(<%= (dto === 'mapstruct' ? asDto(entityInstance) : asEntity(entityInstance)) %>)) .exchange() .expectStatus().isBadRequest <%_ } _%> // Validate the <%= entityClass %> in the database + <%_ if (databaseType === 'couchbase') { _%> + SecurityContextHolder.setContext(TestSecurityContextHolder.getContext()) + <%_ } _%> + val <%= entityInstance %>List = <%= entityInstance %>Repository.findAll()<%= callListBlock %> + assertThat(<%= entityInstance %>List).hasSize(databaseSizeBeforeUpdate) + <%_ if (searchEngine === 'elasticsearch') { _%> + + // Validate the <%= entityClass %> in Elasticsearch + verify(mock<%= entityClass %>SearchRepository, times(0)).save(<%= asEntity(entityInstance) %>) + <%_ } _%> + } + + @Test<%= transactionalAnnotation %> + @Throws(Exception::class) + fun patchWithMissingIdPathParam<%= entityClass %>() { + val databaseSizeBeforeUpdate = <%= entityInstance %>Repository.findAll()<%= callListBlock %>.size + <%= asEntity(entityInstance) %>.<%= primaryKey.name %> = <%= getJavaValueGeneratorForType(primaryKey.type) %> + + <%_ if (dto === 'mapstruct') { _%> + // Create the <%= entityClass %> + val <%= asDto(entityInstance) %> = <%= entityInstance %>Mapper.toDto(<%= asEntity(entityInstance) %>) + + <%_ } _%> + // If url ID doesn't match entity ID, it will throw BadRequestAlertException + <%_ if (!reactive) { _%> + rest<%= entityClass %>MockMvc.perform(patch(ENTITY_API_URL)<% if (testsNeedCsrf) { %>.with(csrf())<% } %> + .contentType("application/merge-patch+json") + .content(convertObjectToJsonBytes(<%= (dto === 'mapstruct' ? asDto(entityInstance) : asEntity(entityInstance)) %>))) + .andExpect(status().isMethodNotAllowed) + <%_ } else { _%> + webTestClient.patch().uri(ENTITY_API_URL) + .contentType(MediaType.valueOf("application/merge-patch+json")) + .bodyValue(convertObjectToJsonBytes(<%= (dto === 'mapstruct' ? asDto(entityInstance) : asEntity(entityInstance)) %>)) + .exchange() + .expectStatus().isEqualTo(405) + <%_ } _%> + + // Validate the <%= entityClass %> in the database + <%_ if (databaseType === 'couchbase') { _%> + SecurityContextHolder.setContext(TestSecurityContextHolder.getContext()) + <%_ } _%> val <%= entityInstance %>List = <%= entityInstance %>Repository.findAll()<%= callListBlock %> assertThat(<%= entityInstance %>List).hasSize(databaseSizeBeforeUpdate) <%_ if (searchEngine === 'elasticsearch') { _%> @@ -1094,28 +1417,24 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab `when`(mock<%= entityClass %>SearchRepository.save(any(<%= entityClass %>::class.java))) .thenAnswer { Mono.just(it.arguments[0] as <%= entityClass %>) } <%_ } _%> - `when`(mock<%= entityClass %>SearchRepository.deleteById(any<%= primaryKeyType %>())).thenReturn(Mono.empty()) + `when`(mock<%= entityClass %>SearchRepository.deleteById(any<%= primaryKey.type %>())).thenReturn(Mono.empty()) <%_ } _%> // Initialize the database - <%_ if (databaseType === 'cassandra') { _%> - <%= asEntity(entityInstance) %>.id = UUID.randomUUID() + <%_ if (primaryKey.type === 'UUID' && databaseType !== 'sql') { _%> + <%= persistInstance %>.<%= primaryKey.name %> = UUID.randomUUID() <%_ } _%> -<%_ if (service !== 'no' && dto !== 'mapstruct') { _%> - <%= entityInstance %>Service.save(<%= asEntity(entityInstance) %>)<%= callBlock %> -<%_ } else { _%> - <%= entityInstance %>Repository.<%= saveMethod %>(<%= asEntity(entityInstance) %>)<%= callBlock %> -<%_ } _%> + <%= entityInstance %>Repository.<%= saveMethod %>(<%= persistInstance %>)<%= callBlock %> val databaseSizeBeforeDelete = <%= entityInstance %>Repository.findAll()<%= callListBlock %>.size <%_ if (!reactive) { _%> // Delete the <%= entityInstance %> rest<%= entityClass %>MockMvc.perform( - delete("/api/<%= entityApiUrl %>/{id}", <%= asEntity(entityInstance) %>.id) + delete(ENTITY_API_URL_ID, <%= persistInstance %>.<%= primaryKey.name %><% if (primaryKey.type === 'UUID' && databaseType === 'sql') { %>.toString()<% } %>)<% if (testsNeedCsrf) { %>.with(csrf())<% }%> .accept(MediaType.APPLICATION_JSON) ).andExpect(status().isNoContent) <%_ } else { _%> - webTestClient.delete().uri("/api/<%= entityApiUrl %>/{id}", <%= asEntity(entityInstance) %>.id) + webTestClient.delete().uri(ENTITY_API_URL_ID, <%= persistInstance %>.<%= primaryKey.name %>) .accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isNoContent @@ -1123,14 +1442,14 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab // Validate the database contains one less item <%_ if (databaseType === 'couchbase') { _%> - SecurityContextHolder.setContext(TestSecurityContextHolder.getContext()); + SecurityContextHolder.setContext(TestSecurityContextHolder.getContext()) <%_ } _%> val <%= entityInstance %>List = <%= entityInstance %>Repository.findAll()<%= callListBlock %> assertThat(<%= entityInstance %>List).hasSize(databaseSizeBeforeDelete - 1) <%_ if (searchEngine === 'elasticsearch') { _%> // Validate the <%= entityClass %> in Elasticsearch - verify(mock<%= entityClass %>SearchRepository, times(1)).deleteById(<%= asEntity(entityInstance) %>.id) + verify(mock<%= entityClass %>SearchRepository, times(1)).deleteById(<%= persistInstance %>.<%= primaryKey.name %>) <%_ } _%> } <%_ } _%> @@ -1148,135 +1467,144 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab <%_ } _%> <%_ } _%> // Initializesearch<%= entityClass %>() the database - <%_ if (databaseType === 'cassandra') { _%> - <%= asEntity(entityInstance) %>.id = UUID.randomUUID() - <%_ } _%> - <%_ if (service !== 'no' && dto !== 'mapstruct') { _%> - <%= entityInstance %>Service.save(<%= asEntity(entityInstance) %>)<%= callBlock %> - <%_ } else { _%> - <%= entityInstance %>Repository.<%= saveMethod %>(<%= asEntity(entityInstance) %>)<%= callBlock %> + <%_ if (primaryKey.type === 'UUID' && databaseType !== 'sql') { _%> + <%= persistInstance %>.<%= primaryKey.name %> = UUID.randomUUID() <%_ } _%> + <%= entityInstance %>Repository.<%= saveMethod %>(<%= persistInstance %>)<%= callBlock %> <%_ if (searchEngine === 'elasticsearch') { _%> <%_ if (reactive) { _%> - `when`(mock<%= entityClass %>SearchRepository.search("id:" + <%= asEntity(entityInstance) %>.id<%_ if (pagination !== 'no') { _%>, PageRequest.of(0, 20)<% }%>)) - .thenReturn(Flux.just(<%= asEntity(entityInstance) %>)) + `when`(mock<%= entityClass %>SearchRepository.search("id:" + <%= persistInstance %>.<%= primaryKey.name %><%_ if (pagination !== 'no') { _%>, PageRequest.of(0, 20)<% }%>)) + .thenReturn(Flux.just(<%= persistInstance %>)) <%_ } else { _%> <%_ if (pagination !== 'no') { _%> - `when`(mock<%= entityClass %>SearchRepository.search(queryStringQuery("id:" + <%= asEntity(entityInstance) %>.id), PageRequest.of(0, 20))) - .thenReturn(PageImpl(listOf(<%= asEntity(entityInstance) %>), PageRequest.of(0, 1), 1)) + `when`(mock<%= entityClass %>SearchRepository.search(queryStringQuery("id:" + <%= persistInstance %>.<%= primaryKey.name %>), PageRequest.of(0, 20))) + .thenReturn(PageImpl(listOf(<%= persistInstance %>), PageRequest.of(0, 1), 1)) <%_ } else { _%> - `when`(mock<%= entityClass %>SearchRepository.search(queryStringQuery("id:" + <%= asEntity(entityInstance) %>.id))) - .thenReturn(listOf(<%= asEntity(entityInstance) %>)) + `when`(mock<%= entityClass %>SearchRepository.search(queryStringQuery("id:" + <%= persistInstance %>.<%= primaryKey.name %>))) + .thenReturn(listOf(<%= persistInstance %>)) <%_ } _%> <%_ } _%> <%_ } else if (searchEngine === 'couchbase') { _%> // Wait for the <%= entityInstance %> to be indexed - retryUntilNotEmpty(() -> <%= entityInstance %>Repository.search(<%= entityClass %>.PREFIX, "id:" + <%= entityInstance %>.id)<% if (reactive) { %>.collectList().block()<% } %>) + retryUntilNotEmpty(() -> <%= entityInstance %>Repository.search(<%= entityClass %>.PREFIX, "id:" + <%= entityInstance %>.<%= primaryKey.name %>)<% if (reactive) { %>.collectList().block()<% } %>) <%_ } _%> // Search the <%= entityInstance %> <%_ if (!reactive) { _%> - rest<%= entityClass %>MockMvc.perform(get("/api/_search/<%= entityApiUrl %>?query=id:" + <%= asEntity(entityInstance) %>.id)) + rest<%= entityClass %>MockMvc.perform(get(ENTITY_SEARCH_API_URL + "?query=id:" + <%= persistInstance %>.<%= primaryKey.name %>)) .andExpect(status().isOk) .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) <%_ } else { _%> - webTestClient.get().uri("/api/_search/<%= entityApiUrl %>?query=id:" + <%= asEntity(entityInstance) %>.id) + webTestClient.get().uri(ENTITY_SEARCH_API_URL + "?query=id:" + <%= persistInstance %>.<%= primaryKey.name %>) .exchange() - .expectStatus().isOk() + .expectStatus().isOk .expectHeader().contentType(MediaType.APPLICATION_JSON) .expectBody() <%_ } _%> <%_ if (['sql', 'mongodb', 'couchbase', 'cassandra'].includes(databaseType)) { _%> - <%= !reactive ? '.andExpect(' : '.' %>jsonPath("$.[*].id").value(hasItem(<%= idValue %>))<%= !reactive ? ')' : '' %><%_ } _%><% for (idx in fields) { %> - <%_ if ((fields[idx].fieldType === 'byte[]' || fields[idx].fieldType === 'ByteBuffer') && fields[idx].fieldTypeBlobContent !== 'text') { _%> - <%= !reactive ? '.andExpect(' : '.' %>jsonPath("$.[*].<%= fields[idx].fieldName %>ContentType").value(hasItem(<%= 'DEFAULT_' + fields[idx].fieldNameUnderscored.toUpperCase() %>_CONTENT_TYPE))<%= !reactive ? ')' : '' %><%_ } _%> - <%= !reactive ? '.andExpect(' : '.' %>jsonPath("$.[*].<%= fields[idx].fieldName %>").value(hasItem(<% if ((fields[idx].fieldType === 'byte[]' || fields[idx].fieldType === 'ByteBuffer') && fields[idx].fieldTypeBlobContent !== 'text') { %>Base64Utils.encodeToString(<% } else if (fields[idx].fieldType === 'ZonedDateTime') { %>sameInstant(<% } %><%= 'DEFAULT_' + fields[idx].fieldNameUnderscored.toUpperCase() %><% if ((fields[idx].fieldType === 'byte[]' || fields[idx].fieldType === 'ByteBuffer') && fields[idx].fieldTypeBlobContent !== 'text') { %><% if (databaseType === 'cassandra') { %>.array()<% } %>)<% } else if (fields[idx].fieldType === 'Integer') { %><% } else if (fields[idx].fieldType === 'Boolean') { %><% } else if (fields[idx].fieldType === 'Long') { %>?.toInt()<% } else if (fields[idx].fieldType === 'Float' || fields[idx].fieldType === 'Double') { %>.toDouble()<% } else if (fields[idx].fieldType === 'BigDecimal') { %>?.toInt()<% } else if (fields[idx].fieldType === 'ZonedDateTime') { %>)<% } else if (fields[idx].fieldType !== 'String') { %>.toString()<% } %>))<%= !reactive ? ')' : '' %><%_ } _%> + <%= !reactive ? '.andExpect(' : '.' %>jsonPath("$.[*].<%= primaryKey.name %>").value(hasItem(<%= idValue %>))<%= !reactive ? ')' : '' %><%_ } _%><% for (field of fields.filter(field => !field.id && !field.transient)) { %> + <%_ if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { _%> + <%= !reactive ? '.andExpect(' : '.' %>jsonPath("$.[*].<%= field.fieldName %>ContentType").value(hasItem(<%= 'DEFAULT_' + field.fieldNameUnderscored.toUpperCase() %>_CONTENT_TYPE))<%= !reactive ? ')' : '' %><%_ } _%> + <%= !reactive ? '.andExpect(' : '.' %>jsonPath("$.[*].<%= field.fieldName %>").value(hasItem(<% + if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { %>Base64Utils.encodeToString(<% } else + if (field.fieldType === 'ZonedDateTime') { %>sameInstant(<% } else + if (field.fieldType === 'BigDecimal') { %>sameNumber(<% } %><%= 'DEFAULT_' + field.fieldNameUnderscored.toUpperCase() %><% + if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { %><% + if (databaseType === 'cassandra') { %>.array()<% } %>)<% } else + if (field.fieldType === 'Integer') { %><% } else + if (field.fieldType === 'Boolean') { %><% } else + if (field.fieldType === 'Long') { %>?.toInt()<% } else + if (field.fieldType === 'Float' || field.fieldType === 'Double') { %>.toDouble()<% } else + if (field.fieldType === 'BigDecimal') { %>)<% } else + if (field.fieldType === 'ZonedDateTime') { %>)<% } else + if (field.fieldType !== 'String') { %>.toString()<% } %>))<%= !reactive ? ')' : '' %><%_ } _%> } <%_ } _%> companion object { - <%_ for (idx in fields) { - const defaultValueName = 'DEFAULT_' + fields[idx].fieldNameUnderscored.toUpperCase(); - const updatedValueName = 'UPDATED_' + fields[idx].fieldNameUnderscored.toUpperCase(); - const smallerValueName = 'SMALLER_' + fields[idx].fieldNameUnderscored.toUpperCase(); - const needsSmallerValueName = jpaMetamodelFiltering && isFilterableType(fields[idx].fieldType) - && ['BigDecimal', 'Byte', 'Double', 'Duration', 'Float', 'Short', 'Integer', 'Long', 'LocalDate', 'ZonedDateTime'].includes(fields[idx].fieldType); - - let defaultValue = 1; - let updatedValue = 2; - - if (fields[idx].fieldValidate === true) { - if (fields[idx].fieldValidateRules.includes('max')) { - defaultValue = fields[idx].fieldValidateRulesMax; - updatedValue = parseInt(fields[idx].fieldValidateRulesMax) - 1; - } - if (fields[idx].fieldValidateRules.includes('min')) { - defaultValue = fields[idx].fieldValidateRulesMin; - updatedValue = parseInt(fields[idx].fieldValidateRulesMin) + 1; - } - if (fields[idx].fieldValidateRules.includes('minbytes')) { - defaultValue = fields[idx].fieldValidateRulesMinbytes; - updatedValue = fields[idx].fieldValidateRulesMinbytes; - } - if (fields[idx].fieldValidateRules.includes('maxbytes')) { - updatedValue = fields[idx].fieldValidateRulesMaxbytes; + <%_ for (field of fields.filter(field => !field.id && !field.transient)) { + const defaultValueName = 'DEFAULT_' + field.fieldNameUnderscored.toUpperCase(); + const updatedValueName = 'UPDATED_' + field.fieldNameUnderscored.toUpperCase(); + const smallerValueName = 'SMALLER_' + field.fieldNameUnderscored.toUpperCase(); + const needsSmallerValueName = jpaMetamodelFiltering && isFilterableType(field.fieldType) + && ['BigDecimal', 'Byte', 'Double', 'Duration', 'Float', 'Short', 'Integer', 'Long', 'LocalDate', 'ZonedDateTime'].includes(field.fieldType); + + let defaultValue = 1; + let updatedValue = 2; + + if (field.fieldValidate === true) { + if (field.fieldValidateRules.includes('max')) { + defaultValue = field.fieldValidateRulesMax; + updatedValue = parseInt(field.fieldValidateRulesMax) - 1; + } + if (field.fieldValidateRules.includes('min')) { + defaultValue = field.fieldValidateRulesMin; + updatedValue = parseInt(field.fieldValidateRulesMin) + 1; + } + if (field.fieldValidateRules.includes('minbytes')) { + defaultValue = field.fieldValidateRulesMinbytes; + updatedValue = field.fieldValidateRulesMinbytes; + } + if (field.fieldValidateRules.includes('maxbytes')) { + updatedValue = field.fieldValidateRulesMaxbytes; + } } - } - const fieldType = fields[idx].fieldType; - const fieldTypeBlobContent = fields[idx].fieldTypeBlobContent; - const isEnum = fields[idx].fieldIsEnum; - let enumValue1; - let enumValue2; - if (isEnum) { - const enumValues = getEnumValuesWithCustomValues(fields[idx].fieldValues); - enumValue1 = enumValues[0]; - if (enumValues.length > 1) { - enumValue2 = enumValues[1]; - } else { - enumValue2 = enumValue1; + const fieldType = field.fieldType; + const fieldTypeBlobContent = field.fieldTypeBlobContent; + const isEnum = field.fieldIsEnum; + let enumValue1; + let enumValue2; + if (isEnum) { + const enumValues = field.enumValues; + enumValue1 = enumValues[0]; + if (enumValues.length > 1) { + enumValue2 = enumValues[1]; + } else { + enumValue2 = enumValue1; + } } - } - if (fieldType === 'String' || fieldTypeBlobContent === 'text') { - // Generate Strings, using the min and max string length if they are configured - let sampleTextString = ""; - let updatedTextString = ""; - let sampleTextLength = 10; - if (fields[idx].fieldValidateRulesMinlength > sampleTextLength) { - sampleTextLength = fields[idx].fieldValidateRulesMinlength; - } - if (fields[idx].fieldValidateRulesMaxlength < sampleTextLength) { - sampleTextLength = fields[idx].fieldValidateRulesMaxlength; - } - for (let i = 0; i < sampleTextLength; i++) { - sampleTextString += "A"; - updatedTextString += "B"; - } - if (!this._.isUndefined(fields[idx].fieldValidateRulesPattern)) { - // Generate Strings, using pattern - try { - const patternRegExp = new RegExp(fields[idx].fieldValidateRulesPattern); - const randExp = new this.randexp(fields[idx].fieldValidateRulesPattern); - // set infinite repetitionals max range - if (!patternRegExp.test(sampleTextString.replace(/\\"/g, '"').replace(/\\\\/g, '\\'))) { - sampleTextString = randExp.gen().replace(/\\/g, '\\\\').replace(/"/g, '\\"'); + if (fieldType === 'String' || fieldTypeBlobContent === 'text') { + // Generate Strings, using the min and max string length if they are configured + let sampleTextString = ""; + let updatedTextString = ""; + let sampleTextLength = 10; + if (field.fieldValidateRulesMinlength > sampleTextLength) { + sampleTextLength = field.fieldValidateRulesMinlength; + } + if (field.fieldValidateRulesMaxlength < sampleTextLength) { + sampleTextLength = field.fieldValidateRulesMaxlength; + } + for (let i = 0; i < sampleTextLength; i++) { + sampleTextString += "A"; + updatedTextString += "B"; + } + if (field.fieldValidateRulesPattern !== undefined) { + // Generate Strings, using pattern + try { + const patternRegExp = new RegExp(field.fieldValidateRulesPattern); + const randExp = field.createRandexp(); + // set infinite repetitions max range + if (!patternRegExp.test(sampleTextString.replace(/\\"/g, '"').replace(/\\\\/g, '\\'))) { + sampleTextString = randExp.gen().replace(/\\/g, '\\\\').replace(/"/g, '\\"'); + } + if (!patternRegExp.test(updatedTextString.replace(/\\"/g, '"').replace(/\\\\/g, '\\'))) { + updatedTextString = randExp.gen().replace(/\\/g, '\\\\').replace(/"/g, '\\"'); + } + } catch (error) { + log(this.chalkRed('Error generating test value for entity "' + entityClass + + '" field "' + field.fieldName + '" with pattern "' + field.fieldValidateRulesPattern + + '", generating default values for this field. Detailed error message: "' + error.message + '".')); } - if (!patternRegExp.test(updatedTextString.replace(/\\"/g, '"').replace(/\\\\/g, '\\'))) { - updatedTextString = randExp.gen().replace(/\\/g, '\\\\').replace(/"/g, '\\"'); + if (sampleTextString === updatedTextString) { + updatedTextString = updatedTextString + "B"; + log(this.chalkRed('Randomly generated first and second test values for entity "' + entityClass + + '" field "' + field.fieldName + '" with pattern "' + field.fieldValidateRulesPattern + + '" in file "' + entityClass + 'ResourceIT" where equal, added symbol "B" to second value.')); } - } catch (error) { - log(this.chalkRed('Error generating test value for entity "' + entityClass + - '" field "' + fields[idx].fieldName + '" with pattern "' + fields[idx].fieldValidateRulesPattern + - '", generating default values for this field. Detailed error message: "' + error.message + '".')); - } - if (sampleTextString === updatedTextString) { - updatedTextString = updatedTextString + "B"; - log(this.chalkRed('Randomly generated first and second test values for entity "' + entityClass + - '" field "' + fields[idx].fieldName + '" with pattern "' + fields[idx].fieldValidateRulesPattern + - '" in file "' + entityClass + 'ResourceIT" where equal, added symbol "B" to second value.')); } - }_%> + _%> private const val <%=defaultValueName %> = "<%-sampleTextString %>" private const val <%=updatedValueName %> = "<%-updatedTextString %>" @@ -1367,6 +1695,21 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab private val <%=defaultValueName %>: <%=fieldType %> = <%=fieldType %>.<%=enumValue1.name %> private val <%=updatedValueName %>: <%=fieldType %> = <%=fieldType %>.<%=enumValue2.name %> <%_ } } _%> + + + private val ENTITY_API_URL: String = "/api/<%= entityApiUrl %>" + private val ENTITY_API_URL_ID: String = ENTITY_API_URL + "/{<%= primaryKey.name %>}" + <%_ if (searchEngine !== false) { _%> + private val ENTITY_SEARCH_API_URL: String = "/api/_search/<%= entityApiUrl %>" + <%_ } _%> + <%_ if (!embedded && primaryKey.fields.some(field => field.fieldType === 'Long')) { _%> + + private val random: Random = Random() + private val count: AtomicLong = AtomicLong(random.nextInt().toLong() + ( 2 * Integer.MAX_VALUE )) + <%_ } _%> + + + <%_ ['DEFAULT_', 'UPDATED_'].forEach((fieldStatus) => { _%> /** @@ -1376,64 +1719,100 @@ class <%= entityClass %>ResourceIT <% if (databaseType === 'cassandra') { %>: Ab * if they test an entity which requires the current entity. */ @JvmStatic - fun create<% if (fieldStatus === 'UPDATED_') { _%>Updated<%_ } %>Entity(<% if (databaseType === 'sql') { %>em: EntityManager<% } %>): <%= asEntity(entityClass) %> { - val <%= asEntity(entityInstance) %> = <%= asEntity(entityClass) %>( - <%_ for (idx in fields) { - const comma = (parseInt(idx, 10) === (fields.length - 1)) ? '' : ','; + fun create<% if (fieldStatus === 'UPDATED_') { _%>Updated<%_ } %>Entity(<% if (databaseType === 'sql') { %>em: EntityManager<% } %>): <%= persistClass %> { + <%_ + const filteredFields = fields.filter(field => !field.id && !field.transient); + if (filteredFields.length === 0) { _%> - <%= fields[idx].fieldName %> = <%=fieldStatus + fields[idx].fieldNameUnderscored.toUpperCase()%><% if ((fields[idx].fieldType === 'byte[]' || fields[idx].fieldType === 'ByteBuffer') && fields[idx].fieldTypeBlobContent !== 'text') { %>, - <%= fields[idx].fieldName %>ContentType = <%=fieldStatus + fields[idx].fieldNameUnderscored.toUpperCase()%>_CONTENT_TYPE<% } %><%= comma %> - <%_ } _%> + val <%= persistInstance %> = <%= persistClass %>() + <%_ } else { _%> + val <%= persistInstance %> = <%= persistClass %>( + + <%_ + let idx = 0; + for (field of filteredFields) { + const comma = (parseInt(idx, 10) === (filteredFields.length - 1)) ? '' : ','; + idx++; + _%> + <%= field.fieldName %> = <%=fieldStatus + field.fieldNameUnderscored.toUpperCase()%><% if ((field.fieldType === 'byte[]' || field.fieldType === 'ByteBuffer') && field.fieldTypeBlobContent !== 'text') { %>, + <%= field.fieldName %>ContentType = <%=fieldStatus + field.fieldNameUnderscored.toUpperCase()%>_CONTENT_TYPE<% } %><%= comma %> + + <%_ } _%> ) + <%_ } _%> + <%_ const alreadyGeneratedEntities = [] - for (idx in relationships) { - const relationshipValidate = relationships[idx].relationshipValidate; - const otherEntityName = relationships[idx].otherEntityName; - const otherEntityNameCapitalized = relationships[idx].otherEntityNameCapitalized; - const relationshipType = relationships[idx].relationshipType; - const relationshipName = relationships[idx].relationshipName; - const mapsIdUse = relationships[idx].useJPADerivedIdentifier; + for (relationship of relationships) { + const relationshipValidate = relationship.relationshipValidate; + const otherEntityName = relationship.otherEntityName; + const otherEntityNameCapitalized = relationship.otherEntityNameCapitalized; + const relationshipType = relationship.relationshipType; + const relationshipName = relationship.relationshipName; + const relationshipNamePlural = relationship.relationshipNamePlural; + const mapsIdUse = relationship.id; if ((relationshipValidate !== null && relationshipValidate === true) || mapsIdUse === true) { _%> // Add required entity <%_ if (alreadyGeneratedEntities.indexOf(otherEntityName) == -1) { _%> <%_ if (otherEntityName === 'user') { // TODO or other entity has no unique fields _%> - val <%= otherEntityName %> = <%= otherEntityNameCapitalized %>ResourceIT.createEntity(<% if (databaseType === 'sql') { %>em<% } %>) - <%_ if (databaseType === 'sql') { _%> + val <%= otherEntityName %> = <%= createEntityPrefix %><%= otherEntityNameCapitalized %>ResourceIT.createEntity(<% if (databaseType === 'sql') { %>em<% } %>)<%= createEntityPostfix %> + <%_ if (databaseType === 'sql' && !reactive) { _%> em.persist(<%= otherEntityName %>) em.flush() <%_ } _%> <%_ if (databaseType === 'mongodb') { _%> - <%= otherEntityName %>.id = "fixed-id-for-tests" + <%= otherEntityName %>.<%= primaryKey.name %> = "fixed-id-for-tests" <%_ } _%> <%_ } else { _%> - val <%= otherEntityName %>: <%= otherEntityNameCapitalized %> - <%_ if (databaseType === 'sql') { _%> - if (em.findAll(<%= otherEntityNameCapitalized %>::class).isEmpty()) { - <%= otherEntityName %> = <%= otherEntityNameCapitalized %>ResourceIT.create<% if (fieldStatus === 'UPDATED_') { %>Updated<% } %>Entity(<% if (databaseType === 'sql') { %>em<% } %>) + val <%= otherEntityName %>: <%= asEntity(otherEntityNameCapitalized) %> + <%_ if (databaseType === 'sql' && !reactive) { _%> + if (em.findAll(<%= asEntity(otherEntityNameCapitalized) %>::class).isEmpty()) { + <%= otherEntityName %> = <%= createEntityPrefix %><%= otherEntityNameCapitalized %>ResourceIT.create<% if (fieldStatus === 'UPDATED_') { %>Updated<% } %>Entity(<% if (databaseType === 'sql') { %>em<% } %>)<%= createEntityPostfix %> em.persist(<%= otherEntityName %>) em.flush() } else { - <%= otherEntityName %> = em.findAll(<%= otherEntityNameCapitalized %>::class).get(0) + <%= otherEntityName %> = em.findAll(<%= asEntity(otherEntityNameCapitalized) %>::class).get(0) } <%_ } else { _%> - <%= otherEntityName %> = <%= otherEntityNameCapitalized %>ResourceIT.create<% if (fieldStatus === 'UPDATED_') { %>Updated<% } %>Entity(<% if (databaseType === 'sql') { %>em<% } %>) + <%= otherEntityName %> = <%= createEntityPrefix %><%= otherEntityNameCapitalized %>ResourceIT.create<% if (fieldStatus === 'UPDATED_') { %>Updated<% } %>Entity(<% if (databaseType === 'sql') { %>em<% } %>)<%= createEntityPostfix %> <%_ } _%> <%_ if (databaseType === 'mongodb') { _%> - <%= otherEntityName %>.id = "fixed-id-for-tests" + <%= otherEntityName %>.<%= primaryKey.name %> = "fixed-id-for-tests" <%_ } _%> <%_ } _%> <%_ } _%> <%_ if (relationshipType === 'many-to-many' || relationshipType === 'one-to-many') { _%> - <%= asEntity(entityInstance) %>.relationshipNamePlural.add(<%= otherEntityName %>); + <%= persistInstance %>.<%= relationshipNamePlural %>?.add(<%= otherEntityName %>) <%_ } else { _%> - <%= asEntity(entityInstance) %>.<%= relationshipName %> = <%= otherEntityName %> + <%= persistInstance %>.<%= relationshipName %> = <%= otherEntityName %> <%_ } _%> <%_ alreadyGeneratedEntities.push(otherEntityName) _%> <%_ } } _%> - return <%= asEntity(entityInstance) %> + return <%= persistInstance %> } <%_ }); _%> + + <%_ if (databaseType === 'sql' && reactive) { + const alreadyGeneratedDeletionCalls = []; + _%> + fun deleteEntities(em: EntityManager) { + try { + <%_ relationships.forEach(function(rel) { + if (rel.shouldWriteJoinTable) { _%> + em.deleteAll("<%= rel.joinTable.name %>").block() + <%_ }}); _%> + em.deleteAll(<%= entityClass %>::class.java).block() + } catch (e: Exception) { + // It can fail, if other entities are still referring this - it will be removed later. + } + <%_ relationships.forEach(function(rel) { + if ((rel.relationshipValidate === true || rel.id === true) && !alreadyGeneratedDeletionCalls.includes(rel.otherEntityName)) { _%> + <%= rel.otherEntityNameCapitalized %>ResourceIT.deleteEntities(em) + <%_ alreadyGeneratedDeletionCalls.push(rel.otherEntityName); + } + }); _%> + } + <%_ } _%> } } diff --git a/generators/generator-kotlin-constants.js b/generators/generator-kotlin-constants.js index 57c4efaad..17ec08a77 100644 --- a/generators/generator-kotlin-constants.js +++ b/generators/generator-kotlin-constants.js @@ -17,12 +17,13 @@ * limitations under the License. */ -const KOTLIN_VERSION = '1.3.70'; +const KOTLIN_VERSION = '1.4.21'; const MOCKITO_KOTLIN_VERSION = '2.2.0'; -const KTLINT_MAVEN_VERSION = '1.2.2'; -const KTLINT_GRADLE_VERSION = '9.4.0'; +const KTLINT_MAVEN_VERSION = '1.7.0'; +const KTLINT_GRADLE_VERSION = '9.4.1'; const DETEKT_VERSION = '1.1.0'; const MAVEN_ANTRUN_VERSION = '1.8'; +const MAPSTRUCT_VERSION = '1.4.1.Final'; const DETEKT_CONFIG_FILE = 'detekt-config.yml'; @@ -34,6 +35,7 @@ const constants = { DETEKT_VERSION, MAVEN_ANTRUN_VERSION, DETEKT_CONFIG_FILE, + MAPSTRUCT_VERSION, }; module.exports = constants; diff --git a/generators/server/files.js b/generators/server/files.js index d28e71fda..3729a0a14 100644 --- a/generators/server/files.js +++ b/generators/server/files.js @@ -17,10 +17,10 @@ * limitations under the License. */ const path = require('path'); -const mkdirp = require('mkdirp'); const cleanup = require('generator-jhipster/generators/cleanup'); const constants = require('generator-jhipster/generators/generator-constants'); const baseServerFiles = require('generator-jhipster/generators/server/files').serverFiles; +// const writeFilesToDisk = require('generator-jhipster/generators/generator-base').writeFilesToDisk; const cheerio = require('cheerio'); const kotlinConstants = require('../generator-kotlin-constants'); @@ -95,11 +95,17 @@ const serverFiles = { path: SERVER_MAIN_RES_DIR, templates: [ { + override: generator => + !generator.jhipsterConfig.incrementalChangelog || generator.configOptions.recreateInitialChangelog, file: 'config/liquibase/changelog/initial_schema.xml', renameTo: () => 'config/liquibase/changelog/00000000000000_initial_schema.xml', options: { interpolate: INTERPOLATE_REGEX }, }, - 'config/liquibase/master.xml', + { + override: generator => + !generator.jhipsterConfig.incrementalChangelog || generator.configOptions.recreateInitialChangelog, + file: 'config/liquibase/master.xml', + }, ], }, { @@ -128,8 +134,6 @@ const serverFiles = { 'config/couchmove/changelog/V0.1__initial_setup/ROLE_ADMIN.json', 'config/couchmove/changelog/V0.1__initial_setup/ROLE_USER.json', 'config/couchmove/changelog/V0.1__initial_setup/user__admin.json', - 'config/couchmove/changelog/V0.1__initial_setup/user__anonymoususer.json', - 'config/couchmove/changelog/V0.1__initial_setup/user__system.json', 'config/couchmove/changelog/V0.1__initial_setup/user__user.json', ], }, @@ -157,14 +161,6 @@ const serverFiles = { file: 'config/couchmove/changelog/V0.1__initial_setup/user__admin.json', renameTo: () => 'config/neo4j/migrations/user__admin.json', }, - { - file: 'config/couchmove/changelog/V0.1__initial_setup/user__anonymoususer.json', - renameTo: () => 'config/neo4j/migrations/user__anonymoususer.json', - }, - { - file: 'config/couchmove/changelog/V0.1__initial_setup/user__system.json', - renameTo: () => 'config/neo4j/migrations/user__system.json', - }, { file: 'config/couchmove/changelog/V0.1__initial_setup/user__user.json', renameTo: () => 'config/neo4j/migrations/user__user.json', @@ -274,7 +270,7 @@ const serverFiles = { ], }, { - condition: generator => !generator.reactive && generator.applicationType !== 'uaa', + condition: generator => !generator.reactive, path: SERVER_MAIN_KOTLIN_SRC_DIR, templates: [ { @@ -285,42 +281,16 @@ const serverFiles = { ], }, { - condition: generator => generator.reactive && generator.applicationType !== 'uaa', + condition: generator => generator.reactive, path: SERVER_MAIN_KOTLIN_SRC_DIR, templates: [ { - file: 'package/config/ReactiveSecurityConfiguration.kt', + file: 'package/config/SecurityConfiguration_reactive.kt', renameTo: generator => `${generator.javaDir}config/SecurityConfiguration.kt`, useBluePrint: true, }, ], }, - { - condition: generator => !shouldSkipUserManagement(generator) && generator.applicationType === 'uaa', - path: SERVER_MAIN_KOTLIN_SRC_DIR, - templates: [ - { - file: 'package/config/UaaWebSecurityConfiguration.kt', - renameTo: generator => `${generator.javaDir}config/UaaWebSecurityConfiguration.kt`, - useBluePrint: true, - }, - { - file: 'package/config/UaaConfiguration.kt', - renameTo: generator => `${generator.javaDir}config/UaaConfiguration.kt`, - useBluePrint: true, - }, - { - file: 'package/config/UaaProperties.kt', - renameTo: generator => `${generator.javaDir}config/UaaProperties.kt`, - useBluePrint: true, - }, - { - file: 'package/security/IatTokenEnhancer.kt', - renameTo: generator => `${generator.javaDir}security/IatTokenEnhancer.kt`, - useBluePrint: true, - }, - ], - }, { condition: generator => !shouldSkipUserManagement(generator) && generator.authenticationType === 'session' && !generator.reactive, @@ -380,6 +350,20 @@ const serverFiles = { }, ], }, + { + condition: generator => + !generator.reactive && + generator.authenticationType === 'oauth2' && + (generator.applicationType === 'microservice' || generator.applicationType === 'gateway'), + path: SERVER_TEST_SRC_KOTLIN_DIR, + templates: [ + { + file: 'package/security/oauth2/AuthorizationHeaderUtilTest.kt', + renameTo: generator => `${generator.javaDir}security/oauth2/AuthorizationHeaderUtilTest.kt`, + useBluePrint: true, + }, + ], + }, { condition: generator => !shouldSkipUserManagement(generator) && generator.authenticationType !== 'oauth2', path: SERVER_MAIN_KOTLIN_SRC_DIR, @@ -423,167 +407,44 @@ const serverFiles = { }, ], }, - ], - serverJavaGateway: [ - { - condition: generator => !generator.reactive && generator.applicationType === 'gateway' && generator.serviceDiscoveryType, - path: SERVER_MAIN_KOTLIN_SRC_DIR, - templates: [ - { - file: 'package/config/GatewayConfiguration.kt', - renameTo: generator => `${generator.javaDir}config/GatewayConfiguration.kt`, - useBluePrint: true, - }, - { - file: 'package/config/apidoc/GatewaySwaggerResourcesProvider.kt', - renameTo: generator => `${generator.javaDir}config/apidoc/GatewaySwaggerResourcesProvider.kt`, - useBluePrint: true, - }, - { - file: 'package/gateway/accesscontrol/AccessControlFilter.kt', - renameTo: generator => `${generator.javaDir}gateway/accesscontrol/AccessControlFilter.kt`, - useBluePrint: true, - }, - { - file: 'package/gateway/responserewriting/SwaggerBasePathRewritingFilter.kt', - renameTo: generator => `${generator.javaDir}gateway/responserewriting/SwaggerBasePathRewritingFilter.kt`, - useBluePrint: true, - }, - ], - }, - { - condition: generator => generator.applicationType === 'gateway' && generator.serviceDiscoveryType, - path: SERVER_MAIN_KOTLIN_SRC_DIR, - templates: [ - { - file: 'package/web/rest/vm/RouteVM.kt', - renameTo: generator => `${generator.javaDir}web/rest/vm/RouteVM.kt`, - useBluePrint: true, - }, - { - file: 'package/web/rest/GatewayResource.kt', - renameTo: generator => `${generator.javaDir}web/rest/GatewayResource.kt`, - useBluePrint: true, - }, - ], - }, - { - condition: generator => - generator.reactive && (generator.applicationType === 'gateway' || generator.applicationType === 'monolith'), - path: SERVER_MAIN_KOTLIN_SRC_DIR, - templates: [ - { - file: 'package/config/apidoc/SwaggerConfiguration.kt', - renameTo: generator => `${generator.javaDir}config/apidoc/SwaggerConfiguration.kt`, - useBluePrint: true, - }, - ], - }, { condition: generator => - generator.applicationType === 'gateway' && generator.serviceDiscoveryType && generator.cacheProvider === 'hazelcast', + !generator.reactive && generator.authenticationType === 'oauth2' && generator.applicationType === 'monolith', path: SERVER_MAIN_KOTLIN_SRC_DIR, templates: [ { - file: 'package/gateway/ratelimiting/RateLimitingFilter.kt', - renameTo: generator => `${generator.javaDir}gateway/ratelimiting/RateLimitingFilter.kt`, + file: 'package/security/oauth2/CustomClaimConverter.kt', + renameTo: generator => `${generator.javaDir}security/oauth2/CustomClaimConverter.kt`, useBluePrint: true, }, ], }, { condition: generator => - !generator.reactive && - generator.applicationType === 'gateway' && - generator.authenticationType === 'jwt' && - generator.serviceDiscoveryType, - path: SERVER_MAIN_KOTLIN_SRC_DIR, - templates: [ - { - file: 'package/gateway/TokenRelayFilter.kt', - renameTo: generator => `${generator.javaDir}gateway/TokenRelayFilter.kt`, - useBluePrint: true, - }, - ], - }, - { - condition: generator => !generator.reactive && generator.applicationType === 'gateway' && !generator.serviceDiscoveryType, - path: SERVER_MAIN_KOTLIN_SRC_DIR, + !generator.reactive && generator.authenticationType === 'oauth2' && generator.applicationType === 'monolith', + path: SERVER_TEST_SRC_KOTLIN_DIR, templates: [ { - file: 'package/web/filter/RouteDetectorFilter.kt', - renameTo: generator => `${generator.javaDir}web/filter/RouteDetectorFilter.kt`, + file: 'package/security/oauth2/CustomClaimConverterIT.kt', + renameTo: generator => `${generator.javaDir}security/oauth2/CustomClaimConverterIT.kt`, useBluePrint: true, }, ], }, + ], + serverJavaGateway: [ { - condition: generator => generator.applicationType === 'gateway' && generator.authenticationType === 'uaa', + condition: generator => generator.applicationType === 'gateway' && generator.serviceDiscoveryType, path: SERVER_MAIN_KOTLIN_SRC_DIR, templates: [ { - file: 'package/web/rest/AuthResource.kt', - renameTo: generator => `${generator.javaDir}web/rest/AuthResource.kt`, - useBluePrint: true, - }, - { - file: 'package/web/filter/RefreshTokenFilter.kt', - renameTo: generator => `${generator.javaDir}web/filter/RefreshTokenFilter.kt`, - useBluePrint: true, - }, - { - file: 'package/web/filter/RefreshTokenFilterConfigurer.kt', - renameTo: generator => `${generator.javaDir}web/filter/RefreshTokenFilterConfigurer.kt`, - useBluePrint: true, - }, - { - file: 'package/config/oauth2/OAuth2AuthenticationConfiguration.kt', - renameTo: generator => `${generator.javaDir}config/oauth2/OAuth2AuthenticationConfiguration.kt`, - useBluePrint: true, - }, - { - file: 'package/security/oauth2/CookieCollection.kt', - renameTo: generator => `${generator.javaDir}security/oauth2/CookieCollection.kt`, - useBluePrint: true, - }, - { - file: 'package/security/oauth2/CookiesHttpServletRequestWrapper.kt', - renameTo: generator => `${generator.javaDir}security/oauth2/CookiesHttpServletRequestWrapper.kt`, - useBluePrint: true, - }, - { - file: 'package/security/oauth2/CookieTokenExtractor.kt', - renameTo: generator => `${generator.javaDir}security/oauth2/CookieTokenExtractor.kt`, - useBluePrint: true, - }, - { - file: 'package/security/oauth2/OAuth2AuthenticationService.kt', - renameTo: generator => `${generator.javaDir}security/oauth2/OAuth2AuthenticationService.kt`, - useBluePrint: true, - }, - { - file: 'package/security/oauth2/OAuth2CookieHelper.kt', - renameTo: generator => `${generator.javaDir}security/oauth2/OAuth2CookieHelper.kt`, - useBluePrint: true, - }, - { - file: 'package/security/oauth2/OAuth2Cookies.kt', - renameTo: generator => `${generator.javaDir}security/oauth2/OAuth2Cookies.kt`, - useBluePrint: true, - }, - { - file: 'package/security/oauth2/OAuth2TokenEndpointClient.kt', - renameTo: generator => `${generator.javaDir}security/oauth2/OAuth2TokenEndpointClient.kt`, - useBluePrint: true, - }, - { - file: 'package/security/oauth2/OAuth2TokenEndpointClientAdapter.kt', - renameTo: generator => `${generator.javaDir}security/oauth2/OAuth2TokenEndpointClientAdapter.kt`, + file: 'package/web/rest/vm/RouteVM.kt', + renameTo: generator => `${generator.javaDir}web/rest/vm/RouteVM.kt`, useBluePrint: true, }, { - file: 'package/security/oauth2/UaaTokenEndpointClient.kt', - renameTo: generator => `${generator.javaDir}security/oauth2/UaaTokenEndpointClient.kt`, + file: 'package/web/rest/GatewayResource.kt', + renameTo: generator => `${generator.javaDir}web/rest/GatewayResource.kt`, useBluePrint: true, }, ], @@ -606,73 +467,40 @@ const serverFiles = { }, ], }, - ], - serverMicroservice: [ { - condition: generator => - generator.authenticationType === 'uaa' && - (generator.applicationType === 'microservice' || generator.applicationType === 'gateway'), + condition: generator => generator.applicationType === 'gateway' && generator.serviceDiscoveryType && generator.reactive, path: SERVER_MAIN_KOTLIN_SRC_DIR, templates: [ { - file: 'package/config/oauth2/OAuth2Properties.kt', - renameTo: generator => `${generator.javaDir}config/oauth2/OAuth2Properties.kt`, - useBluePrint: true, - }, - { - file: 'package/config/oauth2/OAuth2JwtAccessTokenConverter.kt', - renameTo: generator => `${generator.javaDir}config/oauth2/OAuth2JwtAccessTokenConverter.kt`, + file: 'package/config/apidocs/GatewaySwaggerResourcesProvider.kt', + renameTo: generator => `${generator.javaDir}config/apidocs/GatewaySwaggerResourcesProvider.kt`, useBluePrint: true, }, { - file: 'package/security/oauth2/OAuth2SignatureVerifierClient.kt', - renameTo: generator => `${generator.javaDir}security/oauth2/OAuth2SignatureVerifierClient.kt`, - useBluePrint: true, - }, - { - file: 'package/security/oauth2/UaaSignatureVerifierClient.kt', - renameTo: generator => `${generator.javaDir}security/oauth2/UaaSignatureVerifierClient.kt`, + file: 'package/web/filter/ModifyServersOpenApiFilter.kt', + renameTo: generator => `${generator.javaDir}web/filter/ModifyServersOpenApiFilter.kt`, useBluePrint: true, }, ], }, { - condition: generator => - !generator.reactive && generator.applicationType === 'microservice' && generator.authenticationType === 'uaa', - path: SERVER_MAIN_KOTLIN_SRC_DIR, + condition: generator => generator.applicationType === 'gateway' && generator.serviceDiscoveryType && generator.reactive, + path: SERVER_TEST_SRC_KOTLIN_DIR, templates: [ { - file: 'package/config/FeignConfiguration.kt', - renameTo: generator => `${generator.javaDir}config/FeignConfiguration.kt`, - useBluePrint: true, - }, - { - file: 'package/client/AuthorizedFeignClient.kt', - renameTo: generator => `${generator.javaDir}client/AuthorizedFeignClient.kt`, + file: 'package/web/filter/ModifyServersOpenApiFilterTest.kt', + renameTo: generator => `${generator.testDir}web/filter/ModifyServersOpenApiFilterTest.kt`, useBluePrint: true, }, { - file: 'package/client/OAuth2InterceptedFeignConfiguration.kt', - renameTo: generator => `${generator.javaDir}client/OAuth2InterceptedFeignConfiguration.kt`, - useBluePrint: true, - }, - { - file: 'package/client/AuthorizedUserFeignClient.kt', - renameTo: generator => `${generator.javaDir}client/AuthorizedUserFeignClient.kt`, - useBluePrint: true, - }, - { - file: 'package/client/OAuth2_UserFeignClientInterceptor.kt', - renameTo: generator => `${generator.javaDir}client/UserFeignClientInterceptor.kt`, - useBluePrint: true, - }, - { - file: 'package/client/OAuth2UserClientFeignConfiguration.kt', - renameTo: generator => `${generator.javaDir}client/OAuth2UserClientFeignConfiguration.kt`, + file: 'package/config/apidocs/GatewaySwaggerResourcesProviderTest.kt', + renameTo: generator => `${generator.testDir}config/apidocs/GatewaySwaggerResourcesProviderTest.kt`, useBluePrint: true, }, ], }, + ], + serverMicroservice: [ { condition: generator => !generator.reactive && @@ -692,21 +520,6 @@ const serverFiles = { }, ], }, - { - condition: generator => - !generator.reactive && - generator.authenticationType === 'oauth2' && - generator.applicationType === 'gateway' && - generator.serviceDiscoveryType, - path: SERVER_MAIN_KOTLIN_SRC_DIR, - templates: [ - { - file: 'package/security/oauth2/AuthorizationHeaderFilter.kt', - renameTo: generator => `${generator.javaDir}security/oauth2/AuthorizationHeaderFilter.kt`, - useBluePrint: true, - }, - ], - }, { condition: generator => !generator.reactive && @@ -742,20 +555,7 @@ const serverFiles = { ], }, { - condition: generator => !generator.reactive && generator.authenticationType === 'oauth2', - path: SERVER_MAIN_KOTLIN_SRC_DIR, - templates: [ - { - file: 'package/config/SecurityConfiguration.kt', - renameTo: generator => `${generator.javaDir}config/SecurityConfiguration.kt`, - useBluePrint: true, - }, - ], - }, - { - condition: generator => - (!generator.reactive && generator.applicationType === 'gateway' && !generator.serviceDiscoveryType) || - generator.authenticationType === 'uaa', + condition: generator => !generator.reactive && generator.applicationType === 'gateway' && !generator.serviceDiscoveryType, path: SERVER_MAIN_KOTLIN_SRC_DIR, templates: [ { @@ -766,14 +566,7 @@ const serverFiles = { ], }, { - condition: generator => - !( - generator.applicationType !== 'microservice' && - !( - generator.applicationType === 'gateway' && - (generator.authenticationType === 'uaa' || generator.authenticationType === 'oauth2') - ) - ) && generator.applicationType === 'microservice', + condition: generator => generator.applicationType === 'microservice', path: SERVER_MAIN_RES_DIR, templates: [{ file: 'static/microservices_index.html', renameTo: () => 'static/index.html' }], }, @@ -811,6 +604,26 @@ const serverFiles = { }, ], }, + { + path: SERVER_TEST_SRC_KOTLIN_DIR, + templates: [ + { + file: 'package/IntegrationTest.kt', + renameTo: generator => `${generator.testDir}/IntegrationTest.kt`, + useBluePrint: true, + }, + ], + }, + // { + // path: SERVER_MAIN_KOTLIN_SRC_DIR, + // templates: [ + // { + // file: 'package/GeneratedByJHipster.kt', + // renameTo: generator => `${generator.javaDir}GeneratedByJHipster.kt`, + // useBluePrint: true, + // }, + // ], + // }, ], serverJavaConfig: [ { @@ -933,37 +746,53 @@ const serverFiles = { ], }, { - condition: generator => - generator.databaseType === 'sql' || - generator.databaseType === 'mongodb' || - generator.databaseType === 'neo4j' || - generator.databaseType === 'couchbase', + condition: generator => generator.databaseType !== 'no', path: SERVER_MAIN_KOTLIN_SRC_DIR, templates: [ { - file: 'package/config/CloudDatabaseConfiguration.kt', - renameTo: generator => `${generator.javaDir}config/CloudDatabaseConfiguration.kt`, + file: generator => `package/config/DatabaseConfiguration_${generator.databaseType}.kt`, + renameTo: generator => `${generator.javaDir}config/DatabaseConfiguration.kt`, useBluePrint: true, }, + ], + }, + { + condition: generator => generator.databaseType === 'sql', + path: SERVER_MAIN_KOTLIN_SRC_DIR, + templates: [ { - file: 'package/config/DatabaseConfiguration.kt', - renameTo: generator => `${generator.javaDir}config/DatabaseConfiguration.kt`, + file: 'package/config/LiquibaseConfiguration.kt', + renameTo: generator => `${generator.javaDir}config/LiquibaseConfiguration.kt`, + useBluePrint: true, + }, + ], + }, + { + condition: generator => generator.databaseType === 'sql' && generator.reactive, + path: SERVER_MAIN_KOTLIN_SRC_DIR, + templates: [ + { + file: 'package/service/ColumnConverter.kt', + renameTo: generator => `${generator.javaDir}service/ColumnConverter.kt`, useBluePrint: true, }, { - file: 'package/config/audit/AuditEventConverter.kt', - renameTo: generator => `${generator.javaDir}config/audit/AuditEventConverter.kt`, + file: 'package/service/EntityManager.kt', + renameTo: generator => `${generator.javaDir}service/EntityManager.kt`, useBluePrint: true, }, ], }, { - condition: generator => generator.databaseType === 'sql', + condition: generator => + generator.databaseType === 'sql' && + generator.reactive && + (!generator.skipUserManagement || generator.authenticationType === 'oauth2'), path: SERVER_MAIN_KOTLIN_SRC_DIR, templates: [ { - file: 'package/config/LiquibaseConfiguration.kt', - renameTo: generator => `${generator.javaDir}config/LiquibaseConfiguration.kt`, + file: 'package/repository/rowmapper/UserRowMapper.kt', + renameTo: generator => `${generator.javaDir}repository/rowmapper/UserRowMapper.kt`, useBluePrint: true, }, ], @@ -1011,12 +840,12 @@ const serverFiles = { path: SERVER_MAIN_KOTLIN_SRC_DIR, templates: [ { - file: 'package/repository/reactive/ReactiveN1qlCouchbaseRepository.kt', + file: 'package/repository/ReactiveN1qlCouchbaseRepository.kt', renameTo: generator => `${generator.javaDir}repository/ReactiveN1qlCouchbaseRepository.kt`, useBluePrint: true, }, { - file: 'package/repository/reactive/CustomReactiveN1qlCouchbaseRepository.kt', + file: 'package/repository/CustomReactiveN1qlCouchbaseRepository.kt', renameTo: generator => `${generator.javaDir}repository/CustomReactiveN1qlCouchbaseRepository.kt`, useBluePrint: true, }, @@ -1038,33 +867,6 @@ const serverFiles = { }, ], }, - { - condition: generator => generator.databaseType === 'cassandra', - path: SERVER_MAIN_KOTLIN_SRC_DIR, - templates: [ - { - file: 'package/config/metrics/JHipsterHealthIndicatorConfiguration.kt', - renameTo: generator => `${generator.javaDir}config/metrics/JHipsterHealthIndicatorConfiguration.kt`, - useBluePrint: true, - }, - { - file: 'package/config/metrics/CassandraHealthIndicator.kt', - renameTo: generator => `${generator.javaDir}config/metrics/CassandraHealthIndicator.kt`, - useBluePrint: true, - }, - ], - }, - { - condition: generator => generator.databaseType === 'cassandra', - path: SERVER_MAIN_KOTLIN_SRC_DIR, - templates: [ - { - file: 'package/config/cassandra/CassandraConfiguration.kt', - renameTo: generator => `${generator.javaDir}config/cassandra/CassandraConfiguration.kt`, - useBluePrint: true, - }, - ], - }, { condition: generator => generator.searchEngine === 'elasticsearch', path: SERVER_MAIN_KOTLIN_SRC_DIR, @@ -1076,17 +878,6 @@ const serverFiles = { }, ], }, - { - condition: generator => generator.searchEngine === 'elasticsearch', - path: SERVER_TEST_SRC_KOTLIN_DIR, - templates: [ - { - file: 'package/config/ElasticsearchTestConfiguration.kt', - renameTo: generator => `${generator.testDir}config/ElasticsearchTestConfiguration.kt`, - useBluePrint: true, - }, - ], - }, ], serverJavaDomain: [ { @@ -1098,11 +889,6 @@ const serverFiles = { renameTo: generator => `${generator.javaDir}domain/AbstractAuditingEntity.kt`, useBluePrint: true, }, - { - file: 'package/domain/PersistentAuditEvent.kt', - renameTo: generator => `${generator.javaDir}domain/PersistentAuditEvent.kt`, - useBluePrint: true, - }, ], }, ], @@ -1245,6 +1031,24 @@ const serverFiles = { ], }, ], + serverTestReactive: [ + { + condition: generator => generator.reactive, + path: SERVER_TEST_SRC_KOTLIN_DIR, + templates: [ + { + file: 'package/config/JHipsterBlockHoundIntegration.kt', + renameTo: generator => `${generator.testDir}config/JHipsterBlockHoundIntegration.kt`, + useBluePrint: true, + }, + ], + }, + { + condition: generator => generator.reactive, + path: SERVER_TEST_RES_DIR, + templates: ['META-INF/services/reactor.blockhound.integration.BlockHoundIntegration'], + }, + ], serverTestFw: [ { condition: generator => generator.databaseType === 'cassandra', @@ -1260,11 +1064,6 @@ const serverFiles = { renameTo: generator => `${generator.testDir}AbstractCassandraTest.kt`, useBluePrint: true, }, - { - file: 'package/config/CassandraConfigurationIT.kt', - renameTo: generator => `${generator.testDir}config/CassandraConfigurationIT.kt`, - useBluePrint: true, - }, ], }, { @@ -1355,6 +1154,17 @@ const serverFiles = { path: SERVER_TEST_RES_DIR, templates: [{ file: 'testcontainers/mariadb/my.cnf', method: 'copy', noEjs: true }], }, + { + condition: generator => generator.reactiveSqlTestContainers, + path: SERVER_TEST_SRC_KOTLIN_DIR, + templates: [ + { + file: 'package/ReactiveSqlTestContainerExtension.kt', + renameTo: generator => `${generator.testDir}ReactiveSqlTestContainerExtension.kt`, + useBluePrint: true, + }, + ], + }, { // TODO : add these tests to reactive condition: generator => !generator.reactive, @@ -1384,75 +1194,15 @@ const serverFiles = { }, ], }, - { - condition: generator => !generator.reactive && generator.applicationType === 'gateway' && generator.serviceDiscoveryType, - path: SERVER_TEST_SRC_KOTLIN_DIR, - templates: [ - // Create Gateway tests files - { - file: 'package/gateway/responserewriting/SwaggerBasePathRewritingFilterTest.kt', - renameTo: generator => `${generator.testDir}gateway/responserewriting/SwaggerBasePathRewritingFilterTest.kt`, - useBluePrint: true, - }, - ], - }, { condition: generator => generator.serviceDiscoveryType, path: SERVER_TEST_RES_DIR, templates: ['config/bootstrap.yml'], }, - { - condition: generator => generator.authenticationType === 'uaa', - path: SERVER_TEST_SRC_KOTLIN_DIR, - templates: [ - { - file: 'package/config/OAuth2TestConfiguration.kt', - renameTo: generator => `${generator.testDir}config/OAuth2TestConfiguration.kt`, - useBluePrint: true, - }, - { - file: 'package/security/OAuth2TokenMockUtil.kt', - renameTo: generator => `${generator.testDir}security/OAuth2TokenMockUtil.kt`, - useBluePrint: true, - }, - { - file: 'package/config/SecurityBeanOverrideConfiguration.kt', - renameTo: generator => `${generator.testDir}config/SecurityBeanOverrideConfiguration.kt`, - useBluePrint: true, - }, - ], - }, - { - condition: generator => generator.authenticationType === 'uaa' && generator.applicationType === 'gateway', - path: SERVER_TEST_SRC_KOTLIN_DIR, - templates: [ - { - file: 'package/security/oauth2/OAuth2CookieHelperTest.kt', - renameTo: generator => `${generator.testDir}security/oauth2/OAuth2CookieHelperTest.kt`, - useBluePrint: true, - }, - { - file: 'package/security/oauth2/OAuth2AuthenticationServiceTest.kt', - renameTo: generator => `${generator.testDir}security/oauth2/OAuth2AuthenticationServiceTest.kt`, - useBluePrint: true, - }, - { - file: 'package/security/oauth2/CookieTokenExtractorTest.kt', - renameTo: generator => `${generator.testDir}security/oauth2/CookieTokenExtractorTest.kt`, - useBluePrint: true, - }, - { - file: 'package/security/oauth2/CookieCollectionTest.kt', - renameTo: generator => `${generator.testDir}security/oauth2/CookieCollectionTest.kt`, - useBluePrint: true, - }, - ], - }, { condition: generator => generator.authenticationType === 'oauth2' && - (generator.applicationType === 'monolith' || generator.applicationType === 'gateway') && - !generator.reactive, + (generator.applicationType === 'monolith' || generator.applicationType === 'gateway'), path: SERVER_TEST_SRC_KOTLIN_DIR, templates: [ { @@ -1463,15 +1213,7 @@ const serverFiles = { ], }, { - condition: generator => { - if (generator.gatlingTests) { - mkdirp(`${TEST_DIR}gatling/user-files/data`); - mkdirp(`${TEST_DIR}gatling/user-files/bodies`); - mkdirp(`${TEST_DIR}gatling/user-files/simulations`); - return true; - } - return false; - }, + condition: generator => generator.gatlingTests, path: TEST_DIR, templates: [ // Create Gatling test files @@ -1495,16 +1237,17 @@ const serverFiles = { renameTo: generator => `${generator.testDir}cucumber/stepdefs/StepDefs.kt`, }, { - file: 'package/cucumber/CucumberContextConfiguration.kt', - renameTo: generator => `${generator.testDir}cucumber/CucumberContextConfiguration.kt`, + file: 'package/cucumber/CucumberTestContextConfiguration.kt', + renameTo: generator => `${generator.testDir}cucumber/CucumberTestContextConfiguration.kt`, useBluePrint: true, }, + { file: '../features/gitkeep', noEjs: true }, ], }, { condition: generator => generator.cucumberTests, - path: SERVER_TEST_SRC_DIR, - templates: [{ file: '../features/gitkeep', noEjs: true }], + path: SERVER_TEST_RES_DIR, + templates: ['cucumber.properties'], }, { condition: generator => !shouldSkipUserManagement(generator) && generator.authenticationType !== 'oauth2', @@ -1532,6 +1275,33 @@ const serverFiles = { }, ], serverJavaUserManagement: [ + { + condition: generator => generator.isUsingBuiltInUser(), + path: SERVER_MAIN_KOTLIN_SRC_DIR, + templates: [ + { + file: 'package/domain/User.kt', + renameTo: generator => `${generator.javaDir}domain/${generator.asEntity('User')}.kt`, + useBluePrint: true, + }, + ], + }, + { + condition: generator => generator.isUsingBuiltInAuthority(), + path: SERVER_MAIN_KOTLIN_SRC_DIR, + templates: [ + { + file: 'package/domain/Authority.kt', + renameTo: generator => `${generator.javaDir}domain/Authority.kt`, + useBluePrint: true, + }, + { + file: 'package/repository/AuthorityRepository.kt', + renameTo: generator => `${generator.javaDir}repository/AuthorityRepository.kt`, + useBluePrint: true, + }, + ], + }, { condition: generator => (generator.authenticationType === 'oauth2' && generator.applicationType !== 'microservice') || @@ -1562,6 +1332,11 @@ const serverFiles = { renameTo: generator => `${generator.javaDir}service/UserService.kt`, useBluePrint: true, }, + { + file: 'package/service/dto/AdminUserDTO.kt', + renameTo: generator => `${generator.javaDir}service/dto/${generator.asDto('AdminUser')}.kt`, + useBluePrint: true, + }, { file: 'package/service/dto/UserDTO.kt', renameTo: generator => `${generator.javaDir}service/dto/${generator.asDto('User')}.kt`, @@ -1573,16 +1348,6 @@ const serverFiles = { condition: generator => generator.authenticationType === 'oauth2' && generator.databaseType !== 'no', path: SERVER_MAIN_KOTLIN_SRC_DIR, templates: [ - { - file: 'package/domain/User.kt', - renameTo: generator => `${generator.javaDir}domain/${generator.asEntity('User')}.kt`, - useBluePrint: true, - }, - { - file: 'package/domain/Authority.kt', - renameTo: generator => `${generator.javaDir}domain/Authority.kt`, - useBluePrint: true, - }, { file: 'package/service/mapper/UserMapper.kt', renameTo: generator => `${generator.javaDir}service/mapper/UserMapper.kt`, @@ -1594,13 +1359,13 @@ const serverFiles = { useBluePrint: true, }, { - file: 'package/repository/AuthorityRepository.kt', - renameTo: generator => `${generator.javaDir}repository/AuthorityRepository.kt`, + file: 'package/web/rest/UserResource.kt', + renameTo: generator => `${generator.javaDir}web/rest/UserResource.kt`, useBluePrint: true, }, { - file: 'package/web/rest/UserResource.kt', - renameTo: generator => `${generator.javaDir}web/rest/UserResource.kt`, + file: 'package/web/rest/PublicUserResource.kt', + renameTo: generator => `${generator.javaDir}web/rest/PublicUserResource.kt`, useBluePrint: true, }, { @@ -1611,10 +1376,7 @@ const serverFiles = { ], }, { - condition: generator => - generator.skipUserManagement && - generator.authenticationType !== 'uaa' && - ['monolith', 'gateway'].includes(generator.applicationType), + condition: generator => generator.skipUserManagement && ['monolith', 'gateway'].includes(generator.applicationType), path: SERVER_MAIN_KOTLIN_SRC_DIR, templates: [ { @@ -1644,6 +1406,11 @@ const serverFiles = { renameTo: generator => `${generator.testDir}service/mapper/UserMapperTest.kt`, useBluePrint: true, }, + { + file: 'package/web/rest/PublicUserResourceIT.kt', + renameTo: generator => `${generator.testDir}web/rest/PublicUserResourceIT.kt`, + useBluePrint: true, + }, { file: 'package/web/rest/UserResourceIT.kt', renameTo: generator => `${generator.testDir}web/rest/UserResourceIT.kt`, @@ -1654,102 +1421,63 @@ const serverFiles = { { condition: generator => generator.skipUserManagement && - generator.authenticationType !== 'uaa' && + generator.authenticationType !== 'oauth2' && ['monolith', 'gateway'].includes(generator.applicationType), path: SERVER_TEST_SRC_KOTLIN_DIR, templates: [ { - file: 'package/web/rest/AccountResourceIT.kt', + file: 'package/web/rest/AccountResourceIT_skipUserManagement.kt', renameTo: generator => `${generator.testDir}web/rest/AccountResourceIT.kt`, useBluePrint: true, }, ], }, - { - condition: generator => generator.authenticationType === 'oauth2' && generator.searchEngine === 'elasticsearch', - path: SERVER_MAIN_KOTLIN_SRC_DIR, - templates: [ - { - file: 'package/repository/search/UserSearchRepository.kt', - renameTo: generator => `${generator.javaDir}repository/search/UserSearchRepository.kt`, - useBluePrint: true, - }, - ], - }, - { - condition: generator => generator.authenticationType === 'oauth2' && generator.searchEngine === 'elasticsearch', - path: SERVER_TEST_SRC_KOTLIN_DIR, - templates: [ - { - file: 'package/repository/search/UserSearchRepositoryMockConfiguration.kt', - renameTo: generator => `${generator.testDir}repository/search/UserSearchRepositoryMockConfiguration.kt`, - useBluePrint: true, - }, - ], - }, { condition: generator => - generator.authenticationType === 'oauth2' && ['sql', 'mongodb', 'couchbase', 'neo4j'].includes(generator.databaseType), - path: SERVER_MAIN_KOTLIN_SRC_DIR, + generator.skipUserManagement && + generator.authenticationType === 'oauth2' && + ['monolith', 'gateway'].includes(generator.applicationType), + path: SERVER_TEST_SRC_KOTLIN_DIR, templates: [ { - file: 'package/repository/AuthorityRepository.kt', - renameTo: generator => `${generator.javaDir}repository/AuthorityRepository.kt`, - useBluePrint: true, - }, - { - file: 'package/repository/PersistenceAuditEventRepository.kt', - renameTo: generator => `${generator.javaDir}repository/PersistenceAuditEventRepository.kt`, - useBluePrint: true, - }, - { - file: 'package/service/AuditEventService.kt', - renameTo: generator => `${generator.javaDir}service/AuditEventService.kt`, - useBluePrint: true, - }, - { - file: 'package/web/rest/AuditResource.kt', - renameTo: generator => `${generator.javaDir}web/rest/AuditResource.kt`, + file: 'package/web/rest/AccountResourceIT_oauth2.kt', + renameTo: generator => `${generator.testDir}web/rest/AccountResourceIT.kt`, useBluePrint: true, }, ], }, { condition: generator => - !generator.reactive && + generator.skipUserManagement && generator.authenticationType === 'oauth2' && - ['sql', 'mongodb', 'couchbase', 'neo4j'].includes(generator.databaseType), - path: SERVER_MAIN_KOTLIN_SRC_DIR, + ['monolith', 'gateway'].includes(generator.applicationType), + path: SERVER_TEST_SRC_KOTLIN_DIR, templates: [ { - file: 'package/repository/CustomAuditEventRepository.kt', - renameTo: generator => `${generator.javaDir}repository/CustomAuditEventRepository.kt`, + file: 'package/web/rest/AccountResourceIT_oauth2.kt', + renameTo: generator => `${generator.testDir}web/rest/AccountResourceIT.kt`, useBluePrint: true, }, ], }, { - condition: generator => - !generator.reactive && - generator.authenticationType === 'oauth2' && - ['sql', 'mongodb', 'couchbase', 'neo4j'].includes(generator.databaseType), - path: SERVER_TEST_SRC_KOTLIN_DIR, + condition: generator => generator.authenticationType === 'oauth2' && generator.searchEngine === 'elasticsearch', + path: SERVER_MAIN_KOTLIN_SRC_DIR, templates: [ { - file: 'package/repository/CustomAuditEventRepositoryIT.kt', - renameTo: generator => `${generator.testDir}repository/CustomAuditEventRepositoryIT.kt`, + file: 'package/repository/search/UserSearchRepository.kt', + renameTo: generator => `${generator.javaDir}repository/search/UserSearchRepository.kt`, useBluePrint: true, }, ], }, { - condition: generator => - generator.authenticationType === 'oauth2' && ['sql', 'mongodb', 'couchbase', 'neo4j'].includes(generator.databaseType), + condition: generator => generator.authenticationType === 'oauth2' && generator.searchEngine === 'elasticsearch', path: SERVER_TEST_SRC_KOTLIN_DIR, templates: [ { - file: 'package/web/rest/AuditResourceIT.kt', - renameTo: generator => `${generator.testDir}web/rest/AuditResourceIT.kt`, + file: 'package/repository/search/UserSearchRepositoryMockConfiguration.kt', + renameTo: generator => `${generator.testDir}repository/search/UserSearchRepositoryMockConfiguration.kt`, useBluePrint: true, }, ], @@ -1763,62 +1491,11 @@ const serverFiles = { 'templates/mail/passwordResetEmail.html', ], }, - { - condition: generator => - !generator.skipUserManagement && ['sql', 'mongodb', 'couchbase', 'neo4j'].includes(generator.databaseType), - path: SERVER_MAIN_KOTLIN_SRC_DIR, - templates: [ - { - file: 'package/domain/Authority.kt', - renameTo: generator => `${generator.javaDir}domain/Authority.kt`, - useBluePrint: true, - }, - { - file: 'package/repository/AuthorityRepository.kt', - renameTo: generator => `${generator.javaDir}repository/AuthorityRepository.kt`, - useBluePrint: true, - }, - { - file: 'package/repository/PersistenceAuditEventRepository.kt', - renameTo: generator => `${generator.javaDir}repository/PersistenceAuditEventRepository.kt`, - useBluePrint: true, - }, - { - file: 'package/service/AuditEventService.kt', - renameTo: generator => `${generator.javaDir}service/AuditEventService.kt`, - useBluePrint: true, - }, - { - file: 'package/web/rest/AuditResource.kt', - renameTo: generator => `${generator.javaDir}web/rest/AuditResource.kt`, - useBluePrint: true, - }, - ], - }, - { - condition: generator => - !generator.reactive && - !generator.skipUserManagement && - ['sql', 'mongodb', 'couchbase', 'neo4j'].includes(generator.databaseType), - path: SERVER_MAIN_KOTLIN_SRC_DIR, - templates: [ - { - file: 'package/repository/CustomAuditEventRepository.kt', - renameTo: generator => `${generator.javaDir}repository/CustomAuditEventRepository.kt`, - useBluePrint: true, - }, - ], - }, { condition: generator => !generator.skipUserManagement, path: SERVER_MAIN_KOTLIN_SRC_DIR, templates: [ /* User management java domain files */ - { - file: 'package/domain/User.kt', - renameTo: generator => `${generator.javaDir}domain/${generator.asEntity('User')}.kt`, - useBluePrint: true, - }, { file: 'package/repository/UserRepository.kt', renameTo: generator => `${generator.javaDir}repository/UserRepository.kt`, @@ -1836,6 +1513,11 @@ const serverFiles = { renameTo: generator => `${generator.javaDir}service/MailService.kt`, useBluePrint: true, }, + { + file: 'package/service/dto/AdminUserDTO.kt', + renameTo: generator => `${generator.javaDir}service/dto/${generator.asDto('AdminUser')}.kt`, + useBluePrint: true, + }, /* User management java web files */ { @@ -1863,6 +1545,11 @@ const serverFiles = { renameTo: generator => `${generator.javaDir}web/rest/UserResource.kt`, useBluePrint: true, }, + { + file: 'package/web/rest/PublicUserResource.kt', + renameTo: generator => `${generator.javaDir}web/rest/PublicUserResource.kt`, + useBluePrint: true, + }, { file: 'package/web/rest/vm/KeyAndPasswordVM.kt', renameTo: generator => `${generator.javaDir}web/rest/vm/KeyAndPasswordVM.kt`, @@ -1924,38 +1611,6 @@ const serverFiles = { }, ], }, - { - // TODO : add tests for reactive - condition: generator => - !generator.skipUserManagement && ['sql', 'mongodb', 'couchbase', 'neo4j'].includes(generator.databaseType), - path: SERVER_TEST_SRC_KOTLIN_DIR, - templates: [ - { - file: 'package/web/rest/AuditResourceIT.kt', - renameTo: generator => `${generator.testDir}web/rest/AuditResourceIT.kt`, - useBluePrint: true, - }, - { - file: 'package/service/AuditEventServiceIT.kt', - renameTo: generator => `${generator.testDir}service/AuditEventServiceIT.kt`, - useBluePrint: true, - }, - ], - }, - { - condition: generator => - !generator.reactive && - !generator.skipUserManagement && - ['sql', 'mongodb', 'couchbase', 'neo4j'].includes(generator.databaseType), - path: SERVER_TEST_SRC_KOTLIN_DIR, - templates: [ - { - file: 'package/repository/CustomAuditEventRepositoryIT.kt', - renameTo: generator => `${generator.testDir}repository/CustomAuditEventRepositoryIT.kt`, - useBluePrint: true, - }, - ], - }, { condition: generator => !generator.skipUserManagement && generator.cucumberTests, path: SERVER_TEST_SRC_KOTLIN_DIR, @@ -2001,13 +1656,13 @@ const serverFiles = { useBluePrint: true, }, { - file: 'package/web/rest/AccountResourceIT.kt', - renameTo: generator => `${generator.testDir}web/rest/AccountResourceIT.kt`, + file: 'package/config/NoOpMailConfiguration.kt', + renameTo: generator => `${generator.testDir}config/NoOpMailConfiguration.kt`, useBluePrint: true, }, { - file: 'package/config/NoOpMailConfiguration.kt', - renameTo: generator => `${generator.testDir}config/NoOpMailConfiguration.kt`, + file: 'package/web/rest/PublicUserResourceIT.kt', + renameTo: generator => `${generator.testDir}web/rest/PublicUserResourceIT.kt`, useBluePrint: true, }, { @@ -2017,6 +1672,28 @@ const serverFiles = { }, ], }, + { + condition: generator => !generator.skipUserManagement && generator.authenticationType !== 'oauth2', + path: SERVER_TEST_SRC_KOTLIN_DIR, + templates: [ + { + file: 'package/web/rest/AccountResourceIT.kt', + renameTo: generator => `${generator.testDir}web/rest/AccountResourceIT.kt`, + useBluePrint: true, + }, + ], + }, + { + condition: generator => !generator.skipUserManagement && generator.authenticationType === 'oauth2', + path: SERVER_TEST_SRC_KOTLIN_DIR, + templates: [ + { + file: 'package/web/rest/AccountResourceIT_oauth2.kt', + renameTo: generator => `${generator.testDir}web/rest/AccountResourceIT.kt`, + useBluePrint: true, + }, + ], + }, { condition: generator => !generator.skipUserManagement && generator.authenticationType !== 'oauth2', path: SERVER_TEST_SRC_KOTLIN_DIR, @@ -2038,9 +1715,6 @@ function writeFiles() { this.javaDir = `${this.packageFolder}/`; this.testDir = `${this.packageFolder}/`; - // Create server resource files - mkdirp(SERVER_MAIN_RES_DIR); - mkdirp(`${SERVER_TEST_SRC_KOTLIN_DIR}/${this.testDir}`); this.generateKeyStore(); }, @@ -2055,12 +1729,15 @@ function writeFiles() { }, writeFiles() { - writeFilesToDisk(serverFiles, this, false, this.fetchFromInstalledJHipster('server/templates')); + // writeFilesToDisk(serverFiles, this, false, this.fetchFromInstalledJHipster('server/templates')); + + return this.writeFilesToDisk(serverFiles); }, modifyFiles() { if (this.buildTool === 'gradle') { this.addGradleProperty('kotlin_version', kotlinConstants.KOTLIN_VERSION); + this.addGradleProperty('mapstruct_version', kotlinConstants.MAPSTRUCT_VERSION); this.addGradleProperty('detekt_version', kotlinConstants.DETEKT_VERSION); this.addGradlePlugin('org.jetbrains.kotlin', 'kotlin-gradle-plugin', '${kotlin_version}'); this.addGradlePlugin('org.jetbrains.kotlin', 'kotlin-allopen', '${kotlin_version}'); @@ -2077,6 +1754,7 @@ function writeFiles() { this.addMavenPluginRepository('jcenter', 'https://jcenter.bintray.com/'); this.addMavenProperty('kotlin.version', kotlinConstants.KOTLIN_VERSION); + this.addMavenProperty('mapstruct.version', kotlinConstants.MAPSTRUCT_VERSION); this.addMavenProperty('ktlint-maven-plugin.version', kotlinConstants.KTLINT_MAVEN_VERSION); this.addMavenProperty('maven-antrun-plugin.version', kotlinConstants.MAVEN_ANTRUN_VERSION); this.addMavenProperty('detekt.version', kotlinConstants.DETEKT_VERSION); @@ -2086,7 +1764,12 @@ function writeFiles() { this.addMavenProperty('sonar.coverage.jacoco.xmlReportPaths', '${jacoco.reportFolder}/jacoco.xml'); this.addMavenDependencyManagement('org.jetbrains.kotlin', 'kotlin-stdlib', '${kotlin.version}'); - this.addMavenDependencyManagement('org.jetbrains.kotlin', 'kotlin-stdlib-jdk7', '${kotlin.version}'); + this.addMavenDependencyManagement('org.jetbrains.kotlin', 'kotlin-stdlib-jdk8', '${kotlin.version}'); + + this.addMavenDependency('org.jetbrains.kotlinx', 'kotlinx-coroutines-debug'); + this.addMavenDependency('org.jetbrains.kotlinx', 'kotlinx-coroutines-reactor'); + this.addMavenDependency('io.projectreactor.kotlin', 'reactor-kotlin-extensions'); + this.addMavenDependency('com.fasterxml.jackson.datatype', 'jackson-datatype-json-org'); this.addMavenDependency('org.jetbrains.kotlin', 'kotlin-stdlib-jdk8', '${kotlin.version}'); this.addMavenDependency('org.jetbrains.kotlin', 'kotlin-reflect', '${kotlin.version}'); @@ -2115,24 +1798,34 @@ function writeFiles() { $\{project.basedir}/src/main/java - + org.mapstruct mapstruct-processor $\{mapstruct.version} - + ${ this.databaseType === 'sql' ? ` - + org.hibernate hibernate-jpamodelgen $\{hibernate.version} - - + + org.glassfish.jaxb jaxb-runtime $\{jaxb-runtime.version} - ` + ` + : '' + } + ${ + this.databaseType === 'cassandra' + ? ` + + com.datastax.oss + java-driver-mapper-processor + $\{cassandra-driver.version} + ` : '' } @@ -2303,7 +1996,7 @@ function writeFiles() { * @param {boolean} returnFiles - weather to return the generated file list or to write them * @param {string} prefix - prefix to add in the path */ -function writeFilesToDisk(files, generator, returnFiles, prefix) { +/* function writeFilesToDisk(files, generator, returnFiles, prefix) { const _this = generator || this; const filesOut = []; const startTime = new Date(); @@ -2363,7 +2056,7 @@ function writeFilesToDisk(files, generator, returnFiles, prefix) { } _this.debug(`Time taken to write files: ${new Date() - startTime}ms`); return filesOut; -} +} */ /** * Manually updates the pom.xml file to perform the following operations: @@ -2393,6 +2086,6 @@ function updatePom(generator) { module.exports = { writeFiles, - writeFilesToDisk, + // writeFilesToDisk, serverFiles, }; diff --git a/generators/server/index.js b/generators/server/index.js index 3e14d65c0..6e3e9bf24 100644 --- a/generators/server/index.js +++ b/generators/server/index.js @@ -19,7 +19,6 @@ /* eslint-disable consistent-return */ const os = require('os'); -const chalk = require('chalk'); const shelljs = require('shelljs'); const ServerGenerator = require('generator-jhipster/generators/server'); const writeFiles = require('./files').writeFiles; @@ -29,23 +28,16 @@ module.exports = class extends ServerGenerator { constructor(args, opts) { super(args, { fromBlueprint: true, ...opts }); // fromBlueprint variable is important - const jhContext = (this.jhipsterContext = this.options.jhipsterContext || opts.jhipsterContext); - + const jhContext = (this.jhipsterContext = this.options.jhipsterContext); if (!jhContext) { - this.error(`This is a JHipster blueprint and should be used only like ${chalk.yellow('jhipster --blueprint kotlin')}`); + this.error("This is a JHipster blueprint and should be used only like 'jhipster --blueprints myblueprint')}"); } - - this.configOptions = jhContext.configOptions || {}; - // This adds support for a `--skip-ktlint-format` flag this.option('skip-ktlint-format', { desc: 'Indicates to skip formatting using ktlint', type: Boolean, defaults: false, }); - - // This sets up options for this sub generator and is being reused from JHipster - jhContext.setupServerOptions(this, jhContext); } get initializing() { @@ -79,6 +71,11 @@ module.exports = class extends ServerGenerator { return writeFiles(); } + get postWriting() { + // Here we are not overriding this phase and hence its being handled by JHipster + return super._postWriting(); + } + get install() { const phaseFromJHipster = super._install(); const myCustomPhaseSteps = { diff --git a/generators/server/templates/gradle/kotlin.gradle.ejs b/generators/server/templates/gradle/kotlin.gradle.ejs index 9d20e477b..fca193a79 100644 --- a/generators/server/templates/gradle/kotlin.gradle.ejs +++ b/generators/server/templates/gradle/kotlin.gradle.ejs @@ -34,10 +34,19 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlin_version}" implementation "org.jetbrains.kotlin:kotlin-reflect:${kotlin_version}" - kapt "org.mapstruct:mapstruct-processor:${mapstruct_version}" + <%_ if (reactive) { _%> + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-debug" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-reactor" + implementation "io.projectreactor.kotlin:reactor-kotlin-extensions" + <%_ } _%> + + kapt "org.mapstruct:mapstruct-processor:${mapstructVersion}" <%_ if (databaseType === 'sql') { _%> - kapt "org.hibernate:hibernate-jpamodelgen:${hibernate_version}" - kapt "org.glassfish.jaxb:jaxb-runtime:${jaxb_runtime_version}" + kapt "org.hibernate:hibernate-jpamodelgen:${hibernateVersion}" + kapt "org.glassfish.jaxb:jaxb-runtime:${jaxbRuntimeVersion}" + <%_ } _%> + <%_ if (databaseType === 'cassandra') { _%> + kapt "com.datastax.oss:java-driver-mapper-processor:${cassandraDriverVersion}" <%_ } _%> testImplementation "org.jetbrains.kotlin:kotlin-test-junit:${kotlin_version}" diff --git a/generators/server/templates/src/main/kotlin/package/Application.kt.ejs b/generators/server/templates/src/main/kotlin/package/Application.kt.ejs index 3148d7fb5..e44528503 100644 --- a/generators/server/templates/src/main/kotlin/package/Application.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/Application.kt.ejs @@ -18,13 +18,10 @@ -%> package <%= packageName %> -<%_ if (applicationType === 'microservice' && authenticationType === 'uaa') { _%> -import <%= packageName %>.client.OAuth2InterceptedFeignConfiguration -<%_ } _%> import <%= packageName %>.config.ApplicationProperties -import io.github.jhipster.config.DefaultProfileUtil +import tech.jhipster.config.DefaultProfileUtil -import io.github.jhipster.config.JHipsterConstants +import tech.jhipster.config.JHipsterConstants import org.slf4j.LoggerFactory import org.springframework.boot.runApplication @@ -33,32 +30,14 @@ import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties <%_ } _%> import org.springframework.boot.context.properties.EnableConfigurationProperties -<%_ if (applicationType === 'gateway' && !reactive) { _%> -import org.springframework.cloud.netflix.zuul.EnableZuulProxy -<%_ } _%> -<%_ if (applicationType === 'microservice' && authenticationType === 'uaa') { _%> -import org.springframework.context.annotation.ComponentScan -import org.springframework.context.annotation.FilterType -<%_ } _%> import org.springframework.core.env.Environment import javax.annotation.PostConstruct import java.net.InetAddress import java.net.UnknownHostException -<%_ if (applicationType === 'microservice' && authenticationType === 'uaa') { _%> -@ComponentScan( - excludeFilters = [ComponentScan.Filter( - type = FilterType.ASSIGNABLE_TYPE, - classes = [OAuth2InterceptedFeignConfiguration::class] - )] -) -<%_ } _%> @SpringBootApplication @EnableConfigurationProperties(<% if (databaseType === 'sql') { %>LiquibaseProperties::class, <% } %>ApplicationProperties::class) -<%_ if (applicationType === 'gateway' && !reactive) { _%> -@EnableZuulProxy -<%_ } _%> class <%= mainClass %>(private val env: Environment) { private val log = LoggerFactory.getLogger(javaClass) @@ -129,7 +108,7 @@ class <%= mainClass %>(private val env: Environment) { ---------------------------------------------------------- """.trimIndent() ) - <%_ if (serviceDiscoveryType && (applicationType === 'microservice' || applicationType === 'gateway' || applicationType === 'uaa')) { _%> + <%_ if (serviceDiscoveryType && (applicationType === 'microservice' || applicationType === 'gateway')) { _%> val configServerStatus = env.getProperty("configserver.status") diff --git a/generators/server/templates/src/main/kotlin/package/ApplicationWebXml.kt.ejs b/generators/server/templates/src/main/kotlin/package/ApplicationWebXml.kt.ejs index 11c3b2ae1..5453a88a2 100644 --- a/generators/server/templates/src/main/kotlin/package/ApplicationWebXml.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/ApplicationWebXml.kt.ejs @@ -18,7 +18,7 @@ -%> package <%= packageName %> -import io.github.jhipster.config.DefaultProfileUtil +import tech.jhipster.config.DefaultProfileUtil import org.springframework.boot.builder.SpringApplicationBuilder import org.springframework.boot.web.servlet.support.SpringBootServletInitializer diff --git a/generators/server/templates/src/main/kotlin/package/config/metrics/JHipsterHealthIndicatorConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/GeneratedByJHipster.kt.ejs similarity index 50% rename from generators/server/templates/src/main/kotlin/package/config/metrics/JHipsterHealthIndicatorConfiguration.kt.ejs rename to generators/server/templates/src/main/kotlin/package/GeneratedByJHipster.kt.ejs index 84adbf0c9..8eba253f6 100644 --- a/generators/server/templates/src/main/kotlin/package/config/metrics/JHipsterHealthIndicatorConfiguration.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/GeneratedByJHipster.kt.ejs @@ -1,10 +1,10 @@ <%# Copyright 2013-2020 the original author or authors from the JHipster project. - This file is part of the JHipster project, see https://www.jhipster.tech/ +This file is part of the JHipster project, see https://jhipster.github.io/ for more information. - Licensed under the Apache License, Version 2.0 (the "License"); + Licensed under the Apache License, Version 2.0 (the "License") you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -16,16 +16,17 @@ See the License for the specific language governing permissions and limitations under the License. -%> -package <%= packageName %>.config.metrics +package <%= packageName %> -import com.datastax.driver.core.Session -import org.springframework.boot.actuate.health.HealthIndicator -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration +import java.lang.annotation.ElementType +import java.lang.annotation.Retention +import java.lang.annotation.RetentionPolicy +import java.lang.annotation.Target -@Configuration -class JHipsterHealthIndicatorConfiguration(private val session: Session) { +import javax.annotation.Generated - @Bean - fun cassandraHealthIndicator() = CassandraHealthIndicator(session) +@Generated(value="JHipster", comments="Generated by JHipster <%= jhipsterVersion %>") +@Retention(RetentionPolicy.SOURCE) +@Target({ ElementType.TYPE }) +public @interface GeneratedByJHipster { } diff --git a/generators/server/templates/src/main/kotlin/package/aop/logging/LoggingAspect.kt.ejs b/generators/server/templates/src/main/kotlin/package/aop/logging/LoggingAspect.kt.ejs index 6e95cf118..728ca22e9 100644 --- a/generators/server/templates/src/main/kotlin/package/aop/logging/LoggingAspect.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/aop/logging/LoggingAspect.kt.ejs @@ -18,7 +18,7 @@ -%> package <%= packageName %>.aop.logging -import io.github.jhipster.config.JHipsterConstants +import tech.jhipster.config.JHipsterConstants import org.aspectj.lang.JoinPoint import org.aspectj.lang.ProceedingJoinPoint diff --git a/generators/server/templates/src/main/kotlin/package/client/AuthorizedFeignClient.kt.ejs b/generators/server/templates/src/main/kotlin/package/client/AuthorizedFeignClient.kt.ejs index 8c18f9bee..da4fc7ee8 100644 --- a/generators/server/templates/src/main/kotlin/package/client/AuthorizedFeignClient.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/client/AuthorizedFeignClient.kt.ejs @@ -65,7 +65,7 @@ annotation class AuthorizedFeignClient( val fallback: KClass<*> = Unit::class, /** - * Path prefix to be used by all method-level mappings. Can be used with or without `@RibbonClient`. + * Path prefix to be used by all method-level mappings. * @return the path prefix to be used by all method-level mappings. */ val path: String = "" diff --git a/generators/server/templates/src/main/kotlin/package/client/AuthorizedUserFeignClient.kt.ejs b/generators/server/templates/src/main/kotlin/package/client/AuthorizedUserFeignClient.kt.ejs index 1c721c570..937106d27 100644 --- a/generators/server/templates/src/main/kotlin/package/client/AuthorizedUserFeignClient.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/client/AuthorizedUserFeignClient.kt.ejs @@ -61,7 +61,7 @@ annotation class AuthorizedUserFeignClient( val fallback: KClass<*> = Unit::class, /** - * Path prefix to be used by all method-level mappings. Can be used with or without `@RibbonClient`. + * Path prefix to be used by all method-level mappings. */ val path: String = "" ) diff --git a/generators/server/templates/src/main/kotlin/package/client/OAuth2InterceptedFeignConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/client/OAuth2InterceptedFeignConfiguration.kt.ejs index bbb70c9c6..ccd3d096e 100644 --- a/generators/server/templates/src/main/kotlin/package/client/OAuth2InterceptedFeignConfiguration.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/client/OAuth2InterceptedFeignConfiguration.kt.ejs @@ -18,21 +18,6 @@ -%> package <%= packageName %>.client -<%_ if (authenticationType === 'uaa') { _%> -import org.springframework.cloud.security.oauth2.client.feign.OAuth2FeignRequestInterceptor -import org.springframework.context.annotation.Bean -import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext - -import feign.RequestInterceptor -import io.github.jhipster.security.uaa.LoadBalancedResourceDetails - -class OAuth2InterceptedFeignConfiguration(private val loadBalancedResourceDetails: LoadBalancedResourceDetails) { - - @Bean(name = ["oauth2RequestInterceptor"]) - fun getOAuth2RequestInterceptor() = - OAuth2FeignRequestInterceptor(DefaultOAuth2ClientContext(), loadBalancedResourceDetails) -} -<%_ } _%> <%_ if (authenticationType === 'oauth2') { _%> import org.springframework.context.annotation.Bean diff --git a/generators/server/templates/src/main/kotlin/package/config/ApplicationProperties.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/ApplicationProperties.kt.ejs index 354aebab3..66c27760b 100644 --- a/generators/server/templates/src/main/kotlin/package/config/ApplicationProperties.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/config/ApplicationProperties.kt.ejs @@ -24,7 +24,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties * Properties specific to <%= humanizedBaseName %>. * * Properties are configured in the `application.yml` file. - * See [io.github.jhipster.config.JHipsterProperties] for a good example. + * See [tech.jhipster.config.JHipsterProperties] for a good example. */ @ConfigurationProperties(prefix = "application", ignoreUnknownFields = false) class ApplicationProperties diff --git a/generators/server/templates/src/main/kotlin/package/config/AsyncConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/AsyncConfiguration.kt.ejs index b3690934d..1f96c07cd 100644 --- a/generators/server/templates/src/main/kotlin/package/config/AsyncConfiguration.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/config/AsyncConfiguration.kt.ejs @@ -18,7 +18,7 @@ -%> package <%= packageName %>.config -import io.github.jhipster.async.ExceptionHandlingAsyncTaskExecutor +import tech.jhipster.async.ExceptionHandlingAsyncTaskExecutor import org.slf4j.LoggerFactory import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler import org.springframework.boot.autoconfigure.task.TaskExecutionProperties diff --git a/generators/server/templates/src/main/kotlin/package/config/CacheConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/CacheConfiguration.kt.ejs index a62fb770e..2290aa841 100644 --- a/generators/server/templates/src/main/kotlin/package/config/CacheConfiguration.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/config/CacheConfiguration.kt.ejs @@ -26,7 +26,7 @@ import org.ehcache.config.builders.ExpiryPolicyBuilder import org.ehcache.config.builders.ResourcePoolsBuilder import org.ehcache.jsr107.Eh107Configuration -import io.github.jhipster.config.JHipsterProperties +import tech.jhipster.config.JHipsterProperties <%_ if (enableHibernateCache) { _%> import org.hibernate.cache.jcache.ConfigSettings @@ -41,18 +41,14 @@ import java.util.concurrent.TimeUnit <%_ if (enableHibernateCache) { _%> import org.hibernate.cache.jcache.ConfigSettings <%_ } _%> -import io.github.jhipster.config.JHipsterProperties +import tech.jhipster.config.JHipsterProperties <%_ } _%> <%_ if (cacheProvider === 'hazelcast') { _%> -import io.github.jhipster.config.JHipsterConstants -import io.github.jhipster.config.JHipsterProperties - -import com.hazelcast.config.Config -import com.hazelcast.config.EvictionPolicy -import com.hazelcast.config.ManagementCenterConfig -import com.hazelcast.config.MapConfig -import com.hazelcast.config.MaxSizeConfig +import tech.jhipster.config.JHipsterConstants +import tech.jhipster.config.JHipsterProperties + +import com.hazelcast.config.* import com.hazelcast.core.Hazelcast import com.hazelcast.core.HazelcastInstance @@ -76,7 +72,7 @@ import org.springframework.boot.info.BuildProperties import org.springframework.boot.info.GitProperties import org.springframework.cache.interceptor.KeyGenerator import org.springframework.beans.factory.annotation.Autowired -import io.github.jhipster.config.cache.PrefixedKeyGenerator +import tech.jhipster.config.cache.PrefixedKeyGenerator <%_ } _%> <%_ if (cacheProvider === 'memcached') { _%> <%_ if (!skipUserManagement || (authenticationType === 'oauth2' && databaseType !== 'no')) { _%> @@ -112,11 +108,9 @@ import org.infinispan.configuration.cache.ConfigurationBuilder import org.infinispan.configuration.global.GlobalConfigurationBuilder import org.infinispan.jboss.marshalling.core.JBossUserMarshaller import org.slf4j.LoggerFactory -import io.github.jhipster.config.JHipsterProperties +import tech.jhipster.config.JHipsterProperties import java.util.concurrent.TimeUnit import org.hibernate.cfg.AvailableSettings -import org.infinispan.eviction.EvictionType -import org.infinispan.manager.EmbeddedCacheManager import org.infinispan.spring.starter.embedded.InfinispanCacheConfigurer import org.infinispan.spring.starter.embedded.InfinispanGlobalConfigurer import org.infinispan.transaction.TransactionMode @@ -148,7 +142,7 @@ import com.google.code.ssm.providers.xmemcached.MemcacheClientFactoryImpl import com.google.code.ssm.spring.SSMCache import com.google.code.ssm.spring.SSMCacheManager -import io.github.jhipster.config.JHipsterProperties +import tech.jhipster.config.JHipsterProperties <%_ } _%> <%_ if (cacheProvider === 'redis') { _%> import java.net.URI @@ -169,7 +163,7 @@ import javax.cache.configuration.MutableConfiguration import javax.cache.expiry.CreatedExpiryPolicy import javax.cache.expiry.Duration -import io.github.jhipster.config.JHipsterProperties +import tech.jhipster.config.JHipsterProperties <%_ } _%> @Configuration @@ -250,7 +244,9 @@ class CacheConfiguration(<%_ if (cacheProvider !== 'no') { _%> private fun createCache(cm: javax.cache.CacheManager, cacheName: String) { val cache: javax.cache.Cache? = cm.getCache(cacheName) - if (cache == null) { + if (cache != null) { + cache.clear() + } else { cm.createCache(cacheName, jcacheConfiguration) } } @@ -294,7 +290,6 @@ class CacheConfiguration(<%_ if (cacheProvider !== 'no') { _%> if (env.acceptsProfiles(Profiles.of(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT))) { log.debug("Application is running with the \"dev\" profile, Hazelcast cluster will only work with localhost instances") - System.setProperty("hazelcast.local.localAddress", "127.0.0.1") config.networkConfig.port = serverProperties.port!! + 5701 config.networkConfig.join.tcpIpConfig.isEnabled = true for (instance in discoveryClient.getInstances(serviceId)) { @@ -325,26 +320,17 @@ class CacheConfiguration(<%_ if (cacheProvider !== 'no') { _%> config.networkConfig.join.tcpIpConfig.isEnabled = false } <%_ } _%> - config.mapConfigs["default"] = initializeDefaultMapConfig(jHipsterProperties) - // Full reference is available at: https://docs.hazelcast.org/docs/management-center/3.9/manual/html/Deploying_and_Starting.html - config.managementCenterConfig = initializeDefaultManagementCenterConfig(jHipsterProperties) + config.managementCenterConfig = ManagementCenterConfig() + config.addMapConfig(initializeDefaultMapConfig(jHipsterProperties)) <%_ if (enableHibernateCache) { _%> - config.mapConfigs["<%= packageName %>.domain.*"] = initializeDomainMapConfig(jHipsterProperties) + config.addMapConfig(initializeDomainMapConfig(jHipsterProperties)) <%_ } _%> return Hazelcast.newHazelcastInstance(config) } - private fun initializeDefaultManagementCenterConfig(jHipsterProperties: JHipsterProperties): ManagementCenterConfig { - return ManagementCenterConfig().apply { - isEnabled = jHipsterProperties.cache.hazelcast.managementCenter.isEnabled - url = jHipsterProperties.cache.hazelcast.managementCenter.url - updateInterval = jHipsterProperties.cache.hazelcast.managementCenter.updateInterval - } - } - private fun initializeDefaultMapConfig(jHipsterProperties: JHipsterProperties): MapConfig { - val mapConfig = MapConfig() + val mapConfig = MapConfig("default") /* Number of backups. If 1 is set as the backup-count for example, @@ -360,7 +346,7 @@ class CacheConfiguration(<%_ if (cacheProvider !== 'no') { _%> LFU (Least Frequently Used). NONE is the default. */ - mapConfig.evictionPolicy = EvictionPolicy.LRU + mapConfig.evictionConfig.evictionPolicy = EvictionPolicy.LRU /* Maximum size of the map. When max size is reached, @@ -368,14 +354,14 @@ class CacheConfiguration(<%_ if (cacheProvider !== 'no') { _%> Any integer between 0 and Integer.MAX_VALUE. 0 means Integer.MAX_VALUE. Default is 0. */ - mapConfig.maxSizeConfig = MaxSizeConfig(0, MaxSizeConfig.MaxSizePolicy.USED_HEAP_SIZE) + mapConfig.evictionConfig.maxSizePolicy = MaxSizePolicy.USED_HEAP_SIZE return mapConfig } <%_ if (cacheProvider === 'hazelcast') { _%> private fun initializeDomainMapConfig(jHipsterProperties: JHipsterProperties): MapConfig = - MapConfig().apply { timeToLiveSeconds = jHipsterProperties.cache.hazelcast.timeToLiveSeconds } + MapConfig("<%= packageName %>.domain.*").apply { timeToLiveSeconds = jHipsterProperties.cache.hazelcast.timeToLiveSeconds } <%_ } _%> <%_ } _%> <%_ if (cacheProvider === 'infinispan') { _%> @@ -410,7 +396,7 @@ class CacheConfiguration(<%_ if (cacheProvider !== 'no') { _%> log.warn("No discovery service is set up, Infinispan will use default discovery for cluster formation") return InfinispanGlobalConfigurer { GlobalConfigurationBuilder - .defaultClusteredBuilder().defaultCacheName("infinispan-<%=baseName%>-cluster-cache").transport().defaultTransport() + .defaultClusteredBuilder().transport().defaultTransport() .addProperty("configurationFile", jHipsterProperties.cache.infinispan.configFile) .clusterName("infinispan-<%=baseName%>-cluster").jmx() .enabled(jHipsterProperties.cache.infinispan.isStatsEnabled) @@ -419,7 +405,7 @@ class CacheConfiguration(<%_ if (cacheProvider !== 'no') { _%> } else if (discoveryClient?.getInstances(registration?.serviceId)?.size == 0) { return InfinispanGlobalConfigurer { GlobalConfigurationBuilder - .defaultClusteredBuilder().defaultCacheName("infinispan-<%=baseName%>-cluster-cache").transport() + .defaultClusteredBuilder().transport() .transport(JGroupsTransport()) .clusterName("infinispan-<%=baseName%>-cluster").jmx() .enabled(jHipsterProperties.cache.infinispan.isStatsEnabled) @@ -428,7 +414,7 @@ class CacheConfiguration(<%_ if (cacheProvider !== 'no') { _%> } else { return InfinispanGlobalConfigurer { GlobalConfigurationBuilder - .defaultClusteredBuilder().defaultCacheName("infinispan-<%=baseName%>-cluster-cache").transport() + .defaultClusteredBuilder().transport() .transport(JGroupsTransport(getTransportChannel())) .clusterName("infinispan-<%=baseName%>-cluster").jmx() .enabled(jHipsterProperties.cache.infinispan.isStatsEnabled) @@ -438,7 +424,7 @@ class CacheConfiguration(<%_ if (cacheProvider !== 'no') { _%> <%_ } else { _%> return InfinispanGlobalConfigurer { GlobalConfigurationBuilder - .defaultClusteredBuilder().defaultCacheName("infinispan-<%=baseName%>-cluster-cache").transport().defaultTransport() + .defaultClusteredBuilder().transport().defaultTransport() .addProperty("configurationFile", jHipsterProperties.cache.infinispan.configFile) .clusterName("infinispan-<%=baseName%>-cluster").jmx() .enabled(jHipsterProperties.cache.infinispan.isStatsEnabled) @@ -480,17 +466,17 @@ class CacheConfiguration(<%_ if (cacheProvider !== 'no') { _%> manager.defineConfiguration("local-app-data", ConfigurationBuilder() .clustering().cacheMode(CacheMode.LOCAL) .statistics().enabled(cacheInfo.isStatsEnabled) - .memory().evictionType(EvictionType.COUNT).size(cacheInfo.local.maxEntries).expiration() + .memory().maxCount(cacheInfo.local.maxEntries).expiration() .lifespan(cacheInfo.local.timeToLiveSeconds, TimeUnit.SECONDS).build()) manager.defineConfiguration("dist-app-data", ConfigurationBuilder() .clustering().cacheMode(CacheMode.DIST_SYNC).hash().numOwners(cacheInfo.distributed.instanceCount) .statistics().enabled(cacheInfo.isStatsEnabled) - .memory().evictionType(EvictionType.COUNT).size(cacheInfo.distributed.maxEntries).expiration() + .memory().maxCount(cacheInfo.local.maxEntries).expiration() .lifespan(cacheInfo.distributed.timeToLiveSeconds, TimeUnit.SECONDS).build()) manager.defineConfiguration("repl-app-data", ConfigurationBuilder() .clustering().cacheMode(CacheMode.REPL_SYNC) .statistics().enabled(cacheInfo.isStatsEnabled) - .memory().evictionType(EvictionType.COUNT).size(cacheInfo.replicated.maxEntries).expiration() + .memory().maxCount(cacheInfo.local.maxEntries).expiration() .lifespan(cacheInfo.replicated.timeToLiveSeconds, TimeUnit.SECONDS).build()) // initialize Hibernate L2 cache configuration templates @@ -528,7 +514,7 @@ class CacheConfiguration(<%_ if (cacheProvider !== 'no') { _%> manager.defineConfiguration("oAuth2Authentication", ConfigurationBuilder() .clustering().cacheMode(CacheMode.LOCAL) .statistics().enabled(cacheInfo.isStatsEnabled()) - .memory().evictionType(EvictionType.COUNT).size(cacheInfo.getLocal().getMaxEntries()).expiration() + .memory().maxCount(cacheInfo.local.maxEntries).expiration() .lifespan(cacheInfo.getLocal().getTimeToLiveSeconds(), TimeUnit.SECONDS).build()) <%_ } _%> } @@ -648,6 +634,11 @@ class CacheConfiguration(<%_ if (cacheProvider !== 'no') { _%> cacheManager.caches = ssmCaches return cacheManager } + + @Bean + fun defaultCacheFactory(jHipsterProperties: JHipsterProperties): CacheFactory? { + return createCache("default", jHipsterProperties) + } <%_ if (!skipUserManagement || (authenticationType === 'oauth2' && databaseType !== 'no')) { _%> @Bean @@ -739,8 +730,8 @@ class CacheConfiguration(<%_ if (cacheProvider !== 'no') { _%> fun cacheManagerCustomizer(jcacheConfiguration: javax.cache.configuration.Configuration ): JCacheManagerCustomizer { return JCacheManagerCustomizer { <%_ if (!skipUserManagement || (authenticationType === 'oauth2' && databaseType !== 'no')) { _%> - createCache(it, <%= packageName %>.repository<% if (reactive) { %>.reactive<% } %>.UserRepository.USERS_BY_LOGIN_CACHE, jcacheConfiguration) - createCache(it, <%= packageName %>.repository<% if (reactive) { %>.reactive<% } %>.UserRepository.USERS_BY_EMAIL_CACHE, jcacheConfiguration) + createCache(it, <%= packageName %>.repository.UserRepository.USERS_BY_LOGIN_CACHE, jcacheConfiguration) + createCache(it, <%= packageName %>.repository.UserRepository.USERS_BY_EMAIL_CACHE, jcacheConfiguration) <%_ if (enableHibernateCache) { _%> createCache(it, <%= packageName %>.domain.<%= asEntity('User') %>::class.java.name, jcacheConfiguration) createCache(it, <%= packageName %>.domain.Authority::class.java.name, jcacheConfiguration) @@ -757,7 +748,9 @@ class CacheConfiguration(<%_ if (cacheProvider !== 'no') { _%> private fun createCache(cm: javax.cache.CacheManager, cacheName: String, jcacheConfiguration: javax.cache.configuration.Configuration): Unit { val cache = cm.getCache(cacheName) - if (cache == null) { + if (cache != null) { + cache.clear() + } else { cm.createCache(cacheName, jcacheConfiguration) } } diff --git a/generators/server/templates/src/main/kotlin/package/config/CloudDatabaseConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/CloudDatabaseConfiguration.kt.ejs deleted file mode 100644 index 9d078a367..000000000 --- a/generators/server/templates/src/main/kotlin/package/config/CloudDatabaseConfiguration.kt.ejs +++ /dev/null @@ -1,127 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.config -<%_ if (databaseType === 'mongodb') { _%> - -import com.github.mongobee.Mongobee - -import io.github.jhipster.config.JHipsterConstants -import io.github.jhipster.domain.util.JSR310DateConverters.DateToZonedDateTimeConverter -import io.github.jhipster.domain.util.JSR310DateConverters.DurationToLongConverter -import io.github.jhipster.domain.util.JSR310DateConverters.ZonedDateTimeToDateConverter -<%_ } else { _%> - -import io.github.jhipster.config.JHipsterConstants -<%_ } _%> - -<%_ if (databaseType === 'sql' || databaseType === 'mongodb') { _%> -import org.slf4j.LoggerFactory -<%_ } _%> -<%_ if (cacheProvider === 'hazelcast') { _%> -import org.springframework.cache.CacheManager -<%_ } _%> -<%_ if (databaseType === 'mongodb') { _%> -import org.springframework.cloud.Cloud -import org.springframework.cloud.CloudException -<%_ } _%> -import org.springframework.cloud.config.java.AbstractCloudConfig -<%_ if (databaseType === 'mongodb') { _%> -import org.springframework.cloud.service.common.MongoServiceInfo -<%_ } _%> -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.context.annotation.Profile -<%_ if (databaseType === 'mongodb') { _%> -import org.springframework.core.convert.converter.Converter -import org.springframework.data.mongodb.MongoDbFactory -import org.springframework.data.mongodb.core.MongoTemplate -import org.springframework.data.mongodb.core.convert.MongoCustomConversions -import org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener -import org.springframework.data.mongodb.repository.config.Enable<% if (reactive) { %>Reactive<% } %>MongoRepositories -import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean -<%_ } _%> -<%_ if (databaseType === 'sql') { _%> - -import javax.sql.DataSource -import org.springframework.boot.context.properties.ConfigurationProperties -<%_ } _%> - -<%_ if (databaseType === 'sql') { _%> -private const val CLOUD_CONFIGURATION_HIKARI_PREFIX = "spring.datasource.hikari" -<%_ } _%> - -@Configuration -<%_ if (databaseType === 'mongodb') { _%> -@Enable<% if (reactive) { %>Reactive<% } %>MongoRepositories("<%= packageName %>.repository") -<%_ } _%> -@Profile(JHipsterConstants.SPRING_PROFILE_CLOUD) -class CloudDatabaseConfiguration : AbstractCloudConfig() { - <%_ if (databaseType === 'sql' || databaseType === 'mongodb') { _%> - - private val log = LoggerFactory.getLogger(javaClass) - <%_ } _%> - <%_ if (databaseType === 'sql') { _%> - - @Bean - @ConfigurationProperties(CLOUD_CONFIGURATION_HIKARI_PREFIX) - fun dataSource(<% if (cacheProvider === 'hazelcast') { %>cacheManager: CacheManager<% } %>): DataSource { - log.info("Configuring JDBC datasource from a cloud provider") - return connectionFactory().dataSource() - } - <%_ } _%> - <%_ if (databaseType === 'mongodb') { _%> - - @Bean - fun mongoFactory(): MongoDbFactory = connectionFactory().mongoDbFactory() - - @Bean - fun validator() = LocalValidatorFactoryBean() - - @Bean - fun validatingMongoEventListener() = ValidatingMongoEventListener(validator()) - - @Bean - fun customConversions() = - MongoCustomConversions( - mutableListOf>( - DateToZonedDateTimeConverter.INSTANCE, - ZonedDateTimeToDateConverter.INSTANCE, - DurationToLongConverter.INSTANCE - ) - ) - - @Bean - fun mongobee(mongoDbFactory: MongoDbFactory, mongoTemplate: MongoTemplate, cloud: Cloud): Mongobee { - log.debug("Configuring Cloud Mongobee") - val matchingServiceInfos = cloud.getServiceInfos(MongoDbFactory::class.java) - - if (matchingServiceInfos.size != 1) { - throw CloudException("No unique service matching MongoDbFactory found. Expected 1, found $matchingServiceInfos.size") - } - val info = matchingServiceInfos[0] as MongoServiceInfo - return Mongobee(info.uri).apply { - setDbName(mongoDbFactory.db.name) - setMongoTemplate(mongoTemplate) - // package to scan for migrations - setChangeLogsScanPackage("<%= packageName %>.config.dbmigrations") - isEnabled = true - } - } - <%_ } _%> -} diff --git a/generators/server/templates/src/main/kotlin/package/config/Constants.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/Constants.kt.ejs index 0d1926da3..dd0cdb53d 100644 --- a/generators/server/templates/src/main/kotlin/package/config/Constants.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/config/Constants.kt.ejs @@ -26,7 +26,6 @@ const val LOGIN_REGEX: String = "<%- LOGIN_REGEX %>" const val SYSTEM_ACCOUNT: String = "system" <%_ } _%> <%_ if (!skipUserManagement || authenticationType === 'oauth2') { _%> -const val ANONYMOUS_USER: String = "anonymoususer" const val DEFAULT_LANGUAGE: String = "<%= nativeLanguage %>" <%_ } _%> <%_ if (databaseType === 'couchbase') { _%> diff --git a/generators/server/templates/src/main/kotlin/package/config/DatabaseConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/DatabaseConfiguration.kt.ejs deleted file mode 100644 index 09293d5d1..000000000 --- a/generators/server/templates/src/main/kotlin/package/config/DatabaseConfiguration.kt.ejs +++ /dev/null @@ -1,384 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.config - -import io.github.jhipster.config.JHipsterConstants -<%_ if (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory') { _%> -import io.github.jhipster.config.h2.H2ConfigurationHelper -<%_ } _%> -<%_ if (databaseType === 'sql' && reactive) { _%> -import io.r2dbc.spi.ConnectionFactory -<%_ } _%> -<%_ if (databaseType === 'mongodb') { _%> -import com.github.mongobee.Mongobee -import com.mongodb.MongoClient -<%_ } _%> -<%_ if (databaseType === 'couchbase') { _%> - -import com.couchbase.client.java.Bucket -import com.github.couchmove.Couchmove -import <%= packageName %>.repository.Custom<% if (reactive) { %>Reactive<% } %>N1qlCouchbaseRepository - <%_ if (searchEngine === 'elasticsearch') { _%> -import <%= packageName %>.repository.<% if (reactive) { %>Reactive<% } %>N1qlCouchbaseRepository - <%_ } _%> -import org.apache.commons.codec.binary.Base64 -<%_ } _%> -<%_ if (databaseType === 'mongodb') { _%> -import io.github.jhipster.domain.util.JSR310DateConverters.DateToZonedDateTimeConverter -import io.github.jhipster.domain.util.JSR310DateConverters.ZonedDateTimeToDateConverter -<%_ } _%> -<%_ if (databaseType === 'mongodb' || databaseType === 'couchbase' || (databaseType==='sql' && (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory'))) { _%> -import org.slf4j.LoggerFactory -<%_ } _%> -<%_ if (databaseType === 'mongodb') { _%> -import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration -import org.springframework.boot.autoconfigure.mongo.MongoProperties - <%_ if (reactive) { _%> -import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration - <%_ } _%> -<%_ } _%> -<%_ if (databaseType === 'couchbase') { _%> -import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration -import org.springframework.boot.autoconfigure.couchbase.CouchbaseProperties -<%_ } _%> -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.ComponentScan -import org.springframework.context.annotation.ComponentScan.Filter -import org.springframework.context.annotation.Configuration -import org.springframework.context.annotation.FilterType -import org.springframework.context.annotation.Import -import org.springframework.context.annotation.Profile -<%_ if (databaseType === 'mongodb' || databaseType === 'couchbase' || (databaseType === 'sql' && reactive)) { _%> -import org.springframework.core.convert.converter.Converter -<%_ } _%> -<%_ if (searchEngine === 'elasticsearch') { _%> -import org.springframework.data.elasticsearch.repository.config.Enable<% if (reactive) { %>Reactive<% } %>ElasticsearchRepositories -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import org.neo4j.springframework.data.repository.config.Enable<% if (reactive) { %>Reactive<% } %>Neo4jRepositories -<%_ if (searchEngine === 'elasticsearch') { _%> -import org.neo4j.springframework.data.repository.<% if (reactive) { %>Reactive<% } %>Neo4jRepository -<%_ } _%> -<%_ } _%> -<%_ if (databaseType === 'mongodb') { _%> - <%_ if (!reactive) { _%> -import org.springframework.data.mongodb.config.EnableMongoAuditing - <%_ } _%> -import org.springframework.data.mongodb.core.MongoTemplate -import org.springframework.data.mongodb.core.convert.MongoCustomConversions -import org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener - <%_ if (searchEngine === 'elasticsearch') { _%> -import org.springframework.data.mongodb.repository.<% if (reactive) { %>Reactive<% } %>MongoRepository - <%_ } _%> -import org.springframework.data.mongodb.repository.config.Enable<% if (reactive) { %>Reactive<% } %>MongoRepositories -<%_ } _%> -<%_ if (databaseType === 'couchbase') { _%> -import org.springframework.data.convert.ReadingConverter -import org.springframework.data.convert.WritingConverter -import org.springframework.data.couchbase.config.BeanNames -import org.springframework.data.couchbase.core.convert.CouchbaseCustomConversions -import org.springframework.data.couchbase.core.mapping.event.ValidatingCouchbaseEventListener - <%_ if (!reactive) { _%> -import org.springframework.data.couchbase.repository.auditing.EnableCouchbaseAuditing - <%_ } _%> -import org.springframework.data.couchbase.repository.config.Enable<%_ if (reactive) { _%>Reactive<% } %>CouchbaseRepositories -import org.springframework.util.StringUtils<% } %><% if (databaseType === 'mongodb' || databaseType === 'couchbase') { %> -import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean<% } %> -<%_ if (databaseType === 'sql') { _%> - <%_ if (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory') { _%> -import org.springframework.core.env.Environment - <%_ } _%> - <%_ if (reactive) { _%> -import org.springframework.data.convert.CustomConversions -import org.springframework.data.convert.ReadingConverter -import org.springframework.data.convert.WritingConverter -import org.springframework.data.r2dbc.convert.R2dbcCustomConversions -import org.springframework.data.r2dbc.dialect.DialectResolver -import org.springframework.data.r2dbc.dialect.R2dbcDialect -import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories - <%_ } else { _%> -import org.springframework.data.jpa.repository.config.EnableJpaAuditing -import org.springframework.data.jpa.repository.config.EnableJpaRepositories - <%_ } _%> -import org.springframework.transaction.annotation.EnableTransactionManagement - -<%_ if (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory') { _%> -import java.sql.SQLException -<%_ } } _%> -<%_ if (databaseType === 'sql' && reactive) { _%> -import java.time.Instant -import java.time.LocalDateTime -import java.time.ZoneOffset -<%_ } _%> -<%_ if (databaseType === 'couchbase') { _%> - -import java.math.BigDecimal -import java.math.BigInteger -import java.time.ZoneId -import java.time.ZonedDateTime -import java.util.Date -import java.util.UUID -<%_ } _%> - -@Configuration -<%_ if (databaseType === 'sql') { _%> - <%_ if (reactive) { _%> -@EnableR2dbcRepositories("<%= packageName %>.repository") - <%_ } else { _%> -@EnableJpaRepositories("<%= packageName %>.repository") -@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware") - <%_ } _%> -@EnableTransactionManagement -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> - <%_ if (searchEngine === 'elasticsearch') { _%> -@Enable<% if (reactive) { %>Reactive<% } %>Neo4jRepositories(basePackages = ["<%= packageName %>.repository"], includeFilters = [ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = <% if (reactive) { %>Reactive<% } %>Neo4jRepository::class])]) - <%_ } else { _%> -@Enable<% if (reactive) { %>Reactive<% } %>Neo4jRepositories("<%= packageName %>.repository") - <%_ } _%> -<%_ } _%> -<%_ if (searchEngine === 'elasticsearch') { _%> -@Enable<% if (reactive) { %>Reactive<% } %>ElasticsearchRepositories("<%= packageName %>.repository.search") -<%_ } _%> -<%_ if (databaseType === 'mongodb') { _%> - <%_ if (searchEngine === 'elasticsearch') { _%> -@Enable<% if (reactive) { %>Reactive<% } %>MongoRepositories(basePackages = ["<%= packageName %>.repository"], includeFilters = [ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = [<% if (reactive) { %>Reactive<% } %>MongoRepository::class])]) - <%_ } else { _%> -@Enable<% if (reactive) { %>Reactive<% } %>MongoRepositories("<%= packageName %>.repository") - <%_ } _%> -<%_ } _%> -<%_ if (databaseType === 'mongodb' || databaseType === 'couchbase') { _%> -@Profile("!" + JHipsterConstants.SPRING_PROFILE_CLOUD) -<%_ } _%> -<%_ if (databaseType === 'mongodb') { _%> - <%_ if (reactive) { _%> -@Import(value = [MongoAutoConfiguration::class, MongoReactiveAutoConfiguration::class]) - <%_ } else { _%> -@Import(value = [MongoAutoConfiguration::class]) -@EnableMongoAuditing(auditorAwareRef = "springSecurityAuditorAware") - <%_ } _%> -<%_ } _%> -<%_ if (databaseType === 'couchbase') { _%> -@Enable<% if (reactive) { %>Reactive<% } %>CouchbaseRepositories(repositoryBaseClass = Custom<% if (reactive) { %>Reactive<% } %>N1qlCouchbaseRepository::class, basePackages = ["<%= packageName %>.repository"]<%_ if (searchEngine === 'elasticsearch') { %>, - includeFilters = [ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = [<% if (reactive) { %>Reactive<% } %>N1qlCouchbaseRepository::class])]<%_ } _%>) - <%_ if (!reactive) { _%> -@EnableCouchbaseAuditing(auditorAwareRef = "springSecurityAuditorAware") - <%_ } _%> -@Import(value = [CouchbaseAutoConfiguration::class]) -<%_ } _%> -class DatabaseConfiguration<%_ if (databaseType === 'sql' && (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory') ) { _%>(private val env: Environment) { <%_ } else if (databaseType === 'mongodb' || databaseType === 'couchbase') { %> {<% } %> -<%_ if (databaseType === 'sql' && (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory')) { _%> - - private val log = LoggerFactory.getLogger(javaClass) - - /** - * Open the TCP port for the H2 database, so it is available remotely. - * - * @return the H2 database TCP server. - * @throws SQLException if the server failed to start. - */ - @Throws(SQLException::class) - @Bean(initMethod = "start", destroyMethod = "stop") - @Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) - fun h2TCPServer(): Any { - val port = getValidPortForH2() - log.debug("H2 database is available on port $port") - return H2ConfigurationHelper.createServer(port) - } - - private fun getValidPortForH2(): String { - var port = Integer.parseInt(env.getProperty("server.port")) - if (port < 10000) { - port += 10000 - } else { - if (port < 63536) { - port += 2000 - } else { - port -= 2000 - } - } - return port.toString() - } -<%_ } _%> -<%_ if (databaseType === 'mongodb' || databaseType === 'couchbase') { _%> - - private val log = LoggerFactory.getLogger(javaClass) -<%_ } _%> -<%_ if (databaseType === 'mongodb') { _%> - - @Bean - fun validatingMongoEventListener() = ValidatingMongoEventListener(validator()) -<%_ } _%> -<%_ if (databaseType === 'couchbase') { _%> - - @Bean - fun validatingCouchbaseEventListener() = ValidatingCouchbaseEventListener(validator()) -<%_ } _%> -<%_ if (databaseType === 'mongodb' || databaseType === 'couchbase') { _%> - - @Bean - fun validator() = LocalValidatorFactoryBean() -<%_ } if (databaseType === 'mongodb') { _%> - - @Bean - fun customConversions() = - MongoCustomConversions( - mutableListOf>( - DateToZonedDateTimeConverter.INSTANCE, - ZonedDateTimeToDateConverter.INSTANCE - ) - ) - - @Bean - fun mongobee(mongoClient: MongoClient, mongoTemplate: MongoTemplate, mongoProperties: MongoProperties): Mongobee { - log.debug("Configuring Mongobee") - return Mongobee(mongoClient).apply { - setDbName(mongoProperties.mongoClientDatabase) - setMongoTemplate(mongoTemplate) - // package to scan for migrations - setChangeLogsScanPackage("<%= packageName %>.config.dbmigrations") - isEnabled = true - } - } -<%_ } %><% if (databaseType === 'couchbase') { _%> - - @Bean(name = [BeanNames.COUCHBASE_CUSTOM_CONVERSIONS]) - fun customConversions() = - CouchbaseCustomConversions( - mutableListOf>( - ZonedDateTimeToLongConverter, - NumberToLocalDateTimeConverter, - BigIntegerToStringConverter, - StringToBigIntegerConverter, - BigDecimalToStringConverter, - StringToBigDecimalConverter, - StringToByteConverter, - UUIDToStringConverter, - StringToUUIDConverter - ) - ) - - @Bean - fun couchmove(couchbaseBucket: Bucket, properties: CouchbaseProperties): Couchmove { - log.debug("Configuring Couchmove") - return Couchmove(couchbaseBucket, properties.bucket.name, properties.bucket.password, "config/couchmove/changelog").apply { migrate() } - } - - /** - * Simple singleton to convert [ZonedDateTime]s to their [Long] representation. - */ - @WritingConverter - object ZonedDateTimeToLongConverter : Converter { - override fun convert(source: ZonedDateTime) = Date.from(source.toInstant()).time - } - - /** - * Simple singleton to convert from [Number] [BigDecimal] representation. - */ - @ReadingConverter - object NumberToLocalDateTimeConverter : Converter { - override fun convert(source: Number): ZonedDateTime = - ZonedDateTime.ofInstant(Date(source.toLong()).toInstant(), ZoneId.systemDefault()) - } - - /** - * Simple singleton to convert [BigDecimal]s to their [String] representation. - */ - @WritingConverter - object BigDecimalToStringConverter : Converter { - override fun convert(source: BigDecimal) = source.toString() - } - - /** - * Simple singleton to convert from [String] [BigDecimal] representation. - */ - @ReadingConverter - object StringToBigDecimalConverter : Converter { - override fun convert(source: String) = - if (StringUtils.hasText(source)) BigDecimal(source) else null - } - - /** - * Simple singleton to convert [BigInteger]s to their [String] representation. - */ - @WritingConverter - object BigIntegerToStringConverter : Converter { - override fun convert(source: BigInteger) = source.toString() - } - - /** - * Simple singleton to convert from [String] [BigInteger] representation. - */ - @ReadingConverter - object StringToBigIntegerConverter : Converter { - override fun convert(source: String) = - if (StringUtils.hasText(source)) BigInteger(source) else null - } - - /** - * Simple singleton to convert from [String] `byte[]` representation. - */ - @ReadingConverter - object StringToByteConverter : Converter { - override fun convert(source: String): ByteArray = Base64.decodeBase64(source) - } - - /** - * Simple singleton to convert [UUID]s to their [String] representation. - */ - @WritingConverter - object UUIDToStringConverter : Converter { - override fun convert(source: UUID) = source.toString() - } - - /** - * Simple singleton to convert from [String] [UUID] representation. - */ - @ReadingConverter - object StringToUUIDConverter : Converter { - override fun convert(source: String) = - if (StringUtils.hasText(source)) UUID.fromString(source) else null - } -<%_ } _%> -<%_ if (databaseType === 'sql' && reactive) { _%> - // LocalDateTime seems to be the only type that is supported across all drivers atm - // See https://github.com/r2dbc/r2dbc-h2/pull/139 https://github.com/mirromutth/r2dbc-mysql/issues/105 - @Bean - fun r2dbcCustomConversions(connectionFactory: ConnectionFactory): R2dbcCustomConversions { - val dialect = DialectResolver.getDialect(connectionFactory) - val converters = dialect.converters.toMutableList() - converters.add(InstantWriteConverter()) - converters.add(InstantReadConverter()) - converters.addAll(R2dbcCustomConversions.STORE_CONVERTERS) - return R2dbcCustomConversions(CustomConversions.StoreConversions.of(dialect.simpleTypeHolder, converters), mutableListOf()) - } - - @WritingConverter - class InstantWriteConverter: Converter { - override fun convert(source: Instant) = LocalDateTime.ofInstant(source, ZoneOffset.UTC) - } - - @ReadingConverter - class InstantReadConverter: Converter { - override fun convert(localDateTime: LocalDateTime) = localDateTime.toInstant(ZoneOffset.UTC) - } -<%_ } _%> -<%_ if (databaseType === 'mongodb' || databaseType === 'couchbase' || (databaseType === 'sql' && (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory'))) { _%> -} -<%_ } _%> diff --git a/generators/server/templates/src/main/kotlin/package/config/DatabaseConfiguration_cassandra.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/DatabaseConfiguration_cassandra.kt.ejs new file mode 100644 index 000000000..890cf8a1d --- /dev/null +++ b/generators/server/templates/src/main/kotlin/package/config/DatabaseConfiguration_cassandra.kt.ejs @@ -0,0 +1,80 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + +This file is part of the JHipster project, see https://jhipster.github.io/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %>.config + +import com.datastax.oss.driver.api.core.data.TupleValue +import com.datastax.oss.driver.api.core.type.DataTypes +import com.datastax.oss.driver.api.core.type.TupleType +import tech.jhipster.config.JHipsterConstants +import org.slf4j.LoggerFactory +<%_ if (applicationType === 'gateway' && databaseType !== 'cassandra') { _%> +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +<%_ } _%> +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Profile +import org.springframework.core.convert.converter.Converter +import org.springframework.data.cassandra.core.convert.CassandraCustomConversions +import org.springframework.data.convert.ReadingConverter +import org.springframework.data.convert.WritingConverter + +import javax.annotation.Nonnull +import java.time.Instant +import java.time.ZoneId +import java.time.ZonedDateTime +import java.util.ArrayList +import java.util.List + +@Configuration<% if (applicationType === 'gateway' && databaseType !== 'cassandra') { %> +@ConditionalOnProperty("jhipster.gateway.rate-limiting.enabled")<% } %> +public class DatabaseConfiguration { + + private val log = LoggerFactory.getLogger(javaClass) + + @Bean + fun customConversions() = + CassandraCustomConversions( + mutableListOf>( + TupleToZonedDateTimeConverter, + ZonedDateTimeToTupleConverter + ) + ) + + @ReadingConverter + object TupleToZonedDateTimeConverter: Converter { + override fun convert(source: TupleValue): ZonedDateTime { + val instant = source.getInstant(0)!! + val zoneId = ZoneId.of(source.getString(1)) + return instant.atZone(zoneId) + } + } + + @WritingConverter + object ZonedDateTimeToTupleConverter: Converter { + private val type = DataTypes.tupleOf(DataTypes.TIMESTAMP, DataTypes.ASCII) + + override fun convert(@Nonnull source: ZonedDateTime): TupleValue { + val tupleValue = type.newValue() + tupleValue.setInstant(0, source.toInstant()) + tupleValue.setString(1, source.getZone().toString()) + return tupleValue + } + } + +} diff --git a/generators/server/templates/src/main/kotlin/package/config/DatabaseConfiguration_couchbase.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/DatabaseConfiguration_couchbase.kt.ejs new file mode 100644 index 000000000..a13dbff0d --- /dev/null +++ b/generators/server/templates/src/main/kotlin/package/config/DatabaseConfiguration_couchbase.kt.ejs @@ -0,0 +1,187 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + +This file is part of the JHipster project, see https://jhipster.github.io/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> + +package <%= packageName %>.config + +import tech.jhipster.config.JHipsterConstants + +import com.couchbase.client.java.Bucket +import com.github.couchmove.Couchmove +import <%= packageName %>.repository.Custom<% if (reactive) { %>Reactive<% } %>N1qlCouchbaseRepository +<%_ if (searchEngine === 'elasticsearch') { _%> +import <%= packageName %>.repository.<% if (reactive) { %>Reactive<% } %>N1qlCouchbaseRepository +<%_ } _%> +import org.apache.commons.codec.binary.Base64 +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration +import org.springframework.boot.autoconfigure.couchbase.CouchbaseProperties +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Import +<%_ if (searchEngine === 'elasticsearch') { _%> +import org.springframework.context.annotation.ComponentScan.Filter +import org.springframework.context.annotation.FilterType +<%_ } _%> +import org.springframework.context.annotation.Profile +import org.springframework.core.convert.converter.Converter +<%_ if (searchEngine === 'elasticsearch') { _%> +import org.springframework.data.elasticsearch.repository.config.Enable<% if (reactive) { %>Reactive<% } %>ElasticsearchRepositories +<%_ } _%> +import org.springframework.data.convert.ReadingConverter +import org.springframework.data.convert.WritingConverter +import org.springframework.data.couchbase.config.BeanNames +import org.springframework.data.couchbase.core.convert.CouchbaseCustomConversions +import org.springframework.data.couchbase.core.mapping.event.ValidatingCouchbaseEventListener +<%_ if (!reactive) { _%> +import org.springframework.data.couchbase.repository.auditing.EnableCouchbaseAuditing +<%_ } _%> +import org.springframework.data.couchbase.repository.config.Enable<%_ if (reactive) { _%>Reactive<% } %>CouchbaseRepositories +import org.springframework.util.StringUtils +import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean + +import java.math.BigDecimal +import java.math.BigInteger +import java.time.ZoneId +import java.time.ZonedDateTime +import java.util.ArrayList +import java.util.Date +import java.util.List +import java.util.UUID + +@Configuration +<%_ if (searchEngine === 'elasticsearch') { _%> +@Enable<% if (reactive) { %>Reactive<% } %>ElasticsearchRepositories("<%= packageName %>.repository.search") +<%_ } _%> +@Profile("!" + JHipsterConstants.SPRING_PROFILE_CLOUD) +@Enable<% if (reactive) { %>Reactive<% } %>CouchbaseRepositories(repositoryBaseClass = Custom<% if (reactive) { %>Reactive<% } %>N1qlCouchbaseRepository::class, basePackages = ["<%= packageName %>.repository"]<%_ if (searchEngine === 'elasticsearch') { %>, + includeFilters = [Filter(type = FilterType.ASSIGNABLE_TYPE, value =[<% if (reactive) { %>Reactive<% } %>N1qlCouchbaseRepository::class])<%_ } _%>) +<%_ if (!reactive) { _%> +@EnableCouchbaseAuditing(auditorAwareRef = "springSecurityAuditorAware") +<%_ } _%> +@Import(value = [CouchbaseAutoConfiguration::class]) +public class DatabaseConfiguration { + + private val log = LoggerFactory.getLogger(javaClass) + + @Bean + fun validatingCouchbaseEventListener() = ValidatingCouchbaseEventListener(validator()) + + @Bean + fun validator() = LocalValidatorFactoryBean() + + @Bean(name = [BeanNames.COUCHBASE_CUSTOM_CONVERSIONS]) + fun customConversions() = + CouchbaseCustomConversions( + mutableListOf>( + ZonedDateTimeToLongConverter, + NumberToLocalDateTimeConverter, + BigIntegerToStringConverter, + StringToBigIntegerConverter, + BigDecimalToStringConverter, + StringToBigDecimalConverter, + StringToByteConverter, + UUIDToStringConverter, + StringToUUIDConverter + ) + ) + + @Bean + fun couchmove(couchbaseBucket: Bucket, properties: CouchbaseProperties): Couchmove { + log.debug("Configuring Couchmove") + return Couchmove(couchbaseBucket, properties.bucket.name, properties.bucket.password, "config/couchmove/changelog").apply { migrate() } + } + + /** + * Simple singleton to convert [ZonedDateTime]s to their [Long] representation. + */ + @WritingConverter + object ZonedDateTimeToLongConverter : Converter { + override fun convert(source: ZonedDateTime) = Date.from(source.toInstant()).time + } + + /** + * Simple singleton to convert from [Number] [BigDecimal] representation. + */ + @ReadingConverter + object NumberToLocalDateTimeConverter : Converter { + override fun convert(source: Number): ZonedDateTime = + ZonedDateTime.ofInstant(Date(source.toLong()).toInstant(), ZoneId.systemDefault()) + } + + /** + * Simple singleton to convert [BigDecimal]s to their [String] representation. + */ + @WritingConverter + object BigDecimalToStringConverter : Converter { + override fun convert(source: BigDecimal) = source.toString() + } + + /** + * Simple singleton to convert from [String] [BigDecimal] representation. + */ + @ReadingConverter + object StringToBigDecimalConverter : Converter { + override fun convert(source: String) = + if (StringUtils.hasText(source)) BigDecimal(source) else null + } + + /** + * Simple singleton to convert [BigInteger]s to their [String] representation. + */ + @WritingConverter + object BigIntegerToStringConverter : Converter { + override fun convert(source: BigInteger) = source.toString() + } + + /** + * Simple singleton to convert from [String] [BigInteger] representation. + */ + @ReadingConverter + object StringToBigIntegerConverter : Converter { + override fun convert(source: String) = + if (StringUtils.hasText(source)) BigInteger(source) else null + } + + /** + * Simple singleton to convert from [String] `byte[]` representation. + */ + @ReadingConverter + object StringToByteConverter : Converter { + override fun convert(source: String): ByteArray = Base64.decodeBase64(source) + } + + /** + * Simple singleton to convert [UUID]s to their [String] representation. + */ + @WritingConverter + object UUIDToStringConverter : Converter { + override fun convert(source: UUID) = source.toString() + } + + /** + * Simple singleton to convert from [String] [UUID] representation. + */ + @ReadingConverter + object StringToUUIDConverter : Converter { + override fun convert(source: String) = + if (StringUtils.hasText(source)) UUID.fromString(source) else null + } + +} diff --git a/generators/server/templates/src/main/kotlin/package/config/DatabaseConfiguration_mongodb.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/DatabaseConfiguration_mongodb.kt.ejs new file mode 100644 index 000000000..4ebdc7e7c --- /dev/null +++ b/generators/server/templates/src/main/kotlin/package/config/DatabaseConfiguration_mongodb.kt.ejs @@ -0,0 +1,94 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + +This file is part of the JHipster project, see https://jhipster.github.io/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %>.config + +import tech.jhipster.config.JHipsterConstants +import com.github.cloudyrock.spring.v5.EnableMongock +import tech.jhipster.domain.util.JSR310DateConverters.DateToZonedDateTimeConverter +import tech.jhipster.domain.util.JSR310DateConverters.ZonedDateTimeToDateConverter +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration +<%_ if (reactive) { _%> +import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration +<%_ } _%> +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Import +<%_ if (searchEngine === 'elasticsearch') { _%> +import org.springframework.context.annotation.ComponentScan.Filter +import org.springframework.context.annotation.FilterType +<%_ } _%> +import org.springframework.context.annotation.Profile +import org.springframework.core.convert.converter.Converter +<%_ if (searchEngine === 'elasticsearch') { _%> +import org.springframework.data.elasticsearch.repository.config.Enable<% if (reactive) { %>Reactive<% } %>ElasticsearchRepositories +<%_ } _%> +<%_ if (!reactive) { _%> +import org.springframework.data.mongodb.config.EnableMongoAuditing +<%_ } _%> +import org.springframework.data.mongodb.core.convert.MongoCustomConversions +import org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener +<%_ if (searchEngine === 'elasticsearch') { _%> +import org.springframework.data.mongodb.repository.<% if (reactive) { %>Reactive<% } %>MongoRepository +<%_ } _%> +import org.springframework.data.mongodb.repository.config.Enable<% if (reactive) { %>Reactive<% } %>MongoRepositories +import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean +import java.util.ArrayList +import java.util.List + +@Configuration +@EnableMongock +<%_ if (searchEngine === 'elasticsearch') { _%> +@Enable<% if (reactive) { %>Reactive<% } %>ElasticsearchRepositories("<%= packageName %>.repository.search") +<%_ } _%> +<%_ if (searchEngine === 'elasticsearch') { _%> +@Enable<% if (reactive) { %>Reactive<% } %>MongoRepositories( + basePackages = ["<%= packageName %>.repository"], + includeFilters = [ + Filter(type=FilterType.ASSIGNABLE_TYPE,value = [<% if (reactive) { %>Reactive<% } %>MongoRepository::class]) + ] +) +<%_ } else { _%> +@Enable<% if (reactive) { %>Reactive<% } %>MongoRepositories("<%= packageName %>.repository") +<%_ } _%> +@Profile("!" + JHipsterConstants.SPRING_PROFILE_CLOUD) +<%_ if (reactive) { _%> +@Import(value = [MongoAutoConfiguration::class, MongoReactiveAutoConfiguration::class]) +<%_ } else { _%> +@Import(value = [MongoAutoConfiguration::class]) +@EnableMongoAuditing(auditorAwareRef = "springSecurityAuditorAware") +<%_ } _%> +class DatabaseConfiguration { + + @Bean + fun validatingMongoEventListener() = ValidatingMongoEventListener(validator()) + + @Bean + fun validator() = LocalValidatorFactoryBean() + + @Bean + fun customConversions() = + MongoCustomConversions( + mutableListOf>( + DateToZonedDateTimeConverter.INSTANCE, + ZonedDateTimeToDateConverter.INSTANCE + ) + ) +} diff --git a/generators/server/templates/src/main/kotlin/package/config/DatabaseConfiguration_neo4j.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/DatabaseConfiguration_neo4j.kt.ejs new file mode 100644 index 000000000..c9c8e66e2 --- /dev/null +++ b/generators/server/templates/src/main/kotlin/package/config/DatabaseConfiguration_neo4j.kt.ejs @@ -0,0 +1,59 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + +This file is part of the JHipster project, see https://jhipster.github.io/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> + +package <%= packageName %>.config + +import org.neo4j.driver.Driver +import tech.jhipster.config.JHipsterConstants +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +<%_ if (searchEngine === 'elasticsearch') { _%> +import org.springframework.context.annotation.ComponentScan.Filter +import org.springframework.context.annotation.FilterType +<%_ } _%> +<%_ if (searchEngine === 'elasticsearch') { _%> +import org.springframework.data.elasticsearch.repository.config.Enable<% if (reactive) { %>Reactive<% } %>ElasticsearchRepositories +<%_ } _%> +import org.springframework.data.neo4j.core.<% if (reactive) { %>Reactive<% } %>DatabaseSelectionProvider + +import org.springframework.data.neo4j.core.transaction.<% if (reactive) { %>Reactive<% } %>Neo4jTransactionManager +import org.springframework.data.neo4j.repository.config.Enable<% if (reactive) { %>Reactive<% } %>Neo4jRepositories +import org.springframework.data.neo4j.repository.config.<% if (reactive) { %>Reactive<% } %>Neo4jRepositoryConfigurationExtension + +<%_ if (searchEngine === 'elasticsearch') { _%> +import org.springframework.data.neo4j.repository.<% if (reactive) { %>Reactive<% } %>Neo4jRepository +<%_ } _%> +import org.springframework.transaction.<% if (reactive) { %>Reactive<% } %>TransactionManager + + +@Configuration +<%_ if (searchEngine === 'elasticsearch') { _%> +@Enable<% if (reactive) { %>Reactive<% } %>Neo4jRepositories(basePackages = "<%= packageName %>.repository", includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, value =[<% if (reactive) { %>Reactive<% } %>Neo4jRepository::class])) +<%_ } else { _%> +@Enable<% if (reactive) { %>Reactive<% } %>Neo4jRepositories("<%= packageName %>.repository") +<%_ } _%> +<%_ if (searchEngine === 'elasticsearch') { _%> +@Enable<% if (reactive) { %>Reactive<% } %>ElasticsearchRepositories("<%= packageName %>.repository.search") +<%_ } _%> +public class DatabaseConfiguration { + @Bean(<% if (reactive) { %>Reactive<% } %>Neo4jRepositoryConfigurationExtension.DEFAULT_TRANSACTION_MANAGER_BEAN_NAME) + fun transactionManager(driver: Driver, databaseNameProvider: <% if (reactive) { %>Reactive<% } %>DatabaseSelectionProvider): <% if (reactive) { %>Reactive<% } %>TransactionManager { + return <% if (reactive) { %>Reactive<% } %>Neo4jTransactionManager(driver, databaseNameProvider) + } +} diff --git a/generators/server/templates/src/main/kotlin/package/config/DatabaseConfiguration_sql.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/DatabaseConfiguration_sql.kt.ejs new file mode 100644 index 000000000..e18bf9be4 --- /dev/null +++ b/generators/server/templates/src/main/kotlin/package/config/DatabaseConfiguration_sql.kt.ejs @@ -0,0 +1,222 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + +This file is part of the JHipster project, see https://jhipster.github.io/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> + +<%_ + let uuidConversionNeeded = (reactive && !(prodDatabaseType === 'postgresql')) +_%> +package <%= packageName %>.config + +import tech.jhipster.config.JHipsterConstants +<%_ if (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory') { _%> +import tech.jhipster.config.h2.H2ConfigurationHelper +<%_ } _%> +<%_ if (databaseType === 'sql' && reactive) { _%> +import io.r2dbc.spi.ConnectionFactory +<%_ } _%> +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +<%_ if (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory') { _%> +import org.springframework.context.annotation.Profile +<%_ } _%> +<%_ if (reactive) { _%> +import org.springframework.core.convert.converter.Converter +<%_ } _%> +<%_ if (searchEngine === 'elasticsearch') { _%> +import org.springframework.data.elasticsearch.repository.config.Enable<% if (reactive) { %>Reactive<% } %>ElasticsearchRepositories +<%_ } _%> +<%_ if (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory') { _%> +import org.springframework.core.env.Environment +<%_ } _%> +<%_ if (reactive) { _%> +import org.springframework.data.convert.CustomConversions +import org.springframework.data.convert.ReadingConverter +import org.springframework.data.convert.WritingConverter +import org.springframework.data.r2dbc.convert.R2dbcCustomConversions +import org.springframework.data.r2dbc.convert.MappingR2dbcConverter +import org.springframework.data.r2dbc.dialect.DialectResolver +import org.springframework.data.r2dbc.dialect.R2dbcDialect +import org.springframework.data.r2dbc.query.UpdateMapper +import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories +import org.springframework.data.relational.core.dialect.RenderContextFactory +import org.springframework.data.relational.core.sql.render.SqlRenderer +<%_ } else { _%> +import org.springframework.data.jpa.repository.config.EnableJpaAuditing +import org.springframework.data.jpa.repository.config.EnableJpaRepositories +<%_ } _%> +import org.springframework.transaction.annotation.EnableTransactionManagement + +<%_ if (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory') { _%> +import java.sql.SQLException +<%_ } _%> +<%_ if (reactive) { _%> +import java.time.Duration +import java.time.Instant +import java.time.LocalDateTime +import java.time.ZoneId +import java.time.ZoneOffset +import java.time.ZonedDateTime +import java.util.ArrayList +import java.util.BitSet +import java.util.Collections +import java.util.List + <%_ if (uuidConversionNeeded) { _%> +import java.util.UUID + <%_ } _%> +<%_ } _%> + +@Configuration +<%_ if (reactive) { _%> +@EnableR2dbcRepositories("<%= packageName %>.repository") +<%_ } else { _%> +@EnableJpaRepositories("<%= packageName %>.repository") +@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware") +<%_ } _%> +@EnableTransactionManagement +<%_ if (searchEngine === 'elasticsearch') { _%> +@Enable<% if (reactive) { %>Reactive<% } %>ElasticsearchRepositories("<%= packageName %>.repository.search") +<%_ } _%> +public class DatabaseConfiguration<% if (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory') { %>(val env: Environment)<% } %> { + +<%_ if (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory') { _%> + private val log = LoggerFactory.getLogger(javaClass) + + /** + * Open the TCP port for the H2 database, so it is available remotely. + * + * @return the H2 database TCP server. + * @throws SQLException if the server failed to start. + */ + @Throws(SQLException::class) + @Bean(initMethod = "start", destroyMethod = "stop") + @Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) + fun h2TCPServer(): Any { + val port = getValidPortForH2() + log.debug("H2 database is available on port $port") + return H2ConfigurationHelper.createServer(port) + } + + private fun getValidPortForH2(): String { + var port = Integer.parseInt(env.getProperty("server.port")) + if (port < 10000) { + port += 10000 + } else { + if (port < 63536) { + port += 2000 + } else { + port -= 2000 + } + } + return port.toString() + } +<%_ } _%> +<% if (uuidConversionNeeded) { %> + + /** + * Simple singleton to convert [UUID]s to their [String] representation. + */ + @WritingConverter + object UUIDToStringConverter : Converter { + override fun convert(source: UUID) = source.toString() + } + + /** + * Simple singleton to convert from [String] [UUID] representation. + */ + @ReadingConverter + object StringToUUIDConverter : Converter { + override fun convert(source: String) = + if (source == null) null else UUID.fromString(source) + } + +<%_ } _%> +<%_ if (reactive) { _%> + // LocalDateTime seems to be the only type that is supported across all drivers atm + // See https://github.com/r2dbc/r2dbc-h2/pull/139 https://github.com/mirromutth/r2dbc-mysql/issues/105 + @Bean + fun r2dbcCustomConversions(connectionFactory: ConnectionFactory): R2dbcCustomConversions { + val dialect = DialectResolver.getDialect(connectionFactory) + val converters = dialect.converters.toMutableList() + converters.add(InstantWriteConverter) + converters.add(InstantReadConverter) + converters.add(BitSetReadConverter) + converters.add(DurationWriteConverter) + converters.add(DurationReadConverter) + converters.add(ZonedDateTimeReadConverter) + converters.add(ZonedDateTimeWriteConverter) + <%_ if (uuidConversionNeeded) { _%> + converters.add(StringToUUIDConverter) + converters.add(UUIDToStringConverter) + <%_ } _%> + converters.addAll(R2dbcCustomConversions.STORE_CONVERTERS) + return R2dbcCustomConversions(CustomConversions.StoreConversions.of(dialect.simpleTypeHolder, converters), mutableListOf()) + } + + + + @Bean + fun dialect(connectionFactory: ConnectionFactory) = DialectResolver.getDialect(connectionFactory) + + @Bean + fun updateMapper(dialect: R2dbcDialect, mappingR2dbcConverter: MappingR2dbcConverter) = UpdateMapper(dialect, mappingR2dbcConverter) + + @Bean + fun sqlRenderer(dialect: R2dbcDialect): SqlRenderer { + val factory = RenderContextFactory(dialect) + return SqlRenderer.create(factory.createRenderContext()) + } + + @WritingConverter + object InstantWriteConverter: Converter { + override fun convert(source: Instant) = LocalDateTime.ofInstant(source, ZoneOffset.UTC) + } + + @ReadingConverter + object InstantReadConverter: Converter { + override fun convert(localDateTime: LocalDateTime) = localDateTime.toInstant(ZoneOffset.UTC) + } + + @ReadingConverter + object BitSetReadConverter : Converter { + override fun convert(bitSet: BitSet): Boolean = bitSet.get(0) + } + + @ReadingConverter + object ZonedDateTimeReadConverter : Converter { + override fun convert(localDateTime: LocalDateTime) = ZonedDateTime.of(localDateTime, ZoneOffset.UTC) + } + + @WritingConverter + object ZonedDateTimeWriteConverter : Converter { + override fun convert(zonedDateTime: ZonedDateTime) = zonedDateTime.toLocalDateTime() + } + + @WritingConverter + object DurationWriteConverter : Converter { + override fun convert(source: Duration?) = if (source != null) source.toMillis() else null + } + + @ReadingConverter + object DurationReadConverter : Converter { + override fun convert(source: Long?) = if(source != null) Duration.ofMillis(source) else null + } + +<%_ } _%> +} diff --git a/generators/server/templates/src/main/kotlin/package/config/ElasticsearchConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/ElasticsearchConfiguration.kt.ejs index 98f296d3f..313b7a67a 100644 --- a/generators/server/templates/src/main/kotlin/package/config/ElasticsearchConfiguration.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/config/ElasticsearchConfiguration.kt.ejs @@ -18,29 +18,15 @@ -%> package <%= packageName %>.config -import com.fasterxml.jackson.core.type.TypeReference -import com.fasterxml.jackson.databind.DeserializationFeature -import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.databind.SerializationFeature -<%_ if (!reactive) { _%> -import com.github.vanroy.springdata.jest.JestElasticsearchTemplate -import com.github.vanroy.springdata.jest.mapper.DefaultJestResultsMapper -import io.searchbox.client.JestClient -<%_ } _%> -import org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchProperties -import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -<%_ if (!reactive) { _%> -import org.springframework.context.annotation.Primary -import org.springframework.data.elasticsearch.core.ElasticsearchOperations -import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter -<%_ } _%> -import org.springframework.data.elasticsearch.core.EntityMapper -<%_ if (databaseType === 'mongodb' || !reactive) { _%> -import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext -<%_ } _%> +import org.springframework.core.convert.converter.Converter +import org.springframework.data.convert.ReadingConverter +import org.springframework.data.convert.WritingConverter +import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport +import org.springframework.data.elasticsearch.core.convert.ElasticsearchCustomConversions <%_ if (databaseType === 'mongodb') { _%> +import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchPersistentProperty import org.springframework.data.mapping.PersistentEntity @@ -48,69 +34,97 @@ import org.springframework.data.mapping.model.Property import org.springframework.data.mapping.model.SimpleTypeHolder import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchPersistentEntity <%_ } _%> -import org.springframework.data.mapping.MappingException -import java.io.IOException +import java.time.Instant +import java.time.LocalDate +import java.time.ZoneId +import java.time.ZonedDateTime @Configuration -@EnableConfigurationProperties(ElasticsearchProperties::class) -class ElasticsearchConfiguration(private val mapper: ObjectMapper) { +class ElasticsearchConfiguration: ElasticsearchConfigurationSupport() { @Bean - fun getEntityMapper() = CustomEntityMapper(mapper) - -<%_ if (databaseType === 'mongodb') { _%> - - @Bean - fun mappingContext() = CustomElasticsearchMappingContext() -<%_ } _%> -<%_ if (!reactive) { _%> - @Bean - @Primary - fun elasticsearchTemplate( - jestClient: JestClient, - elasticsearchConverter: ElasticsearchConverter, - mappingContext: SimpleElasticsearchMappingContext, - mapper: EntityMapper - ) = JestElasticsearchTemplate( - jestClient, - elasticsearchConverter, - DefaultJestResultsMapper(mappingContext, mapper) + override fun elasticsearchCustomConversions() = ElasticsearchCustomConversions( + listOf ( + ZonedDateTimeWritingConverter(), + ZonedDateTimeReadingConverter(), + InstantWritingConverter(), + InstantReadingConverter(), + LocalDateWritingConverter(), + LocalDateReadingConverter() + ) ) -<%_ } _%> - inner class CustomEntityMapper(private val objectMapper: ObjectMapper) : EntityMapper { - init { - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true) - objectMapper.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, true) - objectMapper.configure(SerializationFeature.INDENT_OUTPUT, false) - objectMapper.configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, true) + @WritingConverter + class ZonedDateTimeWritingConverter: Converter { + override fun convert(source: ZonedDateTime?): String? { + if (source == null) { + return null; + } + return source.toInstant().toString() + } + } + + @ReadingConverter + class ZonedDateTimeReadingConverter: Converter { + override fun convert(source: String?): ZonedDateTime? { + if (source == null) { + return null + } + return Instant.parse(source).atZone(ZoneId.systemDefault()) } + } - @Throws(IOException::class) - override fun mapToString(`object`: Any) = objectMapper.writeValueAsString(`object`) + @WritingConverter + class InstantWritingConverter: Converter { + override fun convert(source: Instant?): String? { + if (source == null) { + return null + } + return source.toString() + } + } - @Throws(IOException::class) - override fun mapToObject(source: String, clazz: Class) = objectMapper.readValue(source, clazz) + @ReadingConverter + class InstantReadingConverter: Converter { + override fun convert(source: String?): Instant? { + if (source == null) { + return null + } + return Instant.parse(source) + } + } - override fun mapObject(source: Any): Map { - try { - return objectMapper.readValue(mapToString(source), object: TypeReference>() {}) - } catch (e: IOException) { - throw MappingException(e.message, e) + @WritingConverter + class LocalDateWritingConverter: Converter { + override fun convert(source: LocalDate?): String? { + if (source == null) { + return null } + return source.toString() } + } - override fun readObject(source: Map, targetType: Class): T { - try { - return mapToObject(mapToString(source), targetType) - } catch (e: IOException) { - throw MappingException(e.message, e) + @ReadingConverter + class LocalDateReadingConverter: Converter { + override fun convert(source: String?): LocalDate? { + if (source == null) { + return null } + return LocalDate.parse(source) } } +<%_ if (databaseType === 'mongodb') { _%> + + @Bean + override fun elasticsearchMappingContext(elasticsearchCustomConversions: ElasticsearchCustomConversions?): SimpleElasticsearchMappingContext? { + val mappingContext = CustomElasticsearchMappingContext() + mappingContext.setInitialEntitySet(this.initialEntitySet) + mappingContext.setSimpleTypeHolder(elasticsearchCustomConversions().simpleTypeHolder) + return mappingContext + } +<%_ } _%> } <%_ if (databaseType === 'mongodb') { _%> diff --git a/generators/server/templates/src/main/kotlin/package/config/GatewayConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/GatewayConfiguration.kt.ejs deleted file mode 100644 index 8d8f80be7..000000000 --- a/generators/server/templates/src/main/kotlin/package/config/GatewayConfiguration.kt.ejs +++ /dev/null @@ -1,64 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.config - -import io.github.jhipster.config.JHipsterProperties - -import <%= packageName %>.gateway.accesscontrol.AccessControlFilter -import <%= packageName %>.gateway.responserewriting.SwaggerBasePathRewritingFilter -<%_ if (cacheProvider === 'hazelcast') { _%> -import <%= packageName %>.gateway.ratelimiting.RateLimitingFilter -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty -<%_ } _%> - -import org.springframework.cloud.netflix.zuul.filters.RouteLocator -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration - -@Configuration -class GatewayConfiguration { - - @Configuration - class SwaggerBasePathRewritingConfiguration { - @Bean - fun swaggerBasePathRewritingFilter() = SwaggerBasePathRewritingFilter() - } - - @Configuration - class AccessControlFilterConfiguration { - @Bean - fun accessControlFilter(routeLocator: RouteLocator, jHipsterProperties: JHipsterProperties) = - AccessControlFilter(routeLocator, jHipsterProperties) - } - - <%_ if (cacheProvider === 'hazelcast') { _%> - /** - * Configures the Zuul filter that limits the number of API calls per user. - * - * - * This uses Bucket4J to limit the API calls, see [<%= packageName %>.gateway.ratelimiting.RateLimitingFilter]. - */ - @Configuration - @ConditionalOnProperty("jhipster.gateway.rate-limiting.enabled") - class RateLimitingConfiguration(private val jHipsterProperties: JHipsterProperties) { - @Bean - fun rateLimitingFilter() = RateLimitingFilter(jHipsterProperties) - } - <%_ } _%> -} diff --git a/generators/server/templates/src/main/kotlin/package/config/LiquibaseConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/LiquibaseConfiguration.kt.ejs index ec52094f1..64ed45cf9 100644 --- a/generators/server/templates/src/main/kotlin/package/config/LiquibaseConfiguration.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/config/LiquibaseConfiguration.kt.ejs @@ -18,11 +18,11 @@ -%> package <%= packageName %>.config -import io.github.jhipster.config.JHipsterConstants +import tech.jhipster.config.JHipsterConstants <%_ if (!reactive) { _%> -import io.github.jhipster.config.liquibase.SpringLiquibaseUtil +import tech.jhipster.config.liquibase.SpringLiquibaseUtil <%_ } else { _%> -import io.github.jhipster.config.liquibase.AsyncSpringLiquibase +import tech.jhipster.config.liquibase.AsyncSpringLiquibase <%_ } _%> import liquibase.integration.spring.SpringLiquibase import org.slf4j.LoggerFactory @@ -103,8 +103,8 @@ class LiquibaseConfiguration(private val env: Environment) { } fun createNewDataSource(liquibaseProperties: LiquibaseProperties, dataSourceProperties: R2dbcProperties): DataSource { - val user = getProperty(liquibaseProperties.user, dataSourceProperties.determineUsername()) - val password = getProperty(liquibaseProperties.password, dataSourceProperties.determinePassword()) + val user = getProperty(liquibaseProperties.user, dataSourceProperties.getUsername()) + val password = getProperty(liquibaseProperties.password, dataSourceProperties.getPassword()) return DataSourceBuilder.create() .url(liquibaseProperties.url) .username(user) diff --git a/generators/server/templates/src/main/kotlin/package/config/LocaleConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/LocaleConfiguration.kt.ejs index d0ccbb71d..c9c390312 100644 --- a/generators/server/templates/src/main/kotlin/package/config/LocaleConfiguration.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/config/LocaleConfiguration.kt.ejs @@ -19,7 +19,7 @@ package <%= packageName %>.config <%_ if (!reactive) { _%> -import io.github.jhipster.config.locale.AngularCookieLocaleResolver +import tech.jhipster.config.locale.AngularCookieLocaleResolver import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration diff --git a/generators/server/templates/src/main/kotlin/package/config/LoggingAspectConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/LoggingAspectConfiguration.kt.ejs index 39de1c24c..35838b53c 100644 --- a/generators/server/templates/src/main/kotlin/package/config/LoggingAspectConfiguration.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/config/LoggingAspectConfiguration.kt.ejs @@ -20,7 +20,7 @@ package <%= packageName %>.config import <%= packageName %>.aop.logging.LoggingAspect -import io.github.jhipster.config.JHipsterConstants +import tech.jhipster.config.JHipsterConstants import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration diff --git a/generators/server/templates/src/main/kotlin/package/config/LoggingConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/LoggingConfiguration.kt.ejs index dc3f74fa3..f2a90b1ad 100644 --- a/generators/server/templates/src/main/kotlin/package/config/LoggingConfiguration.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/config/LoggingConfiguration.kt.ejs @@ -20,10 +20,10 @@ package <%= packageName %>.config import ch.qos.logback.classic.LoggerContext import com.fasterxml.jackson.databind.ObjectMapper -import io.github.jhipster.config.JHipsterProperties +import tech.jhipster.config.JHipsterProperties import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Value -<%_ if (serviceDiscoveryType && ['microservice', 'gateway', 'uaa'].includes(applicationType)) { _%> +<%_ if (serviceDiscoveryType && ['microservice', 'gateway'].includes(applicationType)) { _%> import org.springframework.boot.info.BuildProperties <%_ } _%> <%_ if (serviceDiscoveryType === "consul") { _%> @@ -34,10 +34,9 @@ import org.springframework.cloud.context.config.annotation.RefreshScope <%_ } _%> import org.springframework.context.annotation.Configuration -import io.github.jhipster.config.logging.LoggingUtils.addContextListener -import io.github.jhipster.config.logging.LoggingUtils.addJsonConsoleAppender -import io.github.jhipster.config.logging.LoggingUtils.addLogstashTcpSocketAppender -import io.github.jhipster.config.logging.LoggingUtils.setMetricsMarkerLogbackFilter +import tech.jhipster.config.logging.LoggingUtils.addContextListener +import tech.jhipster.config.logging.LoggingUtils.addJsonConsoleAppender +import tech.jhipster.config.logging.LoggingUtils.addLogstashTcpSocketAppender /* * Configures the console and Logstash log appenders from the app properties. @@ -53,7 +52,7 @@ class LoggingConfiguration( <%_ if (serviceDiscoveryType === "consul") { _%> consulRegistration: ConsulRegistration?, <%_ } _%> - <%_ if (serviceDiscoveryType && ['microservice', 'gateway', 'uaa'].includes(applicationType)) { _%> + <%_ if (serviceDiscoveryType && ['microservice', 'gateway'].includes(applicationType)) { _%> buildProperties: BuildProperties?, <%_ } _%> mapper: ObjectMapper @@ -64,7 +63,7 @@ class LoggingConfiguration( val map = mutableMapOf() map["app_name"] = appName map["app_port"] = serverPort - <%_ if (serviceDiscoveryType && ['microservice', 'gateway', 'uaa'].includes(applicationType)) { _%> + <%_ if (serviceDiscoveryType && ['microservice', 'gateway'].includes(applicationType)) { _%> buildProperties?.apply { map["version"] = this.version } <%_ } _%> <%_ if (serviceDiscoveryType === 'consul') { _%> @@ -84,8 +83,5 @@ class LoggingConfiguration( if (loggingProperties.isUseJsonFormat || logstashProperties.isEnabled) { addContextListener(context, customFields, loggingProperties) } - if (jHipsterProperties.metrics.logs.isEnabled) { - setMetricsMarkerLogbackFilter(context, loggingProperties.isUseJsonFormat) - } } } diff --git a/generators/server/templates/src/main/kotlin/package/config/OAuth2SsoConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/OAuth2SsoConfiguration.kt.ejs index eca74a928..8f4ad64e7 100644 --- a/generators/server/templates/src/main/kotlin/package/config/OAuth2SsoConfiguration.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/config/OAuth2SsoConfiguration.kt.ejs @@ -68,6 +68,7 @@ class OAuth2SsoConfiguration(private val corsFilter: CorsFilter) : WebSecurityCo .authorizeRequests() .antMatchers("/api/**").authenticated() .antMatchers("/management/health").permitAll() + .antMatchers("/management/health/**").permitAll() .antMatchers("/management/**").hasAuthority(ADMIN) .anyRequest().permitAll() } diff --git a/generators/server/templates/src/main/kotlin/package/config/OpenApiConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/OpenApiConfiguration.kt.ejs index b3c4150cb..42119b78a 100644 --- a/generators/server/templates/src/main/kotlin/package/config/OpenApiConfiguration.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/config/OpenApiConfiguration.kt.ejs @@ -18,18 +18,9 @@ limitations under the License. -%> package <%= packageName %>.config -<%_ - let springFox3 = false - if (reactive && (applicationType === 'gateway' || applicationType === 'monolith')) { - springFox3 = true - } -_%> -<%_ if (!springFox3) { _%> -import com.google.common.base.Predicates -<%_ } _%> -import io.github.jhipster.config.JHipsterConstants -import io.github.jhipster.config.JHipsterProperties -import io.github.jhipster.config.apidoc.customizer.SwaggerCustomizer +import tech.jhipster.config.JHipsterConstants +import tech.jhipster.config.JHipsterProperties +import tech.jhipster.config.apidoc.customizer.SpringfoxCustomizer import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.context.annotation.Profile @@ -49,21 +40,17 @@ import java.util.HashSet import springfox.documentation.builders.PathSelectors.regex @Configuration -@Profile(JHipsterConstants.SPRING_PROFILE_SWAGGER) +@Profile(JHipsterConstants.SPRING_PROFILE_API_DOCS) class OpenApiConfiguration { @Bean - fun noApiFirstCustomizer() = SwaggerCustomizer { docket -> docket.select() -<%_ if (springFox3) { _%> + fun noApiFirstCustomizer() = SpringfoxCustomizer { docket -> docket.select() .apis(RequestHandlerSelectors.basePackage("<%= packageName %>.web.api").negate()) -<%_ } else { _%> - .apis(Predicates.not(RequestHandlerSelectors.basePackage("<%= packageName %>.web.api"))) -<%_ } _%> } @Bean fun apiFirstDocket(jHipsterProperties: JHipsterProperties): Docket { - val properties = jHipsterProperties.swagger + val properties = jHipsterProperties.apiDocs val contact = Contact( properties.contactName, properties.contactUrl, @@ -81,7 +68,7 @@ class OpenApiConfiguration { mutableListOf() ) - return Docket(DocumentationType.SWAGGER_2) + return Docket(DocumentationType.OAS_30) .groupName("openapi") .host(properties.host) .protocols(properties.protocols.toSet()) diff --git a/generators/server/templates/src/main/kotlin/package/config/ReactorConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/ReactorConfiguration.kt.ejs index 17de257a4..bd4a20e19 100644 --- a/generators/server/templates/src/main/kotlin/package/config/ReactorConfiguration.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/config/ReactorConfiguration.kt.ejs @@ -1,6 +1,6 @@ package <%= packageName %>.config -import io.github.jhipster.config.JHipsterConstants +import tech.jhipster.config.JHipsterConstants import org.springframework.context.annotation.Configuration import org.springframework.context.annotation.Profile import reactor.core.publisher.Hooks diff --git a/generators/server/templates/src/main/kotlin/package/config/SecurityConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/SecurityConfiguration.kt.ejs index 11de2b4e0..89b755561 100644 --- a/generators/server/templates/src/main/kotlin/package/config/SecurityConfiguration.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/config/SecurityConfiguration.kt.ejs @@ -18,7 +18,6 @@ -%> package <%= packageName %>.config -<%_ if (authenticationType === 'session' || authenticationType === 'jwt' || authenticationType === 'oauth2') { _%> import <%= packageName %>.security.ADMIN <%_ if (authenticationType === 'oauth2' && applicationType !== 'microservice') { _%> import <%= packageName %>.security.extractAuthorityFromClaims @@ -29,14 +28,14 @@ import <%= packageName %>.security.jwt.TokenProvider <%_ } _%> <%_ if (authenticationType === 'session') { _%> <%_ if (!skipUserManagement) { _%> -import io.github.jhipster.config.JHipsterProperties +import tech.jhipster.config.JHipsterProperties <%_ } _%> -import io.github.jhipster.security.AjaxAuthenticationFailureHandler -import io.github.jhipster.security.AjaxAuthenticationSuccessHandler -import io.github.jhipster.security.AjaxLogoutSuccessHandler +import tech.jhipster.security.AjaxAuthenticationFailureHandler +import tech.jhipster.security.AjaxAuthenticationSuccessHandler +import tech.jhipster.security.AjaxLogoutSuccessHandler <%_ } _%> <%_ if (authenticationType === 'oauth2') { _%> -import io.github.jhipster.config.JHipsterProperties +import tech.jhipster.config.JHipsterProperties <%_ } _%> import org.springframework.context.annotation.Bean @@ -44,16 +43,16 @@ import org.springframework.context.annotation.Import <%_ if (authenticationType === 'oauth2') { _%> import org.springframework.core.convert.converter.Converter <%_ } _%> - <%_ if (authenticationType !== 'uaa' && !(applicationType === 'microservice' && authenticationType === 'oauth2')) { _%> + <%_ if (applicationType !== 'microservice' || authenticationType !== 'oauth2') { _%> import org.springframework.http.HttpMethod <%_ } else { _%> - <%_ if (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory') { _%> + <%_ if (applicationType !== 'microservice' || authenticationType !== 'oauth2') { _%> import org.springframework.security.config.annotation.web.builders.WebSecurity; <%_ } _%> <%_ } _%> import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity import org.springframework.security.config.annotation.web.builders.HttpSecurity - <%_ if (authenticationType !== 'uaa' && !(applicationType === 'microservice' && authenticationType === 'oauth2')) { _%> + <%_ if (!(applicationType === 'microservice' && authenticationType === 'oauth2')) { _%> import org.springframework.security.config.annotation.web.builders.WebSecurity <%_ } _%> import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity @@ -74,10 +73,6 @@ import org.springframework.security.oauth2.jwt.JwtDecoders import org.springframework.security.oauth2.jwt.JwtValidators import org.springframework.security.oauth2.jwt.NimbusJwtDecoder import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter - <%_ if (applicationType === 'gateway' && serviceDiscoveryType) { _%> -import <%= packageName %>.security.oauth2.AuthorizationHeaderFilter -import <%= packageName %>.security.oauth2.AuthorizationHeaderUtil - <%_ } _%> import org.springframework.beans.factory.annotation.Value import org.springframework.security.core.GrantedAuthority <%_ if (applicationType !== 'microservice') { _%> @@ -102,6 +97,11 @@ import <%= packageName %>.security.oauth2.JwtGrantedAuthorityConverter <%_ if (authenticationType === 'jwt' && applicationType !== 'microservice') { _%> import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter <%_ } _%> + <%_ if (authenticationType === 'oauth2' && applicationType === 'monolith') { _%> +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository +import org.springframework.boot.web.client.RestTemplateBuilder +import <%= packageName %>.security.oauth2.CustomClaimConverter + <%_ } _%> import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter <%_ if (applicationType !== 'microservice') { _%> import org.springframework.web.filter.CorsFilter @@ -148,7 +148,7 @@ class SecurityConfiguration( @Bean fun passwordEncoder() = BCryptPasswordEncoder() <%_ } _%> - <%_ if (authenticationType !== 'uaa' && applicationType !== 'microservice') { _%> + <%_ if (applicationType !== 'microservice') { _%> override fun configure(web: WebSecurity?) { web!!.ignoring() @@ -161,7 +161,7 @@ class SecurityConfiguration( <%_ if (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory') { _%> .antMatchers("/h2-console/**") <%_ } _%> - .antMatchers("/swagger-ui/index.html") + .antMatchers("/swagger-ui/**") .antMatchers("/test/**") } <%_ } else { _%> @@ -224,7 +224,7 @@ class SecurityConfiguration( .and() .referrerPolicy(ReferrerPolicyHeaderWriter.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN) .and() - .featurePolicy("geolocation 'none'; midi 'none'; sync-xhr 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; speaker 'none'; fullscreen 'self'; payment 'none'") + .featurePolicy("geolocation 'none'; midi 'none'; sync-xhr 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; fullscreen 'self'; payment 'none'") .and() .frameOptions() .deny() @@ -246,12 +246,16 @@ class SecurityConfiguration( .antMatchers("/authorize").authenticated() .antMatchers("/api/auth-info").permitAll() <%_ } _%> + .antMatchers("/api/admin/**").hasAuthority(ADMIN) .antMatchers("/api/**").authenticated() <%_ if (websocket === 'spring-websocket') { _%> - .antMatchers("/websocket/tracker").hasAuthority(ADMIN) - .antMatchers("/websocket/**").permitAll() + .antMatchers("/websocket/**").authenticated() + <%_ } _%> + <%_ if (applicationType === 'gateway') { _%> + .antMatchers("/services/*/v3/api-docs").hasAuthority(ADMIN) <%_ } _%> .antMatchers("/management/health").permitAll() + .antMatchers("/management/health/**").permitAll() .antMatchers("/management/info").permitAll() .antMatchers("/management/prometheus").permitAll() .antMatchers("/management/**").hasAuthority(ADMIN) @@ -312,7 +316,7 @@ class SecurityConfiguration( <%_ } _%> @Bean - fun jwtDecoder(): JwtDecoder { + fun jwtDecoder(<%_ if (authenticationType === 'oauth2' && applicationType === 'monolith') { _%>clientRegistrationRepository: ClientRegistrationRepository, restTemplateBuilder: RestTemplateBuilder<%_ } _%>): JwtDecoder { val jwtDecoder = JwtDecoders.fromOidcIssuerLocation(issuerUri) as NimbusJwtDecoder val audienceValidator = AudienceValidator(jHipsterProperties.security.oauth2.audience) @@ -320,85 +324,11 @@ class SecurityConfiguration( val withAudience = DelegatingOAuth2TokenValidator(withIssuer, audienceValidator) jwtDecoder.setJwtValidator(withAudience) + <%_ if (authenticationType === 'oauth2' && applicationType === 'monolith') { _%> + jwtDecoder.setClaimSetConverter(CustomClaimConverter(clientRegistrationRepository.findByRegistrationId("oidc"), restTemplateBuilder.build())) + <%_ } _%> return jwtDecoder } - <%_ if (applicationType === 'gateway' && serviceDiscoveryType) { _%> - - @Bean - fun authHeaderFilter(headerUtil: AuthorizationHeaderUtil) = AuthorizationHeaderFilter(headerUtil) - <%_ } _%> <%_ } _%> } -<%_ } _%> -<%_ if (authenticationType === 'uaa') { _%> -import <%= packageName %>.config.oauth2.OAuth2JwtAccessTokenConverter -import <%= packageName %>.config.oauth2.OAuth2Properties -import <%= packageName %>.security.oauth2.OAuth2SignatureVerifierClient -import <%= packageName %>.security.ADMIN - -import org.springframework.beans.factory.annotation.Qualifier -import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity -import org.springframework.security.config.annotation.web.builders.HttpSecurity -import org.springframework.security.config.http.SessionCreationPolicy -import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer -import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter -import org.springframework.security.oauth2.provider.token.TokenStore -import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter -import org.springframework.security.oauth2.provider.token.store.JwtTokenStore -import org.springframework.security.web.csrf.CookieCsrfTokenRepository -<%_ if (applicationType === 'gateway') { _%> -import org.springframework.security.web.csrf.CsrfFilter -import org.springframework.web.filter.CorsFilter -<%_ } _%> -import org.springframework.web.client.RestTemplate - -@Configuration -@EnableResourceServer -@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) -class SecurityConfiguration(private val oAuth2Properties: OAuth2Properties<% if (applicationType === 'gateway') { %>, private val corsFilter: CorsFilter<% } %>) : ResourceServerConfigurerAdapter() { - - @Throws(Exception::class) - override fun configure(http: HttpSecurity) { - http - .csrf() - <%_ if (applicationType === 'gateway') { _%> - .ignoringAntMatchers("/h2-console/**") - .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) - .and() - .addFilterBefore(corsFilter, CsrfFilter::class.java) - <%_ } else { _%> - .disable() - <%_ } _%> - .headers() - .frameOptions() - .disable() - .and() - .sessionManagement() - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - .and() - .authorizeRequests() - .antMatchers("/api/**").authenticated() - .antMatchers("/management/health").permitAll() - .antMatchers("/management/info").permitAll() - .antMatchers("/management/prometheus").permitAll() - .antMatchers("/management/**").hasAuthority(ADMIN) - } - - @Bean - fun tokenStore(jwtAccessTokenConverter: JwtAccessTokenConverter) = JwtTokenStore(jwtAccessTokenConverter) - - @Bean - fun jwtAccessTokenConverter(signatureVerifierClient: OAuth2SignatureVerifierClient) = - OAuth2JwtAccessTokenConverter(oAuth2Properties, signatureVerifierClient) - - @Bean - @Qualifier("loadBalancedRestTemplate") - fun loadBalancedRestTemplate(customizer: RestTemplateCustomizer) = - RestTemplate().apply { customizer.customize(this) } - -} -<%_ } _%> diff --git a/generators/server/templates/src/main/kotlin/package/config/ReactiveSecurityConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/SecurityConfiguration_reactive.kt.ejs similarity index 79% rename from generators/server/templates/src/main/kotlin/package/config/ReactiveSecurityConfiguration.kt.ejs rename to generators/server/templates/src/main/kotlin/package/config/SecurityConfiguration_reactive.kt.ejs index a3b5812d8..7cb7b83e5 100644 --- a/generators/server/templates/src/main/kotlin/package/config/ReactiveSecurityConfiguration.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/config/SecurityConfiguration_reactive.kt.ejs @@ -1,10 +1,10 @@ <%# Copyright 2013-2020 the original author or authors from the JHipster project. - This file is part of the JHipster project, see https://www.jhipster.tech/ +This file is part of the JHipster project, see https://jhipster.github.io/ for more information. - Licensed under the Apache License, Version 2.0 (the "License"); + Licensed under the Apache License, Version 2.0 (the "License") you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -16,37 +16,29 @@ See the License for the specific language governing permissions and limitations under the License. -%> -<%_ -let withAudit = ((authenticationType === 'session' && !skipUserManagement) || authenticationType === 'oauth2') && ['sql', 'mongodb', 'couchbase', 'neo4j'].includes(databaseType); -_%> package <%= packageName %>.config import <%= packageName %>.security.ADMIN -<%_ if (authenticationType === 'oauth2') { _%> -import <%= packageName %>.security.extractAuthorityFromClaims -<%_ } _%> <%_ if (authenticationType === 'jwt') { _%> import <%= packageName %>.security.jwt.JWTFilter import <%= packageName %>.security.jwt.TokenProvider <%_ } _%> +<%_ if (authenticationType === 'oauth2' && applicationType !== 'microservice') { _%> +import <%= packageName %>.security.extractAuthorityFromClaims +<%_ } _%> <%_ if (authenticationType === 'session' || authenticationType === 'oauth2') { _%> <%_ if (authenticationType === 'oauth2') { _%> +import <%= packageName %>.security.SecurityUtils import <%= packageName %>.security.oauth2.AudienceValidator import <%= packageName %>.security.oauth2.JwtGrantedAuthorityConverter - <%_ if (withAudit) { _%> -import <%= packageName %>.service.AuditEventService - <%_ } _%> import org.springframework.security.authentication.AbstractAuthenticationToken import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter <%_ } _%> - <%_ if (!skipUserManagement && withAudit) { _%> -import <%= packageName %>.service.AuditEventService - <%_ } _%> -import io.github.jhipster.web.filter.reactive.CookieCsrfFilter +import tech.jhipster.web.filter.reactive.CookieCsrfFilter <%_ } _%> <%_ if (authenticationType === 'oauth2') { _%> import org.springframework.beans.factory.annotation.Value -import io.github.jhipster.config.JHipsterProperties +import tech.jhipster.config.JHipsterProperties <%_ } _%> <%_ if (skipUserManagement && authenticationType !== 'oauth2') { _%> import org.springframework.boot.autoconfigure.security.SecurityProperties @@ -72,16 +64,10 @@ import org.springframework.security.config.annotation.web.reactive.EnableWebFlux import org.springframework.security.config.web.server.SecurityWebFiltersOrder import org.springframework.security.config.web.server.ServerHttpSecurity <%_ if (authenticationType === 'session') { _%> - <%_ if (withAudit) { _%> import org.springframework.security.core.Authentication - <%_ } _%> import org.springframework.security.core.AuthenticationException <%_ } _%> -<%_ if (authenticationType !== 'oauth2' && !skipUserManagement) { _%> -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder -<%_ } _%> <%_ if (authenticationType === 'oauth2') { _%> -import org.springframework.security.core.Authentication import org.springframework.security.core.GrantedAuthority import org.springframework.security.oauth2.client.oidc.userinfo.OidcReactiveOAuth2UserService import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest @@ -94,14 +80,10 @@ import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority import org.springframework.security.oauth2.jwt.* import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter import org.springframework.security.web.server.csrf.CookieServerCsrfTokenRepository - <%_ if (withAudit) { _%> -import org.springframework.security.web.server.WebFilterExchange -import org.springframework.security.web.server.authentication.RedirectServerAuthenticationSuccessHandler -import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler - <%_ } _%> +import org.springframework.security.web.server.header.ReferrerPolicyServerHttpHeadersWriter <%_ } _%> <%_ if (authenticationType !== 'oauth2') { _%> - <%_ if (!skipUserManagement) { _%> + <%_ if (skipUserManagement) { _%> import org.springframework.security.core.userdetails.MapReactiveUserDetailsService <%_ } _%> import org.springframework.security.core.userdetails.ReactiveUserDetailsService @@ -112,8 +94,9 @@ import org.springframework.security.core.userdetails.User import org.springframework.security.core.userdetails.UserDetails <%_ } _%> <%_ } _%> -<%_ if (databaseType === 'couchbase') { _%> -import org.springframework.security.data.repository.query.SecurityEvaluationContextExtension +<%_ if (!skipUserManagement) { _%> +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder +import org.springframework.security.crypto.password.PasswordEncoder <%_ } _%> import org.springframework.security.web.server.SecurityWebFilterChain <%_ if (authenticationType === 'session') { _%> @@ -135,6 +118,11 @@ import org.zalando.problem.spring.webflux.advice.security.SecurityProblemSupport <%_ if (authenticationType === 'session' || authenticationType === 'oauth2') { _%> import reactor.core.publisher.Mono <%_ } _%> +<%_ if (authenticationType === 'oauth2') { _%> + +import java.util.HashSet +import java.util.Set +<%_ } _%> import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers.pathMatchers @@ -148,16 +136,18 @@ class SecurityConfiguration( <%_ if (authenticationType === 'jwt') { _%> private val tokenProvider: TokenProvider, <%_ } _%> -<%_ if (withAudit) { _%> - private val auditEventService: AuditEventService, -<%_ } _%> <%_ if (authenticationType === 'oauth2') { _%> - @Value("\${spring.security.oauth2.client.provider.oidc.issuer-uri}") private val issuerUri: String, private val jHipsterProperties: JHipsterProperties, <%_ } _%> private val problemSupport: SecurityProblemSupport ) { + <%_ if (authenticationType === 'oauth2') { _%> + + @Value("\${spring.security.oauth2.client.provider.oidc.issuer-uri}") + private lateinit var issuerUri: String + <%_ } _%> + <%_ if (!skipUserManagement && authenticationType !== 'oauth2') { _%> @Bean fun passwordEncoder() = BCryptPasswordEncoder() @@ -169,7 +159,6 @@ class SecurityConfiguration( } <%_ } else if (authenticationType !== 'oauth2') { _%> - @Bean fun userDetailsService(properties: SecurityProperties): MapReactiveUserDetailsService { val user = properties.user @@ -194,7 +183,7 @@ class SecurityConfiguration( .securityMatcher( NegatedServerWebExchangeMatcher( OrServerWebExchangeMatcher( - pathMatchers("/app/**", "/i18n/**", "/content/**", "/swagger-ui/**", "/test/**"<% if (applicationType === 'gateway' || applicationType === 'monolith') { %>, "/webjars/**"<% } %>), + pathMatchers("/app/**", "/i18n/**", "/content/**", "/swagger-ui/**", "/swagger-resources/**", "/v2/api-docs", "/v3/api-docs", "/test/**"), pathMatchers(HttpMethod.OPTIONS, "/**") ) ) @@ -262,7 +251,7 @@ class SecurityConfiguration( .pathMatchers("/api/auth-info").permitAll() .pathMatchers("/api/**").authenticated() <%_ if (applicationType === 'monolith' || applicationType === 'gateway') { _%> - .pathMatchers("/services/**", "/swagger-resources/**", "/v2/api-docs").authenticated() + .pathMatchers("/services/**").authenticated() <%_ } _%> .pathMatchers("/management/health").permitAll() .pathMatchers("/management/info").permitAll() @@ -271,9 +260,6 @@ class SecurityConfiguration( <%_ if (authenticationType === 'oauth2') { _%> http<%_ if (['monolith', 'gateway'].includes(applicationType)) { _%>.oauth2Login() - <%_ if (withAudit) { _%> - .authenticationSuccessHandler{ exchange, authentication -> onAuthenticationSuccess(exchange, authentication) } - <%_ } _%> .and() <%_ } _%>.oauth2ResourceServer() .jwt() @@ -328,62 +314,17 @@ class SecurityConfiguration( return jwtDecoder } - <%_ if (withAudit) { _%> - private val redirectServerAuthenticationSuccessHandler = RedirectServerAuthenticationSuccessHandler() - - fun onAuthenticationSuccess(exchange: WebFilterExchange, authentication: Authentication): Mono { - return redirectServerAuthenticationSuccessHandler.onAuthenticationSuccess(exchange, authentication) - .thenReturn(authentication.principal) - .filter { it is OidcUser } - .map { (it as OidcUser).preferredUsername } - .filter { ANONYMOUS_USER != it } - .flatMap { auditEventService.saveAuthenticationSuccess(it) } - .then() - } - <%_ } _%> <%_ } _%> <%_ if (authenticationType === 'session') { _%> private fun onAuthenticationError(exchange: WebFilterExchange, e: AuthenticationException): Mono { exchange.exchange.response.statusCode = HttpStatus.UNAUTHORIZED - <%_ if (withAudit) { _%> - return exchange.exchange - .formData - .map { it.getFirst("username") } - .filter { ANONYMOUS_USER != it } - .flatMap { auditEventService.saveAuthenticationError(it, e) } - .then() - <%_ } else { _%> return Mono.empty(); - <%_ } _%> } private fun onAuthenticationSuccess(exchange: WebFilterExchange, authentication: Authentication): Mono { exchange.exchange.response.statusCode = HttpStatus.OK - <%_ if (withAudit) { _%> - return Mono.just(authentication.principal) - .filter { it is User } - .map { (it as User).username } - .filter { ANONYMOUS_USER != it } - .flatMap { auditEventService.saveAuthenticationSuccess(it) } - .then() - <%_ } else { _%> return Mono.empty(); - <%_ } _%> - } - <%_ } _%> - <%_ if(databaseType === 'couchbase') { _%> - - /** - * Disables Spring security integration with SpEL expressions since it is not yet compatible with Reactor - */ - @Bean - fun securityEvaluationContextExtension(): SecurityEvaluationContextExtension? { - return object : SecurityEvaluationContextExtension() { - override fun getRootObject(): Any? { - return null - } - } } <%_ } _%> } diff --git a/generators/server/templates/src/main/kotlin/package/config/StaticResourcesWebConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/StaticResourcesWebConfiguration.kt.ejs index be924574a..2846fefe4 100644 --- a/generators/server/templates/src/main/kotlin/package/config/StaticResourcesWebConfiguration.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/config/StaticResourcesWebConfiguration.kt.ejs @@ -18,8 +18,8 @@ -%> package <%=packageName%>.config -import io.github.jhipster.config.JHipsterConstants -import io.github.jhipster.config.JHipsterProperties +import tech.jhipster.config.JHipsterConstants +import tech.jhipster.config.JHipsterProperties import org.springframework.context.annotation.Configuration import org.springframework.context.annotation.Profile import org.springframework.http.CacheControl diff --git a/generators/server/templates/src/main/kotlin/package/config/UaaConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/UaaConfiguration.kt.ejs deleted file mode 100644 index 9503b4e5f..000000000 --- a/generators/server/templates/src/main/kotlin/package/config/UaaConfiguration.kt.ejs +++ /dev/null @@ -1,191 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.config - -import <%= packageName %>.security.ADMIN -import io.github.jhipster.config.JHipsterProperties -import org.springframework.beans.BeansException -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.beans.factory.annotation.Qualifier -import org.springframework.context.ApplicationContext -import org.springframework.context.ApplicationContextAware -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.core.io.ClassPathResource -import org.springframework.security.authentication.AuthenticationManager -import org.springframework.security.config.annotation.web.builders.HttpSecurity -import org.springframework.security.config.http.SessionCreationPolicy -import org.springframework.security.crypto.password.PasswordEncoder -import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer -import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter -import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer -import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer -import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter -import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer -import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer -import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer -import org.springframework.security.oauth2.provider.token.TokenEnhancer -import org.springframework.security.oauth2.provider.token.TokenEnhancerChain -import org.springframework.security.oauth2.provider.token.TokenStore -import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter -import org.springframework.security.oauth2.provider.token.store.JwtTokenStore -import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter -import org.springframework.web.filter.CorsFilter - -import javax.servlet.http.HttpServletResponse - -/** - * Access tokens will not expire any earlier than this. - */ -private const val MIN_ACCESS_TOKEN_VALIDITY_SECS = 60 - -@Configuration -@EnableAuthorizationServer -class UaaConfiguration( - private val jHipsterProperties: JHipsterProperties, - private val uaaProperties: UaaProperties, - private val passwordEncoder: PasswordEncoder -) : AuthorizationServerConfigurerAdapter(), ApplicationContextAware { - - private var applicationContext: ApplicationContext? = null - - @Autowired - @Qualifier("authenticationManagerBean") - private val authenticationManager: AuthenticationManager? = null - - @Throws(BeansException::class) - override fun setApplicationContext(applicationContext: ApplicationContext) { - this.applicationContext = applicationContext - } - - @EnableResourceServer - class ResourceServerConfiguration( - private val tokenStore: TokenStore, - private val corsFilter: CorsFilter - ) : ResourceServerConfigurerAdapter() { - - @Throws(Exception::class) - override fun configure(http: HttpSecurity) { - http - .exceptionHandling() - .authenticationEntryPoint { _, response, _ -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED) } - .and() - .csrf() - .disable() - .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter::class.java) - .headers() - .frameOptions() - .disable() - .and() - .sessionManagement() - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - .and() - .authorizeRequests() - .antMatchers("/api/register").permitAll() - .antMatchers("/api/activate").permitAll() - .antMatchers("/api/authenticate").permitAll() - .antMatchers("/api/account/reset-password/init").permitAll() - .antMatchers("/api/account/reset-password/finish").permitAll() - .antMatchers("/api/**").authenticated() - .antMatchers("/management/health").permitAll() - .antMatchers("/management/**").hasAuthority(ADMIN) - .antMatchers("/v2/api-docs/**").permitAll() - .antMatchers("/swagger-resources/configuration/ui").permitAll() - .antMatchers("/swagger-ui/index.html").hasAuthority(ADMIN) - } - - @Throws(Exception::class) - override fun configure(resources: ResourceServerSecurityConfigurer?) { - resources!!.resourceId("jhipster-uaa").tokenStore(tokenStore) - } - } - - @Throws(Exception::class) - override fun configure(clients: ClientDetailsServiceConfigurer?) { - var accessTokenValidity = uaaProperties.webClientConfiguration.accessTokenValidityInSeconds - accessTokenValidity = Math.max(accessTokenValidity, MIN_ACCESS_TOKEN_VALIDITY_SECS) - var refreshTokenValidity = uaaProperties.webClientConfiguration.refreshTokenValidityInSecondsForRememberMe - refreshTokenValidity = Math.max(refreshTokenValidity, accessTokenValidity) - /* - For a better client design, this should be done by a ClientDetailsService (similar to UserDetailsService). - */ - clients!!.inMemory() - .withClient(uaaProperties.webClientConfiguration.clientId) - .secret(passwordEncoder.encode(uaaProperties.webClientConfiguration.secret)) - .scopes("openid") - .autoApprove(true) - .authorizedGrantTypes("implicit", "refresh_token", "password", "authorization_code") - .accessTokenValiditySeconds(accessTokenValidity) - .refreshTokenValiditySeconds(refreshTokenValidity) - .and() - .withClient(jHipsterProperties.security.clientAuthorization.clientId) - .secret(passwordEncoder.encode(jHipsterProperties.security.clientAuthorization.clientSecret)) - .scopes("web-app") - .authorities("ROLE_ADMIN") - .autoApprove(true) - .authorizedGrantTypes("client_credentials") - .accessTokenValiditySeconds(jHipsterProperties.security.authentication.jwt.tokenValidityInSeconds.toInt()) - .refreshTokenValiditySeconds(jHipsterProperties.security.authentication.jwt.tokenValidityInSecondsForRememberMe.toInt()) - } - - @Throws(Exception::class) - override fun configure(endpoints: AuthorizationServerEndpointsConfigurer?) { - // pick up all TokenEnhancers incl. those defined in the application - // this avoids changes to this class if an application wants to add its own to the chain - val tokenEnhancers = applicationContext!!.getBeansOfType(TokenEnhancer::class.java).values - val tokenEnhancerChain = TokenEnhancerChain() - tokenEnhancerChain.setTokenEnhancers(tokenEnhancers.toMutableList()) - endpoints!! - .authenticationManager(authenticationManager) - .tokenStore(tokenStore()) - .tokenEnhancer(tokenEnhancerChain) - .reuseRefreshTokens(false) // don't reuse or we will run into session inactivity timeouts - } - - /** - * Apply the token converter (and enhancer) for token store. - * @return the [JwtTokenStore] managing the tokens. - */ - @Bean - fun tokenStore() = JwtTokenStore(jwtAccessTokenConverter()) - - /** - * This bean generates an token enhancer, which manages the exchange between JWT access tokens and Authentication - * in both directions. - * - * @return an access token converter configured with the authorization server's public/private keys. - */ - @Bean - fun jwtAccessTokenConverter(): JwtAccessTokenConverter { - val converter = JwtAccessTokenConverter() - val keyPair = KeyStoreKeyFactory( - ClassPathResource(uaaProperties.keyStore.name), - uaaProperties.keyStore.password.toCharArray() - ).getKeyPair(uaaProperties.keyStore.alias) - - converter.setKeyPair(keyPair) - return converter - } - - @Throws(Exception::class) - override fun configure(oauthServer: AuthorizationServerSecurityConfigurer?) { - oauthServer!!.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()") - } -} diff --git a/generators/server/templates/src/main/kotlin/package/config/UaaProperties.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/UaaProperties.kt.ejs deleted file mode 100644 index 908cf139c..000000000 --- a/generators/server/templates/src/main/kotlin/package/config/UaaProperties.kt.ejs +++ /dev/null @@ -1,54 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.config - -import org.springframework.boot.context.properties.ConfigurationProperties -import org.springframework.stereotype.Component - -/** - * Properties for UAA-based OAuth2 security. - */ -@Component -@ConfigurationProperties(prefix = "uaa", ignoreUnknownFields = false) -class UaaProperties { - val keyStore = KeyStore() - - val webClientConfiguration = WebClientConfiguration() - - /** - * Keystore configuration for signing and verifying JWT tokens. - */ - class KeyStore { - //name of the keystore in the classpath - var name = "config/tls/keystore.p12" - //password used to access the key - var password = "password" - //name of the alias to fetch - var alias = "selfsigned" - } - - class WebClientConfiguration { - //validity of the short-lived access token in secs (min: 60), don't make it too long - var accessTokenValidityInSeconds = 5 * 60 - //validity of the refresh token in secs (defines the duration of "remember me") - var refreshTokenValidityInSecondsForRememberMe = 7 * 24 * 60 * 60 - var clientId = "web_app" - var secret = "changeit" - } -} diff --git a/generators/server/templates/src/main/kotlin/package/config/UaaWebSecurityConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/UaaWebSecurityConfiguration.kt.ejs deleted file mode 100644 index 7daa5f94d..000000000 --- a/generators/server/templates/src/main/kotlin/package/config/UaaWebSecurityConfiguration.kt.ejs +++ /dev/null @@ -1,74 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.config - -import org.springframework.beans.factory.BeanInitializationException -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.http.HttpMethod -import org.springframework.security.authentication.AuthenticationManager -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder -import org.springframework.security.config.annotation.web.builders.WebSecurity -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter -import org.springframework.security.core.userdetails.UserDetailsService -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder -import org.springframework.security.data.repository.query.SecurityEvaluationContextExtension - -import javax.annotation.PostConstruct - -@Configuration -class UaaWebSecurityConfiguration( - private val userDetailsService: UserDetailsService, - private val authenticationManagerBuilder: AuthenticationManagerBuilder -) : WebSecurityConfigurerAdapter() { - - @PostConstruct - @Throws(Exception::class) - fun init() { - try { - authenticationManagerBuilder - .userDetailsService(userDetailsService) - .passwordEncoder(passwordEncoder()) - } catch (e: Exception) { - throw BeanInitializationException("Security configuration failed", e) - } - } - - @Bean - fun passwordEncoder() = BCryptPasswordEncoder() - - @Bean - @Throws(Exception::class) - override fun authenticationManagerBean(): AuthenticationManager = super.authenticationManagerBean() - - @Throws(Exception::class) - override fun configure(web: WebSecurity?) { - web!!.ignoring() - .antMatchers(HttpMethod.OPTIONS, "/**") - .antMatchers("/app/**/*.{js,html}") - .antMatchers("/i18n/**") - .antMatchers("/content/**") - .antMatchers("/swagger-ui/index.html") - .antMatchers("/test/**") - .antMatchers("/h2-console/**") - } - - @Bean - fun securityEvaluationContextExtension() = SecurityEvaluationContextExtension() -} diff --git a/generators/server/templates/src/main/kotlin/package/config/WebConfigurer.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/WebConfigurer.kt.ejs index 3a39f48c5..418ff6cca 100644 --- a/generators/server/templates/src/main/kotlin/package/config/WebConfigurer.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/config/WebConfigurer.kt.ejs @@ -21,15 +21,15 @@ package <%= packageName %>.config <%_ if (reactive) { _%> import com.fasterxml.jackson.databind.ObjectMapper <%_ } _%> -<%_ if (!skipClient || ['h2Disk', 'h2Memory'].includes(devDatabaseType) && !reactive) { _%> -import io.github.jhipster.config.JHipsterConstants +<%_ if (!skipClient || ['h2Disk', 'h2Memory'].includes(devDatabaseType)) { _%> +import tech.jhipster.config.JHipsterConstants <%_ } _%> -import io.github.jhipster.config.JHipsterProperties -<%_ if (['h2Disk', 'h2Memory'].includes(devDatabaseType) && !reactive) { _%> -import io.github.jhipster.config.h2.H2ConfigurationHelper +import tech.jhipster.config.JHipsterProperties +<%_ if (['h2Disk', 'h2Memory'].includes(devDatabaseType)) { _%> +import tech.jhipster.config.h2.H2ConfigurationHelper <%_ } _%> <%_ if (!skipClient && reactive) { _%> -import io.github.jhipster.web.filter.<% if (reactive) { %>reactive.<% } %>CachingHttpHeadersFilter +import tech.jhipster.web.filter.<% if (reactive) { %>reactive.<% } %>CachingHttpHeadersFilter <%_ } _%> import org.slf4j.LoggerFactory <%_ if (!reactive) { _%> @@ -54,17 +54,15 @@ import org.springframework.core.annotation.Order import org.springframework.data.web.ReactivePageableHandlerMethodArgumentResolver import org.springframework.data.web.ReactiveSortHandlerMethodArgumentResolver <%_ } _%> -<%_ if (!reactive) { _%> +<%_ if (!reactive || (['h2Disk', 'h2Memory'].includes(devDatabaseType) && reactive)) { _%> import org.springframework.core.env.Environment import org.springframework.core.env.Profiles - <%_ if (!skipClient) { _%> -import org.springframework.http.MediaType - <%_ } _%> <%_ } _%> <%_ if (reactive && !skipClient) { _%> import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers <%_ } _%> +import org.springframework.util.CollectionUtils <%_ if (!reactive) { _%> import org.springframework.web.cors.UrlBasedCorsConfigurationSource import org.springframework.web.filter.CorsFilter @@ -72,9 +70,6 @@ import org.springframework.web.filter.CorsFilter <%_ if (reactive) { _%> import org.springframework.web.cors.reactive.CorsWebFilter import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource - <%_ if (!skipClient && ['monolith','gateway'].includes(applicationType)) { _%> -import org.springframework.web.reactive.config.ResourceHandlerRegistry - <%_ } _%> import org.springframework.web.reactive.config.WebFluxConfigurer <%_ if (!skipClient) { _%> import org.springframework.web.reactive.function.server.HandlerFunction @@ -119,12 +114,20 @@ import java.util.concurrent.TimeUnit */ @Configuration class WebConfigurer( - <%_ if (!reactive) { _%> + <% if (!reactive || (['h2Disk', 'h2Memory'].includes(devDatabaseType) && reactive)) { %> private val env: Environment, <%_ } _%> private val jHipsterProperties: JHipsterProperties ) : <% if (!reactive) { %>ServletContextInitializer<% if (!skipClient) { %>, WebServerFactoryCustomizer<% } %><% } %><% if (reactive) { %>WebFluxConfigurer<% } %> { + <%_ if (['h2Disk', 'h2Memory'].includes(devDatabaseType) && reactive) { _%> + init { + if (env.acceptsProfiles(Profiles.of(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT))) { + H2ConfigurationHelper.initH2Console() + } + } + <%_ } _%> + private val log = LoggerFactory.getLogger(javaClass) <%_ if (!reactive) { _%> @@ -147,22 +150,10 @@ class WebConfigurer( * Customize the Servlet engine: Mime types, the document root, the cache. */ override fun customize(server: WebServerFactory) { - setMimeMappings(server) // When running in an IDE or with <% if (buildTool === 'gradle') { %>./gradlew bootRun<% } else { %>./mvnw spring-boot:run<% } %>, set location of the static web assets. setLocationForStaticAssets(server) } - private fun setMimeMappings(server: WebServerFactory) { - if (server is ConfigurableServletWebServerFactory) { - val mappings = MimeMappings(MimeMappings.DEFAULT) - // IE issue, see https://github.com/jhipster/generator-jhipster/pull/711 - mappings.add("html", "${MediaType.TEXT_HTML_VALUE};charset=${StandardCharsets.UTF_8.name().toLowerCase()}") - // CloudFoundry issue, see https://github.com/cloudfoundry/gorouter/issues/64 - mappings.add("json", "${MediaType.TEXT_HTML_VALUE};charset=${StandardCharsets.UTF_8.name().toLowerCase()}") - server.setMimeMappings(mappings) - } - } - private fun setLocationForStaticAssets(server: WebServerFactory) { if (server is ConfigurableServletWebServerFactory) { val prefixPath = resolvePathPrefix() @@ -200,22 +191,19 @@ class WebConfigurer( fun corsFilter(): Cors<% if (reactive) { %>Web<% } %>Filter { val source = UrlBasedCorsConfigurationSource() val config = jHipsterProperties.cors - if (config.allowedOrigins != null && config.allowedOrigins!!.isNotEmpty()) { + if (!CollectionUtils.isEmpty(config.allowedOrigins)) { log.debug("Registering CORS filter") source.apply { registerCorsConfiguration("/api/**", config) registerCorsConfiguration("/management/**", config) registerCorsConfiguration("/v2/api-docs", config) - <%_ if (applicationType === 'gateway' && authenticationType === 'uaa') { _%> - registerCorsConfiguration("/auth/**", config) - <%_ } _%> + registerCorsConfiguration("/v3/api-docs", config) + registerCorsConfiguration("/swagger-resources", config) + registerCorsConfiguration("/swagger-ui/**", config) <%_ if (applicationType === 'gateway') { _%> registerCorsConfiguration("/*/api/**", config) registerCorsConfiguration("/services/*/api/**", config) registerCorsConfiguration("/*/management/**", config) - <%_ if (authenticationType === 'uaa') { _%> - registerCorsConfiguration("/*/oauth/**", config) - <%_ } _%> <%_ } _%> } } @@ -250,16 +238,6 @@ class WebConfigurer( // Use a cache filter that only match selected paths return CachingHttpHeadersFilter(TimeUnit.DAYS.toMillis(jHipsterProperties.http.cache.timeToLiveInDays.toLong())) } - <%_ if (applicationType === 'monolith' || applicationType === 'gateway') { _%> - - override fun addResourceHandlers(registry: ResourceHandlerRegistry) { - registry.addResourceHandler("/swagger-ui.html**") - .addResourceLocations("classpath:/META-INF/resources/") - - registry.addResourceHandler("/webjars/**") - .addResourceLocations("classpath:/META-INF/resources/webjars/") - } - <%_ } _%> <%_ } _%> <%_ } _%> <%_ if (['h2Disk', 'h2Memory'].includes(devDatabaseType) && !reactive) { _%> diff --git a/generators/server/templates/src/main/kotlin/package/config/WebsocketConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/WebsocketConfiguration.kt.ejs index 87c7ee9fd..2d7446f0b 100644 --- a/generators/server/templates/src/main/kotlin/package/config/WebsocketConfiguration.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/config/WebsocketConfiguration.kt.ejs @@ -20,7 +20,7 @@ package <%= packageName %>.config import <%= packageName %>.security.ANONYMOUS -import io.github.jhipster.config.JHipsterProperties +import tech.jhipster.config.JHipsterProperties import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration diff --git a/generators/server/templates/src/main/kotlin/package/config/apidoc/GatewaySwaggerResourcesProvider.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/apidoc/GatewaySwaggerResourcesProvider.kt.ejs deleted file mode 100644 index 4da46e0fd..000000000 --- a/generators/server/templates/src/main/kotlin/package/config/apidoc/GatewaySwaggerResourcesProvider.kt.ejs +++ /dev/null @@ -1,59 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.config.apidoc - -import io.github.jhipster.config.JHipsterConstants - -import org.springframework.context.annotation.Primary -import org.springframework.context.annotation.Profile -import org.springframework.cloud.netflix.zuul.filters.RouteLocator -import org.springframework.stereotype.Component - -import springfox.documentation.swagger.web.SwaggerResource -import springfox.documentation.swagger.web.SwaggerResourcesProvider - -/** - * Retrieves all registered microservices Swagger resources. - */ -@Component -@Primary -@Profile(JHipsterConstants.SPRING_PROFILE_SWAGGER) -class GatewaySwaggerResourcesProvider(private val routeLocator: RouteLocator) : SwaggerResourcesProvider { - - override fun get(): MutableList { - val resources = mutableListOf( - // Add the default swagger resource that correspond to the gateway's own swagger doc - swaggerResource("default", "/v2/api-docs") - ) - - // Add the registered microservices swagger docs as additional swagger resources - routeLocator.routes.forEach { - resources.add(swaggerResource(it.id, it.fullPath.replace("**", "v2/api-docs"))) - } - - return resources - } - - private fun swaggerResource(name: String, location: String) = - SwaggerResource().apply { - this.name = name - this.location = location - swaggerVersion = "2.0" - } -} diff --git a/generators/server/templates/src/main/kotlin/package/config/apidoc/SwaggerConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/apidoc/SwaggerConfiguration.kt.ejs deleted file mode 100644 index 4813e2e3a..000000000 --- a/generators/server/templates/src/main/kotlin/package/config/apidoc/SwaggerConfiguration.kt.ejs +++ /dev/null @@ -1,44 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.config.apidoc - -import io.github.jhipster.config.JHipsterConstants -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.context.annotation.Primary -import org.springframework.context.annotation.Profile -import springfox.documentation.builders.PathSelectors -import springfox.documentation.builders.RequestHandlerSelectors -import springfox.documentation.spi.DocumentationType -import springfox.documentation.spring.web.plugins.Docket -import springfox.documentation.swagger2.annotations.EnableSwagger2WebFlux - -@Primary -@Profile(JHipsterConstants.SPRING_PROFILE_SWAGGER) -@Configuration -@EnableSwagger2WebFlux -class SwaggerConfiguration { - - @Bean - fun api() = Docket(DocumentationType.SWAGGER_2) - .select() - .apis(RequestHandlerSelectors.any()) - .paths(PathSelectors.any()) - .build() -} diff --git a/generators/server/templates/src/main/kotlin/package/config/apidocs/GatewaySwaggerResourcesProvider.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/apidocs/GatewaySwaggerResourcesProvider.kt.ejs new file mode 100644 index 000000000..92ac26c3c --- /dev/null +++ b/generators/server/templates/src/main/kotlin/package/config/apidocs/GatewaySwaggerResourcesProvider.kt.ejs @@ -0,0 +1,99 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + + This file is part of the JHipster project, see https://www.jhipster.tech/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %>.config.apidocs + +import java.util.* +import java.util.concurrent.TimeUnit +import org.springframework.beans.factory.annotation.Qualifier +import org.springframework.beans.factory.annotation.Value +import org.springframework.cloud.gateway.route.Route +import org.springframework.cloud.gateway.route.RouteLocator +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Primary +import org.springframework.context.annotation.Profile +import org.springframework.stereotype.Component +import reactor.core.scheduler.Schedulers +import springfox.documentation.swagger.web.SwaggerResource +import springfox.documentation.swagger.web.SwaggerResourcesProvider +import tech.jhipster.config.JHipsterConstants + +/** + * Retrieves all registered microservices Swagger resources. + */ +@Component +@Primary +@Profile(JHipsterConstants.SPRING_PROFILE_API_DOCS) +@Configuration +class GatewaySwaggerResourcesProvider( + private val routeLocator: RouteLocator, + @Qualifier("SwaggerResources") private val swaggerResourcesProvider: SwaggerResourcesProvider +) : SwaggerResourcesProvider { + + @Value("\${eureka.instance.appname:<%= baseName.toLowerCase() %>}") + private var gatewayName: String? = null + + override fun get(): MutableList { + val swaggerResources = mutableListOf( + // Add the default swagger resource that correspond to the gateway's own swagger doc + swaggerResource(gatewayName.plus(" (default)"), "/v3/api-docs"), + swaggerResource(gatewayName.plus(" (management)"), "/v3/api-docs?group=management") + ) + + val microservices = routeLocator.routes.map { getMicroservicesName(it) } + .collectList() + .defaultIfEmpty(listOf()) + .subscribeOn(Schedulers.boundedElastic()) + .toFuture() + .orTimeout(10, TimeUnit.SECONDS) + .join() + + microservices + .filter { isNotGateway(it) } + <%_ if (serviceDiscoveryType === 'consul') { _%> + .filter { isNotConsul(it) } + <%_ } _%> + .forEach { swaggerResources.add(swaggerResource(it, getMicroserviceApiDocs(it))) } + + return swaggerResources + } + + companion object { + fun swaggerResource(name: String, location: String) = + SwaggerResource().apply { + this.name = name + this.location = location + swaggerVersion = "3.0" + } + } + + private fun isNotGateway(name: String) = !name.equals(gatewayName, ignoreCase = true) + + <%_ if (serviceDiscoveryType === 'consul') { _%> + private fun isNotConsul(name: String) = !name.equals("consul", ignoreCase = true) + + <%_ } _%> + + private fun getMicroserviceApiDocs(name: String): String { + return "/services/$name/v3/api-docs" + } + + private fun getMicroservicesName(route: Route): String { + return route.uri.toString().replace("lb://", "").toLowerCase() + } +} diff --git a/generators/server/templates/src/main/kotlin/package/config/audit/AuditEventConverter.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/audit/AuditEventConverter.kt.ejs deleted file mode 100644 index c1bd7115f..000000000 --- a/generators/server/templates/src/main/kotlin/package/config/audit/AuditEventConverter.kt.ejs +++ /dev/null @@ -1,86 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.config.audit - -import <%= packageName %>.domain.PersistentAuditEvent - -import org.springframework.boot.actuate.audit.AuditEvent -import org.springframework.security.web.authentication.WebAuthenticationDetails -import org.springframework.stereotype.Component - -@Component -class AuditEventConverter { - - /** - * Convert a list of [PersistentAuditEvent] to a list of [AuditEvent]. - * - * @param persistentAuditEvents the list to convert. - * @return the converted list. - */ - fun convertToAuditEvent(persistentAuditEvents: Iterable?) = - when (persistentAuditEvents) { - null -> mutableListOf() - else -> persistentAuditEvents.asSequence().mapNotNull { convertToAuditEvent(it) }.toMutableList() - } - - /** - * Convert a [PersistentAuditEvent] to an [AuditEvent]. - * - * @param persistentAuditEvent the event to convert. - * @return the converted list. - */ - fun convertToAuditEvent(persistentAuditEvent: PersistentAuditEvent?): AuditEvent? = - when (persistentAuditEvent) { - null -> null - else -> AuditEvent( - persistentAuditEvent.auditEventDate, persistentAuditEvent.principal, - persistentAuditEvent.auditEventType, convertDataToObjects(persistentAuditEvent.data) - ) - } - - /** - * Internal conversion. This is needed to support the current SpringBoot actuator[ AuditEventRepository] interface. - * - * @param data the data to convert. - * @return a map of [String], [Any]. - */ - fun convertDataToObjects(data: MutableMap?): MutableMap = - data?.mapValuesTo(mutableMapOf()) { it.value } ?: mutableMapOf() - - /** - * Internal conversion. This method will allow to save additional data. - * By default, it will save the object as string. - * - * @param data the data to convert. - * @return a map of [String], [String]. - */ - fun convertDataToStrings(data: Map?): Map { - val results = mutableMapOf() - data?.forEach { (key, value) -> - // Extract the data that will be saved. - if (value is WebAuthenticationDetails) { - results["remoteAddress"] = value.remoteAddress - results["sessionId"] = value.sessionId - } else { - results[key] = value?.toString() - } - } - return results - } -} diff --git a/generators/server/templates/src/main/kotlin/package/config/cassandra/CassandraConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/cassandra/CassandraConfiguration.kt.ejs deleted file mode 100644 index 2a7ecc50f..000000000 --- a/generators/server/templates/src/main/kotlin/package/config/cassandra/CassandraConfiguration.kt.ejs +++ /dev/null @@ -1,141 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.config.cassandra - -import com.codahale.metrics.MetricRegistry -import com.datastax.driver.core.Cluster -import com.datastax.driver.core.CodecRegistry -import com.datastax.driver.core.DataType -import com.datastax.driver.core.ProtocolVersion -import com.datastax.driver.core.Session -import com.datastax.driver.core.TupleType -import com.datastax.driver.core.TupleValue -import com.datastax.driver.extras.codecs.jdk8.InstantCodec -import com.datastax.driver.extras.codecs.jdk8.LocalDateCodec -import com.datastax.driver.extras.codecs.jdk8.ZonedDateTimeCodec -import io.github.jhipster.config.JHipsterConstants -import org.slf4j.LoggerFactory -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.beans.factory.annotation.Value -import org.springframework.boot.autoconfigure.cassandra.CassandraProperties -import org.springframework.boot.autoconfigure.cassandra.ClusterBuilderCustomizer -<%_ if (applicationType === 'gateway' && databaseType !== 'cassandra') { _%> -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty -<%_ } _%> -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.context.annotation.Profile -import org.springframework.core.convert.converter.Converter -import org.springframework.data.cassandra.core.convert.CassandraCustomConversions -import org.springframework.data.convert.ReadingConverter -import org.springframework.data.convert.WritingConverter - -import javax.annotation.PostConstruct -import java.time.ZoneId -import java.time.ZoneOffset -import java.time.ZonedDateTime -import java.util.Date - -@Configuration<% if (applicationType === 'gateway' && databaseType !== 'cassandra') { %> -@ConditionalOnProperty("jhipster.gateway.rate-limiting.enabled")<% } %> -@Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT, JHipsterConstants.SPRING_PROFILE_PRODUCTION) -class CassandraConfiguration { - - @Value("\${spring.data.cassandra.protocolVersion:V4}") - private lateinit var protocolVersion: ProtocolVersion - - @Autowired(required = false) - internal var metricRegistry: MetricRegistry? = null - - private val log = LoggerFactory.getLogger(javaClass) - - @Autowired - private lateinit var cluster: Cluster - - @PostConstruct - fun postConstruct() { - val tupleType = cluster.metadata.newTupleType(DataType.timestamp(), DataType.varchar()) - - cluster.configuration.codecRegistry - .register(LocalDateCodec.instance) - .register(InstantCodec.instance) - .register(ZonedDateTimeCodec(tupleType)) - - cluster.init() - } - - @Bean - fun cassandraCustomConversions(cluster: Cluster): CassandraCustomConversions { - val converters = mutableListOf>( - TupleToZonedDateTimeConverter, - ZonedDateTimeToTupleConverter(protocolVersion, cluster.configuration.codecRegistry) - ) - return CassandraCustomConversions(converters) - } - - @ReadingConverter - internal object TupleToZonedDateTimeConverter : Converter { - override fun convert(source: TupleValue): ZonedDateTime { - val timestamp = source.getTimestamp(0) - val zoneId = ZoneId.of(source.getString(1)) - return timestamp.toInstant().atZone(zoneId) - } - } - - @WritingConverter - internal object ZonedDateTimeToTupleConverter : Converter { - - private lateinit var type: TupleType - - override fun convert(source: ZonedDateTime): TupleValue? = - type.newValue().apply { - setTimestamp(0, Date.from(source.toLocalDateTime().toInstant(ZoneOffset.UTC))) - setString(1, source.zone.toString()) - } - - internal operator fun invoke( - version: ProtocolVersion, - codecRegistry: CodecRegistry? - ): ZonedDateTimeToTupleConverter { - type = TupleType.of(version, codecRegistry, DataType.timestamp(), DataType.text()) - return this - } - } - - @Bean - internal fun clusterBuilderCustomizer(properties: CassandraProperties) = - ClusterBuilderCustomizer { - it - .withProtocolVersion(protocolVersion) - .withPort(getPort(properties)) - .withoutJMXReporting() - .withoutMetrics() - } - - protected fun getPort(properties: CassandraProperties) = properties.port - - @Bean(destroyMethod = "close") - fun session(properties: CassandraProperties, cluster: Cluster): Session { - log.debug("Configuring Cassandra session") - return when { - properties.keyspaceName.isNullOrBlank() -> cluster.connect() - else -> cluster.connect(properties.keyspaceName) - } - } -} diff --git a/generators/server/templates/src/main/kotlin/package/config/dbmigrations/InitialSetupMigration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/dbmigrations/InitialSetupMigration.kt.ejs index 295209b93..1660039d0 100644 --- a/generators/server/templates/src/main/kotlin/package/config/dbmigrations/InitialSetupMigration.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/config/dbmigrations/InitialSetupMigration.kt.ejs @@ -22,10 +22,11 @@ import <%= packageName %>.domain.Authority import <%= packageName %>.domain.<%= asEntity('User') %> import <%= packageName %>.security.ADMIN import <%= packageName %>.security.USER +import <%= packageName %>.config.SYSTEM_ACCOUNT -import com.github.mongobee.changeset.ChangeLog -import com.github.mongobee.changeset.ChangeSet -import org.springframework.data.mongodb.core.MongoTemplate +import com.github.cloudyrock.mongock.ChangeLog +import com.github.cloudyrock.mongock.ChangeSet +import com.github.cloudyrock.mongock.driver.mongodb.springdata.v3.decorator.impl.MongockTemplate import java.time.Instant @@ -37,7 +38,7 @@ import java.time.Instant class InitialSetupMigration { @ChangeSet(order = "01", author = "initiator", id = "01-addAuthorities") - fun addAuthorities(mongoTemplate: MongoTemplate) { + fun addAuthorities(mongoTemplate: MongockTemplate) { val adminAuthority = Authority(ADMIN) val userAuthority = Authority(USER) @@ -47,45 +48,12 @@ class InitialSetupMigration { <%_ if (authenticationType !== 'oauth2') { _%> @ChangeSet(order = "02", author = "initiator", id = "02-addUsers") - fun addUsers(mongoTemplate: MongoTemplate) { + fun addUsers(mongoTemplate: MongockTemplate) { val adminAuthority = Authority(ADMIN) val userAuthority = Authority(USER) - val systemUser = <%= asEntity('User') %>( - id = "user-0", - login = "system", - <%_ if (authenticationType !== 'oauth2') { _%> - password = "\$2a\$10\$mE.qmcV0mFU5NcKh73TZx.z4ueI/.bDWbj0T1BYyqP481kGGarKLG", - <%_ } _%> - firstName = "", - lastName = "System", - email = "system@localhost", - activated = true, - langKey = "en", - createdBy = "system", - createdDate = Instant.now(), - authorities = mutableSetOf(adminAuthority, userAuthority) - ) - mongoTemplate.save(systemUser) - - val anonymousUser = <%= asEntity('User') %>( - id = "user-1", - login = "anonymoususer", - <%_ if (authenticationType !== 'oauth2') { _%> - password = "\$2a\$10\$j8S5d7Sr7.8VTOYNviDPOeWX8KcYILUVJBsYV83Y5NtECayypx9lO", - <%_ } _%> - firstName = "Anonymous", - lastName = "User", - email = "anonymous@localhost", - activated = true, - langKey = "en", - createdBy = systemUser.login, - createdDate = Instant.now() - ) - mongoTemplate.save(anonymousUser) - val adminUser = <%= asEntity('User') %>( - id = "user-2", + id = "user-1", login = "admin", <%_ if (authenticationType !== 'oauth2') { _%> password = "\$2a\$10\$gSAhZrxMllrbgj/kkK9UceBPpChGWJA7SYIb1Mqo.n5aNLq1/oRrC", @@ -95,14 +63,14 @@ class InitialSetupMigration { email = "admin@localhost", activated = true, langKey = "en", - createdBy = systemUser.login, + createdBy = SYSTEM_ACCOUNT, createdDate = Instant.now(), authorities = mutableSetOf(adminAuthority, userAuthority) ) mongoTemplate.save(adminUser) val userUser = <%= asEntity('User') %>( - id = "user-3", + id = "user-2", login = "user", <%_ if (authenticationType !== 'oauth2') { _%> password = "\$2a\$10\$VEjxo0jq2YG9Rbk2HmX9S.k1uZBGYUHdUcid3g/vfiEl7lwWgOH/K", @@ -112,7 +80,7 @@ class InitialSetupMigration { email = "user@localhost", activated = true, langKey = "en", - createdBy = systemUser.login, + createdBy = SYSTEM_ACCOUNT, createdDate = Instant.now(), authorities = mutableSetOf(userAuthority) ) diff --git a/generators/server/templates/src/main/kotlin/package/config/metrics/CassandraHealthIndicator.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/metrics/CassandraHealthIndicator.kt.ejs deleted file mode 100644 index f214ea78f..000000000 --- a/generators/server/templates/src/main/kotlin/package/config/metrics/CassandraHealthIndicator.kt.ejs +++ /dev/null @@ -1,54 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.config.metrics - -import com.datastax.driver.core.Session -import org.apache.commons.logging.LogFactory -import org.springframework.boot.actuate.health.AbstractHealthIndicator -import org.springframework.boot.actuate.health.Health - -/** - * Simple implementation of a [org.springframework.boot.actuate.health.HealthIndicator] returning status information for - * Cassandra data stores. - */ -class CassandraHealthIndicator(private val session: Session) : AbstractHealthIndicator() { - - private val validationStmt = session.prepare("SELECT release_version FROM system.local") - - @Throws(Exception::class) - override fun doHealthCheck(builder: Health.Builder) { - log.debug("Initializing Cassandra health indicator") - try { - val results = session.execute(validationStmt.bind()) - if (results.isExhausted) { - builder.up() - } else { - builder.up().withDetail("version", results.one().getString(0)) - } - } catch (e: Exception) { - log.debug("Cannot connect to Cassandra cluster. Error: $e") - builder.down(e) - } - } - - companion object { - - private val log = LogFactory.getLog(CassandraHealthIndicator::class.java) - } -} diff --git a/generators/server/templates/src/main/kotlin/package/config/oauth2/OAuth2AuthenticationConfiguration.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/oauth2/OAuth2AuthenticationConfiguration.kt.ejs deleted file mode 100644 index 63867ccfa..000000000 --- a/generators/server/templates/src/main/kotlin/package/config/oauth2/OAuth2AuthenticationConfiguration.kt.ejs +++ /dev/null @@ -1,85 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.config.oauth2 - -import <%= packageName %>.security.oauth2.CookieTokenExtractor -import <%= packageName %>.security.oauth2.OAuth2AuthenticationService -import <%= packageName %>.security.oauth2.OAuth2CookieHelper -import <%= packageName %>.security.oauth2.OAuth2TokenEndpointClient -import <%= packageName %>.web.filter.RefreshTokenFilterConfigurer -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity -import org.springframework.security.config.annotation.web.builders.HttpSecurity -import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer -import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter -import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer -import org.springframework.security.oauth2.provider.authentication.TokenExtractor -import org.springframework.security.oauth2.provider.token.TokenStore - -/** - * Configures the RefreshFilter refreshing expired OAuth2 token Cookies. - */ -@Configuration -@EnableResourceServer -@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) -class OAuth2AuthenticationConfiguration( - private val oAuth2Properties: OAuth2Properties, - private val tokenEndpointClient: OAuth2TokenEndpointClient, - private val tokenStore: TokenStore -) : ResourceServerConfigurerAdapter() { - - @Throws(Exception::class) - override fun configure(http: HttpSecurity) { - http - .authorizeRequests() - .antMatchers("/auth/login").permitAll() - .antMatchers("/auth/logout").authenticated() - .and() - .apply(refreshTokenSecurityConfigurerAdapter()) - } - - /** - * A `SecurityConfigurerAdapter` to install a servlet filter that refreshes OAuth2 tokens. - */ - private fun refreshTokenSecurityConfigurerAdapter() = - RefreshTokenFilterConfigurer(uaaAuthenticationService(), tokenStore) - - @Bean - fun cookieHelper() = OAuth2CookieHelper(oAuth2Properties) - - @Bean - fun uaaAuthenticationService() = OAuth2AuthenticationService(tokenEndpointClient, cookieHelper()) - - /** - * Configure the ResourceServer security by installing a new [TokenExtractor]. - */ - @Throws(Exception::class) - override fun configure(resources: ResourceServerSecurityConfigurer) { - resources.tokenExtractor(tokenExtractor()) - } - - /** - * The new [TokenExtractor] can extract tokens from Cookies and Authorization headers. - * - * @return the [CookieTokenExtractor] bean. - */ - @Bean - fun tokenExtractor() = CookieTokenExtractor() -} diff --git a/generators/server/templates/src/main/kotlin/package/config/oauth2/OAuth2JwtAccessTokenConverter.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/oauth2/OAuth2JwtAccessTokenConverter.kt.ejs deleted file mode 100644 index 316e4d675..000000000 --- a/generators/server/templates/src/main/kotlin/package/config/oauth2/OAuth2JwtAccessTokenConverter.kt.ejs +++ /dev/null @@ -1,117 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.config.oauth2 - -import <%= packageName %>.security.oauth2.OAuth2SignatureVerifierClient -import org.slf4j.LoggerFactory -import org.springframework.security.oauth2.common.exceptions.InvalidTokenException -import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter -import org.springframework.security.oauth2.provider.OAuth2Authentication - -/** - * Improved [JwtAccessTokenConverter] that can handle lazy fetching of public verifier keys. - */ -class OAuth2JwtAccessTokenConverter( - private val oAuth2Properties: OAuth2Properties, - private val signatureVerifierClient: OAuth2SignatureVerifierClient -) : JwtAccessTokenConverter() { - - private val log = LoggerFactory.getLogger(javaClass) - - /** - * When did we last fetch the public key? - */ - private var lastKeyFetchTimestamp: Long = 0 - - init { - tryCreateSignatureVerifier() - } - - /** - * Try to decode the token with the current public key. - * If it fails, contact the OAuth2 server to get a new public key, then try again. - * We might not have fetched it in the first place or it might have changed. - * - * @param token the JWT token to decode. - * @return the resulting claims. - * @throws InvalidTokenException if we cannot decode the token. - */ - override fun decode(token: String): Map { - try { - // check if our public key and thus SignatureVerifier have expired - val ttl = oAuth2Properties.signatureVerification.ttl - if (ttl != null && ttl > 0 && System.currentTimeMillis() - lastKeyFetchTimestamp > ttl) { - throw InvalidTokenException("public key expired") - } - return super.decode(token) - } catch (ex: InvalidTokenException) { - if (tryCreateSignatureVerifier()) { - return super.decode(token) - } - throw ex - } - } - - /** - * Fetch a new public key from the AuthorizationServer. - * - * @return true, if we could fetch it; false, if we could not. - */ - private fun tryCreateSignatureVerifier(): Boolean { - val time = System.currentTimeMillis() - if (time - lastKeyFetchTimestamp < oAuth2Properties.signatureVerification.publicKeyRefreshRateLimit ?: 0) { - return false - } - try { - val verifier = signatureVerifierClient.getSignatureVerifier() - if (verifier != null) { - setVerifier(verifier) - lastKeyFetchTimestamp = time - log.debug("Public key retrieved from OAuth2 server to create SignatureVerifier") - return true - } - } catch (ex: Throwable) { - log.error("could not get public key from OAuth2 server to create SignatureVerifier $ex") - } - return false - } - - /** - * Extract JWT claims and set it to OAuth2Authentication decoded details. - * Here is how to get details: - * - * ``` - * val securityContext = SecurityContextHolder.getContext() - * val authentication = securityContext.authentication - * if (authentication != null) { - * val details = authentication.details - * if (details is OAuth2AuthenticationDetails) { - * val decodedDetails = details.decodedDetails - * if (decodedDetails is Map<*, *>) { - * val detailFoo = decodedDetails["foo"] as String? - * } - * } - * } - * ``` - * @param claims OAuth2JWTToken claims. - * @return [OAuth2Authentication]. - */ - override fun extractAuthentication(claims: Map): OAuth2Authentication = - super.extractAuthentication(claims).apply { details = claims } -} diff --git a/generators/server/templates/src/main/kotlin/package/config/oauth2/OAuth2Properties.kt.ejs b/generators/server/templates/src/main/kotlin/package/config/oauth2/OAuth2Properties.kt.ejs deleted file mode 100644 index b14a31c09..000000000 --- a/generators/server/templates/src/main/kotlin/package/config/oauth2/OAuth2Properties.kt.ejs +++ /dev/null @@ -1,72 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.config.oauth2 - -import org.springframework.boot.context.properties.ConfigurationProperties -import org.springframework.stereotype.Component - -/** - * OAuth2 properties define properties for OAuth2-based microservices. - */ -@Component -@ConfigurationProperties(prefix = "oauth2", ignoreUnknownFields = false) -class OAuth2Properties { - val webClientConfiguration = WebClientConfiguration() - - val signatureVerification = SignatureVerification() - - class WebClientConfiguration { - var clientId: String? = "web_app" - var secret: String? = "changeit" - /** - * Holds the session timeout in seconds for non-remember-me sessions. - * After so many seconds of inactivity, the session will be terminated. - * Only checked during token refresh, so long access token validity may - * delay the session timeout accordingly. - */ - var sessionTimeoutInSeconds: Int? = 1800 - /** - * Defines the cookie domain. If specified, cookies will be set on this domain. - * If not configured, then cookies will be set on the top-level domain of the - * request you sent, i.e. if you send a request to `app1.your-domain.com`, - * then cookies will be set on `.your-domain.com`, such that they - * are also valid for `app2.your-domain.com`. - */ - var cookieDomain: String? = null - } - - class SignatureVerification { - /** - * Maximum refresh rate for public keys in ms. - * We won't fetch new public keys any faster than that to avoid spamming UAA in case - * we receive a lot of "illegal" tokens. - */ - var publicKeyRefreshRateLimit: Long? = 10 * 1000L - /** - * Maximum TTL for the public key in ms. - * The public key will be fetched again from UAA if it gets older than that. - * That way, we make sure that we get the newest keys always in case they are updated there. - */ - var ttl: Long? = 24 * 60 * 60 * 1000L - /** - * Endpoint where to retrieve the public key used to verify token signatures. - */ - var publicKeyEndpointUri: String? = "http://uaa/oauth/token_key" - } -} diff --git a/generators/server/templates/src/main/kotlin/package/domain/AbstractAuditingEntity.kt.ejs b/generators/server/templates/src/main/kotlin/package/domain/AbstractAuditingEntity.kt.ejs index 5a1ce3f5d..743dd5761 100644 --- a/generators/server/templates/src/main/kotlin/package/domain/AbstractAuditingEntity.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/domain/AbstractAuditingEntity.kt.ejs @@ -44,7 +44,7 @@ import org.springframework.data.annotation.LastModifiedDate import org.springframework.data.mongodb.core.mapping.Field <%_ } _%> <%_ if (databaseType === 'neo4j') { _%> -import org.neo4j.springframework.data.core.schema.Property +import org.springframework.data.neo4j.core.schema.Property <%_ } _%> <%_ if (databaseType === 'sql' && !reactive) { _%> import org.springframework.data.jpa.domain.support.AuditingEntityListener diff --git a/generators/server/templates/src/main/kotlin/package/domain/Authority.kt.ejs b/generators/server/templates/src/main/kotlin/package/domain/Authority.kt.ejs index a9da8a760..92ad46d62 100644 --- a/generators/server/templates/src/main/kotlin/package/domain/Authority.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/domain/Authority.kt.ejs @@ -27,8 +27,8 @@ import org.springframework.data.annotation.Id import org.springframework.data.<%= databaseType %>.core.mapping.Document <%_ } _%> <%_ if (databaseType === 'neo4j') { _%> -import org.neo4j.springframework.data.core.schema.Id -import org.neo4j.springframework.data.core.schema.Node +import org.springframework.data.neo4j.core.schema.Id +import org.springframework.data.neo4j.core.schema.Node <%_ } _%> <%_ if (databaseType === 'sql') { _%> <%_ if (!reactive) { _%> diff --git a/generators/server/templates/src/main/kotlin/package/domain/PersistentAuditEvent.kt.ejs b/generators/server/templates/src/main/kotlin/package/domain/PersistentAuditEvent.kt.ejs deleted file mode 100644 index 9c17226a9..000000000 --- a/generators/server/templates/src/main/kotlin/package/domain/PersistentAuditEvent.kt.ejs +++ /dev/null @@ -1,199 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.domain - -<%_ if (databaseType === 'mongodb') { _%> -import org.springframework.data.annotation.Id -import org.springframework.data.mongodb.core.mapping.Document -import org.springframework.data.mongodb.core.mapping.Field -<%_ } else if (databaseType === 'neo4j') { _%> -import org.neo4j.springframework.data.core.schema.GeneratedValue -import org.neo4j.springframework.data.core.schema.Id -import org.neo4j.springframework.data.core.schema.Node -import org.neo4j.springframework.data.core.schema.Property -import org.neo4j.springframework.data.core.schema.Relationship -import org.neo4j.springframework.data.core.support.UUIDStringGenerator -import org.springframework.data.annotation.Transient -<%_ } else if (databaseType === 'couchbase') { _%> -import org.springframework.data.annotation.Id -import com.couchbase.client.java.repository.annotation.Field -import org.springframework.data.couchbase.core.mapping.Document -import org.springframework.data.couchbase.core.mapping.id.GeneratedValue -import org.springframework.data.couchbase.core.mapping.id.IdPrefix -<%_ } else if (databaseType === 'sql') { _%> - <%_ if (reactive) { _%> -import org.springframework.data.annotation.PersistenceConstructor -import org.springframework.data.annotation.Id -import org.springframework.data.annotation.Transient -import org.springframework.data.relational.core.mapping.Column -import org.springframework.data.relational.core.mapping.Table - <%_ } else { _%> -import javax.persistence.CollectionTable -import javax.persistence.Column -import javax.persistence.ElementCollection -import javax.persistence.Entity -import javax.persistence.GeneratedValue -import javax.persistence.GenerationType -import javax.persistence.Id -import javax.persistence.JoinColumn -import javax.persistence.MapKeyColumn - <%_ if (!(prodDatabaseType === 'mysql' || prodDatabaseType === 'mariadb')) { _%> -import javax.persistence.SequenceGenerator - <%_ } _%> -import javax.persistence.Table - <%_ } _%> -<%_ } _%> -import javax.validation.constraints.NotNull -import java.io.Serializable -import java.time.Instant - -<%_ if (databaseType === 'couchbase') { _%> -import <%= packageName %>.config.ID_DELIMITER -import org.springframework.data.couchbase.core.mapping.id.GenerationStrategy.UNIQUE - -<%_ } _%> -/** - * Persist AuditEvent managed by the Spring Boot actuator. - * - * @see org.springframework.boot.actuate.audit.AuditEvent - */ - <%_ if (databaseType === 'sql') { _%> - <%_ if (!reactive) { _%> -@Entity -@Table(name = "<%= jhiTablePrefix %>_persistent_audit_event") - <%_ } else { _%> -@Table("<%= jhiTablePrefix %>_persistent_audit_event") - <%_ } _%> -<%_ } _%> -<%_ if (databaseType === 'mongodb') { _%> -@Document(collection = "<%= jhiTablePrefix %>_persistent_audit_event") -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -@Node("<%= jhiTablePrefix %>_persistent_audit_event") -<%_ } _%> -<%_ if (databaseType === 'couchbase') { _%> -@Document -<%_ } _%> -data class PersistentAuditEvent( - - @Id - <%_ if (databaseType === 'sql') { _%> - <%_ if (!reactive) { _%> - <%_ if (prodDatabaseType === 'mysql' || prodDatabaseType === 'mariadb') { _%> - @GeneratedValue(strategy = GenerationType.IDENTITY) - <%_ } else { _%> - @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") - @SequenceGenerator(name = "sequenceGenerator") - <%_ } _%> - <%_ } _%> - @Column(<% if (!reactive) { %>name = <% } %>"event_id") - var id: Long? = null, - <%_ } else { _%> - <%_ if (databaseType === 'couchbase') { _%> - @GeneratedValue(strategy = UNIQUE, delimiter = ID_DELIMITER) - <%_ } else if (databaseType === 'neo4j') { _%> - @Property("event_id") - @GeneratedValue(UUIDStringGenerator::class) - <%_ } _%> - var id: String? = null, - <%_ } _%> - - @field:NotNull - <%_ if (databaseType === 'sql' && !reactive) { _%> - @Column(nullable = false) - <%_ } _%> - var principal: String? = null, - - <%_ if (databaseType === 'sql') { _%> - @Column(<% if (!reactive) { %>name = <% } %>"event_date") - <%_ } _%> - <%_ if (databaseType === 'mongodb' || databaseType === 'couchbase') { _%> - @Field("event_date") - <%_ } else if (databaseType === 'neo4j') { _%> - @Property("event_date") - <%_ } _%> - var auditEventDate: Instant? = null, - - <%_ if (databaseType === 'sql') { _%> - @Column(<% if (!reactive) { %>name = <% } %>"event_type") - <%_ } _%> - <%_ if (databaseType === 'mongodb' || databaseType === 'couchbase') { _%> - @Field("event_type") - <%_ } else if (databaseType === 'neo4j') { _%> - @Property("event_type") - <%_ } _%> - var auditEventType: String? = null, - - <%_ if (databaseType === 'sql') { _%> - <%_ if (!reactive) { _%> - @ElementCollection - @MapKeyColumn(name = "name") - @Column(name = "value") - @CollectionTable(name = "<%= jhiTablePrefix %>_persistent_audit_evt_data", joinColumns = [JoinColumn(name="event_id")]) - <%_ } else { _%> - @Transient - <%_ } _%> - <%_ } _%> - <%_ if (databaseType === 'neo4j') { _%> - @Transient - <%_ } _%> - var data: MutableMap = mutableMapOf() - -) : Serializable { - -<%_ if (databaseType === 'sql' && reactive) { _%> - @PersistenceConstructor - constructor( - id: Long?, - principal: String?, - auditEventDate: Instant?, - auditEventType: String? - ): this(id, principal, auditEventDate, auditEventType, mutableMapOf()) -<%_ } _%> - -<%_ if (databaseType === 'couchbase') { _%> - - @IdPrefix - private val prefix: String = PREFIX -<%_ } _%> - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is PersistentAuditEvent) return false - if (other.id == null || id == null) return false - - return id == other.id - } - - override fun hashCode() = 31 - - override fun toString() = "PersistentAuditEvent{" + - "principal='" + principal + '\'' + - ", auditEventDate=" + auditEventDate + - ", auditEventType='" + auditEventType + '\'' + - '}' - - companion object { - private const val serialVersionUID = 1L - <%_ if (databaseType === 'couchbase') { _%> - - const val PREFIX = "audit" - <%_ } _%> - } -} diff --git a/generators/server/templates/src/main/kotlin/package/domain/PersistentToken.kt.ejs b/generators/server/templates/src/main/kotlin/package/domain/PersistentToken.kt.ejs index 1c53beb21..bb0d957e3 100644 --- a/generators/server/templates/src/main/kotlin/package/domain/PersistentToken.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/domain/PersistentToken.kt.ejs @@ -19,9 +19,10 @@ package <%= packageName %>.domain <%_ if (databaseType === 'cassandra') { _%> -import com.datastax.driver.mapping.annotations.Column -import com.datastax.driver.mapping.annotations.PartitionKey -import com.datastax.driver.mapping.annotations.Table +import com.datastax.oss.driver.api.mapper.annotations.Entity +import com.datastax.oss.driver.api.mapper.annotations.NamingStrategy +import com.datastax.oss.driver.api.mapper.annotations.PartitionKey +import com.datastax.oss.driver.api.mapper.entity.naming.NamingConvention <%_ } _%> import com.fasterxml.jackson.annotation.JsonIgnore <%_ if (enableHibernateCache) { _%> @@ -34,11 +35,11 @@ import org.springframework.data.mongodb.core.mapping.DBRef import org.springframework.data.mongodb.core.mapping.Document <%_ } _%> <%_ if (databaseType === 'neo4j') { _%> -import org.neo4j.springframework.data.core.schema.GeneratedValue -import org.neo4j.springframework.data.core.schema.Id -import org.neo4j.springframework.data.core.schema.Node -import org.neo4j.springframework.data.core.schema.Property -import org.neo4j.springframework.data.core.schema.Relationship +import org.springframework.data.neo4j.core.schema.GeneratedValue +import org.springframework.data.neo4j.core.schema.Id +import org.springframework.data.neo4j.core.schema.Node +import org.springframework.data.neo4j.core.schema.Property +import org.springframework.data.neo4j.core.schema.Relationship <%_ } _%> <%_ if (databaseType === 'couchbase') { _%> import org.springframework.data.annotation.Id @@ -63,7 +64,7 @@ import java.io.Serializable import java.time.LocalDate <%_ } _%> <%_ if (databaseType === 'cassandra') { _%> -import java.util.Date +import java.time.Instant <%_ } _%> <%_ if (databaseType === 'couchbase') { _%> @@ -90,7 +91,12 @@ import org.springframework.data.couchbase.core.mapping.id.GenerationStrategy.USE @Document <%_ } _%> <%_ if (databaseType === 'cassandra') { _%> + <%_ if (reactive) { _%> @Table(name = "persistent_token") + <%_ } else { _%> +@Entity +@NamingStrategy(convention = [NamingConvention.SNAKE_CASE_INSENSITIVE]) + <%_ } _%> <%_ } _%> class PersistentToken @JvmOverloads constructor( <%_ if (databaseType === 'couchbase') { _%> @@ -110,35 +116,48 @@ class PersistentToken @JvmOverloads constructor( var series: String? = null, @JsonIgnore - @field:NotNull<% if (databaseType === 'sql') { %> - @Column(name = "token_value", nullable = false)<% } %><% if (databaseType === 'cassandra') { %> - @Column(name = "token_value")<% } %> + @field:NotNull + <%_ if (databaseType === 'sql') { _%> + @Column(name = "token_value", nullable = false) + <%_ } else if (databaseType === 'cassandra' && reactive) { _%> + @Column(name = "token_value") + <%_ } _%> var tokenValue: String? = null, <%_ if (databaseType === 'sql') { _%> - @Column(name = "token_date") - var tokenDate: LocalDate? = null,<% } %><% if (databaseType === 'mongodb' || databaseType === 'couchbase') { %> - var tokenDate: LocalDate? = null,<% } %><% if (databaseType === 'neo4j') { %> + <%_ } else if (databaseType === 'neo4j') { _%> @Property(name = "token_date") - var tokenDate: Date? = null,<% } %><% if (databaseType === 'cassandra') { %> + <%_ } else if (databaseType === 'cassandra' && reactive) { _%> @Column(name = "token_date") - var tokenDate: Date? = null,<% } %> + <%_ } _%> + var tokenDate: <% if (databaseType !== 'cassandra') { %>LocalDate<% } else { %>Instant<% } %>? = null, // An IPV6 address max length is 39 characters - @field:Size(min = 0, max = 39)<% if (databaseType === 'sql') { %> - @Column(name = "ip_address", length = 39)<% } %><% if (databaseType === 'cassandra') { %> - @Column(name = "ip_address")<% } %><% if (databaseType === 'neo4j') { %> - @Property(name = "ip_address")<% } %> + @field:Size(min = 0, max = 39) + <%_ if (databaseType === 'sql') { _%> + @Column(name = "ip_address", length = 39) + <%_ } else if (databaseType === 'cassandra' && reactive) { _%> + @Column(name = "ip_address") + <%_ } else if (databaseType === 'neo4j') { _%> + @Property(name = "ip_address") + <%_ } _%> var ipAddress: String? = null, + <%_ if (databaseType === 'sql' || (databaseType === 'cassandra' && reactive)) { _%> + @Column(name = "user_agent") + <%_ } _%> + <%_ if (databaseType === 'neo4j') { _%> + @Property(name = "user_agent") + <%_ } _%> userAgent: String? = null, <%_ if (databaseType === 'cassandra' || databaseType === 'couchbase') { _%> var login: String? = null, <%_ } _%> <%_ if (databaseType === 'cassandra') { _%> - + <%_ if (reactive) { _%> @Column(name = "user_id") + <%_ } _%> var userId: String? = null <%_ } _%> <%_ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType == 'neo4j') { _%> @@ -164,7 +183,7 @@ class PersistentToken @JvmOverloads constructor( private var prefix: String = PREFIX <%_ } _%> -<%_ if (databaseType === 'sql' || databaseType === 'cassandra') { _%> +<%_ if (databaseType === 'sql' || (databaseType === 'cassandra' && reactive)) { _%> @Column(name = "user_agent") <%_ } _%> <%_ if (databaseType === 'neo4j') { _%> diff --git a/generators/server/templates/src/main/kotlin/package/domain/User.kt.ejs b/generators/server/templates/src/main/kotlin/package/domain/User.kt.ejs index e5b9c6426..b0953edb9 100644 --- a/generators/server/templates/src/main/kotlin/package/domain/User.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/domain/User.kt.ejs @@ -24,9 +24,11 @@ import <%= packageName %>.config.LOGIN_REGEX import com.couchbase.client.java.repository.annotation.Field <%_ } _%> <%_ if (!reactive && databaseType === 'cassandra') { _%> -import com.datastax.driver.mapping.annotations.Column -import com.datastax.driver.mapping.annotations.PartitionKey -import com.datastax.driver.mapping.annotations.Table +import com.datastax.oss.driver.api.mapper.annotations.CqlName +import com.datastax.oss.driver.api.mapper.annotations.Entity +import com.datastax.oss.driver.api.mapper.annotations.NamingStrategy +import com.datastax.oss.driver.api.mapper.annotations.PartitionKey +import com.datastax.oss.driver.api.mapper.entity.naming.NamingConvention <%_ } _%> import com.fasterxml.jackson.annotation.JsonIgnore <%_ if (databaseType === 'sql' && !reactive) { _%> @@ -49,12 +51,12 @@ import org.springframework.data.mongodb.core.index.Indexed import org.springframework.data.mongodb.core.mapping.Field <%_ } _%> <%_ if (databaseType === 'neo4j') { _%> -import org.neo4j.springframework.data.core.schema.GeneratedValue -import org.neo4j.springframework.data.core.schema.Id -import org.neo4j.springframework.data.core.schema.Node -import org.neo4j.springframework.data.core.schema.Property -import org.neo4j.springframework.data.core.schema.Relationship -import org.neo4j.springframework.data.core.support.UUIDStringGenerator +import org.springframework.data.neo4j.core.schema.GeneratedValue +import org.springframework.data.neo4j.core.schema.Id +import org.springframework.data.neo4j.core.schema.Node +import org.springframework.data.neo4j.core.schema.Property +import org.springframework.data.neo4j.core.schema.Relationship +import org.springframework.data.neo4j.core.support.UUIDStringGenerator <%_ } _%> <%_ if (reactive && databaseType === 'cassandra') { _%> import org.springframework.data.cassandra.core.mapping.Column @@ -95,6 +97,9 @@ import javax.validation.constraints.Size import java.io.Serializable import java.time.Instant import java.util.Locale +<%_ if (user.primaryKey.type === 'UUID') { _%> +import java.util.UUID +<%_ } _%> <%_ if (databaseType === 'couchbase') { _%> import <%= packageName %>.config.ID_DELIMITER @@ -108,7 +113,7 @@ import org.springframework.data.couchbase.core.mapping.id.GenerationStrategy.USE <%_ if (!reactive) { _%> @Entity <%_ } _%> -@Table(<% if (!reactive) { %>name = <% } %>"<%= jhiTablePrefix %>_user") +@Table(<% if (!reactive) { %>name = <% } %>"<%= user.entityTableName %>") <%_ } _%> <%_ if (enableHibernateCache) { _%> @Cache(usage = CacheConcurrencyStrategy.<% if (cacheProvider !== 'infinispan') { %>NONSTRICT_<% } %>READ_WRITE) @@ -117,13 +122,18 @@ import org.springframework.data.couchbase.core.mapping.id.GenerationStrategy.USE @org.springframework.data.mongodb.core.mapping.Document(collection = "<%= jhiTablePrefix %>_user") <%_ } _%> <%_ if (databaseType === 'neo4j') { _%> -@Node("<%= jhiTablePrefix %>_user") +@Node("<%= user.entityTableName %>") <%_ } _%> <%_ if (databaseType === 'couchbase') { _%> @Document <%_ } _%> <%_ if (databaseType === 'cassandra') { _%> -@Table(<% if(!reactive) { %>name = <% } %>"user") + <%_ if (reactive) { _%> +@Table("user") + <%_ } else { _%> +@Entity +@NamingStrategy(convention = [NamingConvention.SNAKE_CASE_INSENSITIVE]) + <%_ } _%> <%_ } _%> <%_ if (searchEngine === 'elasticsearch') { _%> @org.springframework.data.elasticsearch.annotations.Document(indexName = "user") @@ -133,24 +143,24 @@ class <%= asEntity('User') %> ( @Id <%_ if (!reactive) { _%> - <%_ if (authenticationType !== 'oauth2' && (prodDatabaseType === 'mysql' || prodDatabaseType === 'mariadb')) { _%> + <%_ if (user.primaryKey.fields[0].jpaGeneratedValue === 'identity') { _%> @GeneratedValue(strategy = GenerationType.IDENTITY) - <%_ } else if (authenticationType !== 'oauth2') { _%> + <%_ } else if (user.primaryKey.fields[0].jpaGeneratedValue === 'sequence') { _%> @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") @SequenceGenerator(name = "sequenceGenerator") + <%_ } else if (user.primaryKey.fields[0].jpaGeneratedValue) { _%> + @GeneratedValue <%_ } _%> <%_ } _%> <%_ if (searchEngine === 'elasticsearch' && authenticationType === 'oauth2') { _%> @org.springframework.data.elasticsearch.annotations.Field(type = FieldType.Keyword) <%_ } _%> - var id: <% if (authenticationType === 'oauth2') { %>String?<% } else { %>Long?<% } %> = null, <%_ } else if (databaseType === 'neo4j') { _%> @Id <%_ if (authenticationType !== 'oauth2') { _%> @GeneratedValue(UUIDStringGenerator::class) <%_ } _%> @Property("user_id") - var id: String? = null, <%_ } else { _%> <%_ if (databaseType === 'mongodb' || databaseType === 'couchbase') { _%> @@ -169,8 +179,8 @@ class <%= asEntity('User') %> ( <%_ if (searchEngine === 'elasticsearch') { _%> @org.springframework.data.elasticsearch.annotations.Field(type = FieldType.Keyword) <%_ } _%> - var id: String? = null, <%_ } _%> + var id: <%= user.primaryKey.type %>? = null, @field:NotNull @field:Pattern(regexp = LOGIN_REGEX) @@ -209,6 +219,9 @@ class <%= asEntity('User') %> ( <%_ if (databaseType === 'mongodb' || databaseType === 'couchbase') { _%> @Field("first_name") <%_ } _%> + <%_ if (databaseType === 'cassandra' && !reactive) { _%> + @field:CqlName("firstname") + <%_ } _%> <%_ if (databaseType === 'neo4j') { _%> @Property("first_name") <%_ } _%> @@ -224,6 +237,9 @@ class <%= asEntity('User') %> ( <%_ if (databaseType === 'mongodb' || databaseType === 'couchbase') { _%> @Field("last_name") <%_ } _%> + <%_ if (databaseType === 'cassandra' && !reactive) { _%> + @field:CqlName("lastname") + <%_ } _%> <%_ if (databaseType === 'neo4j') { _%> @Property("last_name") <%_ } _%> @@ -245,7 +261,7 @@ class <%= asEntity('User') %> ( @Column(nullable = false) <%_ } _%> <%_ } _%> - var activated: Boolean = false, + var activated: Boolean? = false, @field:Size(min = 2, max = 10) <%_ if (databaseType === 'sql' && !reactive) { _%> @@ -260,8 +276,8 @@ class <%= asEntity('User') %> ( <%_ if (databaseType === 'neo4j') { _%> @Property("lang_key") <%_ } _%> - <%_ if (databaseType === 'cassandra') { _%> - @Column(<% if (!reactive) { %>name = <% } %>"lang_key") + <%_ if (databaseType === 'cassandra' && reactive) { _%> + @Column("lang_key") <%_ } _%> var langKey: String? = null, <%_ if (databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase' || databaseType === 'sql') { _%> @@ -296,8 +312,8 @@ class <%= asEntity('User') %> ( <%_ if (databaseType === 'neo4j') { _%> @Property("activation_key") <%_ } _%> - <%_ if (databaseType === 'cassandra') { _%> - @Column(<% if (!reactive) { %>name = <% } %>"activation_key") + <%_ if (databaseType === 'cassandra' && reactive) { _%> + @Column("activation_key") <%_ } _%> @JsonIgnore var activationKey: String? = null, @@ -315,12 +331,12 @@ class <%= asEntity('User') %> ( <%_ if (databaseType === 'neo4j') { _%> @Property("reset_key") <%_ } _%> - <%_ if (databaseType === 'cassandra') { _%> - @Column(<% if (!reactive) { %>name = <% } %>"reset_key") + <%_ if (databaseType === 'cassandra' && reactive) { _%> + @Column("reset_key") <%_ } _%> var resetKey: String? = null, - <%_ if (databaseType === 'sql' || databaseType === 'cassandra') { _%> + <%_ if (databaseType === 'sql' || (databaseType === 'cassandra' && reactive)) { _%> @Column(<% if(!reactive) { %>name = <% } %>"reset_date") <%_ } else if (databaseType === 'mongodb' || databaseType === 'couchbase') { _%> @Field("reset_date") @@ -331,42 +347,36 @@ class <%= asEntity('User') %> ( <%_ } _%> @JsonIgnore - <%_ if (databaseType === 'neo4j') { _%> - @Relationship("HAS_AUTHORITY") - <%_ } _%> - <%_ if (databaseType === 'sql' && !reactive) { _%> + <% if (databaseType === 'neo4j') { %>@Relationship("HAS_AUTHORITY")<% } %> + <% if (databaseType === 'sql' && !reactive) { %> @ManyToMany @JoinTable( - name = "<%= jhiTablePrefix %>_user_authority", + name = "<%= user.entityTableName %>_authority", joinColumns = [JoinColumn(name = "user_id", referencedColumnName = "id")], inverseJoinColumns = [JoinColumn(name = "authority_name", referencedColumnName = "name")] ) - <%_ if (enableHibernateCache) { if (cacheProvider === 'infinispan') { _%> + <% if (enableHibernateCache) { if (cacheProvider === 'infinispan') { %> @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) - <%_ } else { _%> + <% } else { %> @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) - <%_ } } _%> + <% } } %> @BatchSize(size = 20) - <%_ } _%> - <%_ if (databaseType === 'sql' && reactive) { _%> + <% } %> + <% if (databaseType === 'sql' && reactive) { %> @Transient - <%_ } _%> - <%_ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j') { _%> - var authorities: MutableSet = mutableSetOf(), - <%_ } _%> - <%_ if (databaseType === 'cassandra' || databaseType === 'couchbase') { _%> - var authorities: MutableSet = mutableSetOf()<% if(databaseType !== 'cassandra') { %>,<% } %> - <%_ } _%> - <%_ if (authenticationType === 'session' && databaseType === 'sql' && !reactive) { _%> + <% } %> + <% if (['sql', 'mongodb', 'neo4j'].includes(databaseType)) { %> + var authorities: MutableSet = mutableSetOf() + <% } else if (['cassandra', 'couchbase'].includes(databaseType)) { %> + var authorities: MutableSet = mutableSetOf() + <% } %><% if (authenticationType === 'session' && databaseType === 'sql' && !reactive) { %>, @JsonIgnore @OneToMany(cascade = [ CascadeType.ALL ], orphanRemoval = true, mappedBy = "user") <%_ if (enableHibernateCache) { _%> @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) <%_ } _%> - var persistentTokens: MutableSet = mutableSetOf(),<% } %> -<%_ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'couchbase') { _%> - + var persistentTokens: MutableSet = mutableSetOf()<% } %><% if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'couchbase') { %>, createdBy: String? = null, createdDate: Instant? = Instant.now(), lastModifiedBy: String? = null, @@ -394,7 +404,7 @@ class <%= asEntity('User') %> ( firstName: String?, lastName: String?, email: String?, - activated: Boolean, + activated: Boolean?, langKey: String?, <%_ if (databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase' || databaseType === 'sql') { _%> imageUrl: String?<% if (authenticationType !== 'oauth2' || (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'couchbase')) { %>,<% } %> diff --git a/generators/server/templates/src/main/kotlin/package/gateway/TokenRelayFilter.kt.ejs b/generators/server/templates/src/main/kotlin/package/gateway/TokenRelayFilter.kt.ejs deleted file mode 100644 index eeb243850..000000000 --- a/generators/server/templates/src/main/kotlin/package/gateway/TokenRelayFilter.kt.ejs +++ /dev/null @@ -1,44 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.gateway - -import com.netflix.zuul.ZuulFilter -import com.netflix.zuul.context.RequestContext -import org.springframework.stereotype.Component - -@Component -class TokenRelayFilter : ZuulFilter() { - - override fun run(): Any? { - val ctx = RequestContext.getCurrentContext() - <%_ if (authenticationType === 'jwt' || authenticationType === 'uaa') { _%> - @Suppress("UNCHECKED_CAST") - val headers = ctx.get("ignoredHeaders") as MutableSet - // JWT tokens should be relayed to the resource servers - headers.remove("authorization") - <%_ } _%> - return null - } - - override fun shouldFilter() = true - - override fun filterType() = "pre" - - override fun filterOrder() = 10000 -} diff --git a/generators/server/templates/src/main/kotlin/package/gateway/accesscontrol/AccessControlFilter.kt.ejs b/generators/server/templates/src/main/kotlin/package/gateway/accesscontrol/AccessControlFilter.kt.ejs deleted file mode 100644 index 1627dab3b..000000000 --- a/generators/server/templates/src/main/kotlin/package/gateway/accesscontrol/AccessControlFilter.kt.ejs +++ /dev/null @@ -1,102 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.gateway.accesscontrol - -import io.github.jhipster.config.JHipsterProperties - -import org.slf4j.LoggerFactory -import org.springframework.cloud.netflix.zuul.filters.RouteLocator -import org.springframework.http.HttpStatus - -import com.netflix.zuul.ZuulFilter -import com.netflix.zuul.context.RequestContext - -/** - * Zuul filter for restricting access to backend micro-services endpoints. - */ -class AccessControlFilter( - private val routeLocator: RouteLocator, - private val jHipsterProperties: JHipsterProperties -) : ZuulFilter() { - - private val log = LoggerFactory.getLogger(javaClass) - - override fun filterType() = "pre" - - override fun filterOrder() = 0 - - /** - * Filter requests on endpoints that are not in the list of authorized microservices endpoints. - */ - override fun shouldFilter(): Boolean { - val requestUri = RequestContext.getCurrentContext().request.requestURI - val contextPath = RequestContext.getCurrentContext().request.contextPath - - // If the request Uri does not start with the path of the authorized endpoints, we block the request - for (route in routeLocator.routes) { - val serviceUrl = contextPath + route.fullPath - val serviceName = route.id - - // If this route correspond to the current request URI - // We do a substring to remove the "**" at the end of the route URL - if (requestUri.startsWith(serviceUrl.substring(0, serviceUrl.length - 2))) { - return !isAuthorizedRequest(serviceUrl, serviceName, requestUri) - } - } - return true - } - - private fun isAuthorizedRequest(serviceUrl: String, serviceName: String, requestUri: String): Boolean { - val authorizedMicroservicesEndpoints = jHipsterProperties.gateway.authorizedMicroservicesEndpoints - - // If the authorized endpoints list was left empty for this route, all access are allowed - if (authorizedMicroservicesEndpoints[serviceName] == null) { - log.debug( - "Access Control: allowing access for $requestUri, as no access control policy has been set up for service: $serviceName" - ) - return true - } else { - val authorizedEndpoints = authorizedMicroservicesEndpoints[serviceName] - - if (authorizedEndpoints != null) { - // Go over the authorized endpoints to control that the request URI matches it - for (endpoint in authorizedEndpoints) { - // We do a substring to remove the "**/" at the end of the route URL - val gatewayEndpoint = serviceUrl.substring(0, serviceUrl.length - 3) + endpoint - if (requestUri.startsWith(gatewayEndpoint)) { - log.debug( - "Access Control: allowing access for $requestUri, as it matches the following authorized microservice endpoint: $gatewayEndpoint" - ) - return true - } - } - } - } - return false - } - - override fun run(): Any? { - RequestContext.getCurrentContext().apply { - responseStatusCode = HttpStatus.FORBIDDEN.value() - setSendZuulResponse(false) - log.debug("Access Control: filtered unauthorized access on endpoint ${request.requestURI}") - } - return null - } -} diff --git a/generators/server/templates/src/main/kotlin/package/gateway/ratelimiting/RateLimitingFilter.kt.ejs b/generators/server/templates/src/main/kotlin/package/gateway/ratelimiting/RateLimitingFilter.kt.ejs deleted file mode 100644 index 5b5ebe0ea..000000000 --- a/generators/server/templates/src/main/kotlin/package/gateway/ratelimiting/RateLimitingFilter.kt.ejs +++ /dev/null @@ -1,127 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.gateway.ratelimiting - -import <%= packageName %>.security.getCurrentUserLogin - -import java.time.Duration -import java.util.function.Supplier -import javax.cache.Caching -import javax.cache.configuration.MutableConfiguration -import javax.servlet.http.HttpServletRequest - -import org.slf4j.LoggerFactory -import org.springframework.http.HttpStatus - -import com.netflix.zuul.ZuulFilter -import com.netflix.zuul.context.RequestContext - -import io.github.bucket4j.Bandwidth -import io.github.bucket4j.Bucket4j -import io.github.bucket4j.BucketConfiguration -import io.github.bucket4j.grid.GridBucketState -import io.github.bucket4j.grid.ProxyManager -import io.github.bucket4j.grid.jcache.JCache -import io.github.jhipster.config.JHipsterProperties - -/** - * Zuul filter for limiting the number of HTTP calls per client. - * - * See the Bucket4j documentation at https://github.com/vladimir-bukhtoyarov/bucket4j - * https://github.com/vladimir-bukhtoyarov/bucket4j/blob/master/doc-pages/jcache-usage - * .md#example-1---limiting-access-to-http-server-by-ip-address - */ -class RateLimitingFilter(private val jHipsterProperties: JHipsterProperties) : ZuulFilter() { - - private val log = LoggerFactory.getLogger(javaClass) - - private val cache: javax.cache.Cache - - private val buckets: ProxyManager - - private val configSupplier: Supplier - get() = Supplier { - val rateLimitingProperties = jHipsterProperties.gateway.rateLimiting - - Bucket4j.configurationBuilder() - .addLimit( - Bandwidth.simple( - rateLimitingProperties.limit, - Duration.ofSeconds(rateLimitingProperties.durationInSeconds.toLong()) - ) - ) - .build() - } - - init { - - val cachingProvider = Caching.getCachingProvider() - val cacheManager = cachingProvider.cacheManager - val config = MutableConfiguration() - .setTypes(String::class.java, GridBucketState::class.java) - - this.cache = cacheManager.createCache(GATEWAY_RATE_LIMITING_CACHE_NAME, config) - this.buckets = Bucket4j.extension(JCache::class.java).proxyManagerForCache(cache) - } - - override fun filterType() = "pre" - - override fun filterOrder() = 10 - - // specific APIs can be filtered out using - // if (RequestContext.getCurrentContext().getRequest().getRequestURI().startsWith("/api")) { ... } - override fun shouldFilter() = true - - override fun run(): Any? { - val bucketId = getId(RequestContext.getCurrentContext().request) - val bucket = buckets.getProxy(bucketId, configSupplier) - if (bucket.tryConsume(1)) { - // the limit is not exceeded - log.debug("API rate limit OK for $bucketId") - } else { - // limit is exceeded - log.info("API rate limit exceeded for $bucketId") - apiLimitExceeded() - } - return null - } - - /** - * Create a Zuul response error when the API limit is exceeded. - */ - private fun apiLimitExceeded() { - RequestContext.getCurrentContext().apply { - responseStatusCode = HttpStatus.TOO_MANY_REQUESTS.value() - if (responseBody == null) { - responseBody = "API rate limit exceeded" - setSendZuulResponse(false) - } - } - } - - /** - * The ID that will identify the limit: the user login or the user IP address. - */ - private fun getId(httpServletRequest: HttpServletRequest): String = - getCurrentUserLogin().orElse(httpServletRequest.remoteAddr) - - companion object { - const val GATEWAY_RATE_LIMITING_CACHE_NAME = "gateway-rate-limiting" - } -} diff --git a/generators/server/templates/src/main/kotlin/package/gateway/responserewriting/SwaggerBasePathRewritingFilter.kt.ejs b/generators/server/templates/src/main/kotlin/package/gateway/responserewriting/SwaggerBasePathRewritingFilter.kt.ejs deleted file mode 100644 index c6d5ae8bc..000000000 --- a/generators/server/templates/src/main/kotlin/package/gateway/responserewriting/SwaggerBasePathRewritingFilter.kt.ejs +++ /dev/null @@ -1,109 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.gateway.responserewriting - -import com.fasterxml.jackson.databind.ObjectMapper -import com.netflix.zuul.context.RequestContext -import org.apache.commons.io.IOUtils -import org.slf4j.LoggerFactory -import org.springframework.cloud.netflix.zuul.filters.ZuulProperties -import org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter -import springfox.documentation.swagger2.web.Swagger2Controller - -import java.io.ByteArrayInputStream -import java.io.ByteArrayOutputStream -import java.io.IOException -import java.io.PrintWriter -import java.nio.charset.StandardCharsets -import java.util.LinkedHashMap -import java.util.zip.GZIPInputStream -import java.util.zip.GZIPOutputStream - -/** - * Zuul filter to rewrite micro-services Swagger URL Base Path. - */ -class SwaggerBasePathRewritingFilter : SendResponseFilter(ZuulProperties()) { - - private val log = LoggerFactory.getLogger(javaClass) - - private val mapper = ObjectMapper() - - override fun filterType() = "post" - - override fun filterOrder() = 100 - - /** - * Filter requests to micro-services Swagger docs. - */ - override fun shouldFilter(): Boolean = - RequestContext.getCurrentContext().request.requestURI.endsWith(Swagger2Controller.DEFAULT_URL) - - override fun run(): Any? { - val context = RequestContext.getCurrentContext() - - context.response.characterEncoding = "UTF-8" - - val rewrittenResponse = rewriteBasePath(context) - if (context.responseGZipped) { - try { - context.responseDataStream = ByteArrayInputStream(gzipData(rewrittenResponse)) - } catch (e: IOException) { - log.error("Swagger-docs filter error $e") - } - } else { - context.responseBody = rewrittenResponse - } - return null - } - - private fun rewriteBasePath(context: RequestContext): String? { - var responseDataStream = context.responseDataStream - val requestUri = RequestContext.getCurrentContext().request.requestURI - try { - if (context.responseGZipped) { - responseDataStream = GZIPInputStream(context.responseDataStream) - } - val response = IOUtils.toString(responseDataStream, StandardCharsets.UTF_8) - if (response != null) { - @Suppress("UNCHECKED_CAST") - val map = this.mapper.readValue(response, LinkedHashMap::class.java) as LinkedHashMap - - val basePath = requestUri.replace(Swagger2Controller.DEFAULT_URL, "") - map["basePath"] = basePath - log.debug("Swagger-docs: rewritten Base URL with correct micro-service route: $basePath") - return mapper.writeValueAsString(map) - } - } catch (e: IOException) { - log.error("Swagger-docs filter error $e") - } - - return null - } - -} - -@Throws(IOException::class) -fun gzipData(content: String?): ByteArray { - val bos = ByteArrayOutputStream() - val gzip = PrintWriter(GZIPOutputStream(bos)) - gzip.print(content) - gzip.flush() - gzip.close() - return bos.toByteArray() -} diff --git a/generators/server/templates/src/main/kotlin/package/repository/AuthorityRepository.kt.ejs b/generators/server/templates/src/main/kotlin/package/repository/AuthorityRepository.kt.ejs index dc8416be3..2f2218509 100644 --- a/generators/server/templates/src/main/kotlin/package/repository/AuthorityRepository.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/repository/AuthorityRepository.kt.ejs @@ -31,7 +31,7 @@ import org.springframework.data.mongodb.repository.<% if (reactive) { %>Reactive <%_ } _%> <%_ if (databaseType === 'neo4j') { _%> -import org.neo4j.springframework.data.repository.<% if (reactive) { %>Reactive<% } %>Neo4jRepository +import org.springframework.data.neo4j.repository.<% if (reactive) { %>Reactive<% } %>Neo4jRepository <% if (reactive) { %>import reactor.core.publisher.Flux<% } %> <%_ } _%> <% if (databaseType === 'sql') { %> @@ -44,7 +44,7 @@ import org.neo4j.springframework.data.repository.<% if (reactive) { %>Reactive<% */ <% } %><%_ if (databaseType === 'neo4j') { _%> /** -* Spring Data Neo4j RX repository for the {@link Authority} entity. +* Spring Data Neo4j repository for the {@link Authority} entity. */ <%_ } _%><% if (databaseType === 'couchbase') { %> /** diff --git a/generators/server/templates/src/main/kotlin/package/repository/CustomAuditEventRepository.kt.ejs b/generators/server/templates/src/main/kotlin/package/repository/CustomAuditEventRepository.kt.ejs deleted file mode 100644 index d7a160f31..000000000 --- a/generators/server/templates/src/main/kotlin/package/repository/CustomAuditEventRepository.kt.ejs +++ /dev/null @@ -1,98 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.repository - -import <%= packageName %>.config.ANONYMOUS_USER -import <%= packageName %>.config.audit.AuditEventConverter -import <%= packageName %>.domain.PersistentAuditEvent - -import org.slf4j.LoggerFactory -import org.springframework.boot.actuate.audit.AuditEvent -import org.springframework.boot.actuate.audit.AuditEventRepository -import org.springframework.stereotype.Repository -import org.springframework.transaction.annotation.Propagation -import org.springframework.transaction.annotation.Transactional - -import java.time.Instant - -private const val AUTHORIZATION_FAILURE = "AUTHORIZATION_FAILURE" - -/** - * Should be the same as in Liquibase migration. - */ -const val EVENT_DATA_COLUMN_MAX_LENGTH: Int = 255 - -/** - * An implementation of Spring Boot's {@link AuditEventRepository}. - */ -@Repository -class CustomAuditEventRepository( - private val persistenceAuditEventRepository: PersistenceAuditEventRepository, - private val auditEventConverter: AuditEventConverter -) : AuditEventRepository { - - private val log = LoggerFactory.getLogger(javaClass) - - override fun find(principal: String, after: Instant, type: String): List { - val persistentAuditEvents = - persistenceAuditEventRepository.findByPrincipalAndAuditEventDateAfterAndAuditEventType( - principal, after, type - ) - return auditEventConverter.convertToAuditEvent(persistentAuditEvents) - } - - @Transactional(propagation = Propagation.REQUIRES_NEW) - override fun add(event: AuditEvent) { - if (AUTHORIZATION_FAILURE != event.type && ANONYMOUS_USER != event.principal) { - - val persistentAuditEvent = PersistentAuditEvent( - principal = event.principal, - auditEventType = event.type, - auditEventDate = event.timestamp - ) - val eventData = auditEventConverter.convertDataToStrings(event.data) - persistentAuditEvent.data = truncate(eventData) - persistenceAuditEventRepository.save(persistentAuditEvent) - } - } - - /** - * Truncate event data that might exceed column length. - */ - private fun truncate(data: Map?): MutableMap { - val results = mutableMapOf() - - if (data != null) { - for (entry in data.entries) { - var value: String? = entry.value - if (value != null) { - val length = value.length - if (length > EVENT_DATA_COLUMN_MAX_LENGTH) { - value = value.substring(0, EVENT_DATA_COLUMN_MAX_LENGTH) - log.warn( - "Event data for ${entry.key} too long ($length) has been truncated to $EVENT_DATA_COLUMN_MAX_LENGTH. Consider increasing column width." - ) - } - } - results[entry.key] = value - } - } - return results - } -} diff --git a/generators/server/templates/src/main/kotlin/package/repository/reactive/CustomReactiveN1qlCouchbaseRepository.kt.ejs b/generators/server/templates/src/main/kotlin/package/repository/CustomReactiveN1qlCouchbaseRepository.kt.ejs similarity index 60% rename from generators/server/templates/src/main/kotlin/package/repository/reactive/CustomReactiveN1qlCouchbaseRepository.kt.ejs rename to generators/server/templates/src/main/kotlin/package/repository/CustomReactiveN1qlCouchbaseRepository.kt.ejs index 83332920d..206b2e7bf 100644 --- a/generators/server/templates/src/main/kotlin/package/repository/reactive/CustomReactiveN1qlCouchbaseRepository.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/repository/CustomReactiveN1qlCouchbaseRepository.kt.ejs @@ -1,10 +1,10 @@ <%# Copyright 2013-2020 the original author or authors from the JHipster project. - This file is part of the JHipster project, see https://jhipster.github.io/ +This file is part of the JHipster project, see https://jhipster.github.io/ for more information. - Licensed under the Apache License, Version 2.0 (the "License"); + Licensed under the Apache License, Version 2.0 (the "License") you may not use this file except in compliance with the License. You may obtain a copy of the License at @@ -51,71 +51,70 @@ import java.util.LinkedList <%_ } _%> /** - * A custom implementation of `CouchbaseRepository`. - * - * Create a new Repository. - * - * @param metadata the Metadata for the entity. - * @param operations the reference to the template used. + * A custom implementation of {@code CouchbaseRepository}. */ -class CustomReactiveN1qlCouchbaseRepository( - private val metadata: CouchbaseEntityInformation, - private val operations: RxJavaCouchbaseOperations -) : ReactiveN1qlCouchbaseRepository(metadata, operations)<%if (searchEngine === 'couchbase') { %>, SearchCouchbaseRepository<% } %> { - - private val persistentEntity = couchbaseOperations.converter.mappingContext.getPersistentEntity(entityInformation.javaType) +public class CustomReactiveN1qlCouchbaseRepository(metadata: CouchbaseEntityInformation, couchbaseOperations: RxJavaCouchbaseOperations) : + ReactiveN1qlCouchbaseRepository(metadata, couchbaseOperations)<%if (searchEngine === 'couchbase') { %>, SearchCouchbaseRepository<% } %> { + + private val persistentEntity: CouchbasePersistentEntity<*>? = + getCouchbaseOperations().converter.mappingContext.getPersistentEntity(entityInformation.javaType) + @Autowired - private var template: CouchbaseTemplate = CouchbaseTemplate(couchbaseOperations.couchbaseClusterInfo, couchbaseOperations.couchbaseBucket) + private val template: CouchbaseTemplate + + private final CouchbasePersistentEntity persistentEntity init { + template = CouchbaseTemplate(getCouchbaseOperations().couchbaseClusterInfo, getCouchbaseOperations().couchbaseBucket) allowPageable() } // Temporary Hack to fix pageable - @Suppress("unchecked") + @SuppressWarnings("unchecked") private fun allowPageable() { try { val allowed_pageable_types = QueryExecutionConverters::class.java.getDeclaredField("ALLOWED_PAGEABLE_TYPES") - allowed_pageable_types.isAccessible = true - val ALLOWED_PAGEABLE_TYPES = allowed_pageable_types[QueryExecutionConverters::class.java] as MutableSet> - ALLOWED_PAGEABLE_TYPES.add(Flux::class.java) + allowed_pageable_types.accessible = true + val ALLOWED_PAGEABLE_TYPES = allowed_pageable_types.get(QueryExecutionConverters::class) as Set> + ALLOWED_PAGEABLE_TYPES.add(Flux::class) } catch (e: NoSuchFieldException) { e.printStackTrace() - } catch (e: IllegalAccessException) { + } catch(e: IllegalAccessException) { e.printStackTrace() } } - override fun save(entity: S): Mono = super.save(populateIdIfNecessary(entity)) - + override fun save(entity: S): Mono = super.save(populateIdIfNecessary(entity)) <%_ if (searchEngine === 'couchbase') { _%> fun search(indexName: String, request: String, pageable: Pageable): Flux { val searchQuery = SearchQuery(indexName, queryString(request)) - .limit(pageable.pageSize) - .skip(pageable.offset as Int) + .limit(pageable.getPageSize()) + .skip((int) pageable.getOffset()) return search(searchQuery) } - override fun search(indexName: String, request: String): Flux { + override fun search(indexName: String, request: String,): Flux { val searchQuery = SearchQuery(indexName, queryString(request)) return search(searchQuery) } + <%# TODO verify this #%> fun queryString(request: String): AbstractFtsQuery { - val ids = LinkedList(); - var req = request - req.split(" ") - .filter { it.indexOf("id:") == 0 } - .map { - ids.add(it.substring(3)) - req = req.replace(r, "").replaceAll("[ ]+", " ").trim() + val ids = LinkedList() + + request.split(" ").forEach { + if (r.indexOf("id:") == 0) { + ids.add(r.substring(3)) + request = request.replace(r, "").replaceAll("[ ]+", " ").trim() } - val queryString = SearchQuery.queryString(req) - if (ids.size != 0) { - val docIdQuery = SearchQuery.docId(ids.mapToTypedArray { it as String }) - if (!request.isEmpty) { + } + + val queryString = SearchQuery.queryString(request) + if (ids.size() != 0) { + val docIdQuery = SearchQuery.docId(ids.toArray(String[0])) + if (!request.isEmpty()) { return SearchQuery.conjuncts(queryString, docIdQuery) } return docIdQuery @@ -129,26 +128,26 @@ class CustomReactiveN1qlCouchbaseRepository( .flatMap(AsyncSearchQueryResult::hits) .map(SearchQueryRow::id) return Flux.from(RxReactiveStreams.toPublisher(resultIdObservable)) - .map { it as ID } + .map{ it as ID } .flatMap(this::findById) } <%_ } _%> /** - * Add generated ID to entity if not already set. - * - * @param entity the entity to update. - * @return entity with ID set. - */ - private fun populateIdIfNecessary(entity: S): S { - if (entityInformation.getId(entity) != null) { + * Add generated ID to entity if not already set. + * + * @param entity the entity to update. + * @return entity with ID set. + */ + private fun populateIdIfNecessary(entity: S): S { + if (getEntityInformation().getId(entity) != null) { return entity } setId(entity, template.getGeneratedId(entity)) return entity } - private fun setId(entity: S, generatedId: String) { - persistentEntity.getPropertyAccessor(entity).setProperty(persistentEntity.idProperty, generatedId) + private fun setId(entity: S, generatedId: String) { + persistentEntity.getPropertyAccessor(entity).setProperty(persistentEntity.getIdProperty(), generatedId) } } diff --git a/generators/server/templates/src/main/kotlin/package/repository/PersistenceAuditEventRepository.kt.ejs b/generators/server/templates/src/main/kotlin/package/repository/PersistenceAuditEventRepository.kt.ejs deleted file mode 100644 index 277ec2bd2..000000000 --- a/generators/server/templates/src/main/kotlin/package/repository/PersistenceAuditEventRepository.kt.ejs +++ /dev/null @@ -1,162 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.repository - -import <%= packageName %>.domain.PersistentAuditEvent -<%_ if (!reactive) { _%> -import org.springframework.data.domain.Page -<%_ } _%> -import org.springframework.data.domain.Pageable - -<%_ if (databaseType === 'sql' && !reactive) { _%> -import org.springframework.data.jpa.repository.JpaRepository -<%_ } _%> -<%_ if (databaseType === 'sql' && reactive) { _%> -import org.springframework.data.r2dbc.core.DatabaseClient -import org.springframework.data.r2dbc.core.asType -import org.springframework.data.r2dbc.query.Criteria -import org.springframework.data.r2dbc.repository.Query -import org.springframework.data.r2dbc.repository.R2dbcRepository -import org.springframework.data.util.Pair -import org.springframework.stereotype.Repository -<%_ } _%> -<%_ if (databaseType === 'mongodb') { _%> -import org.springframework.data.mongodb.repository.<% if (reactive) { %>Reactive<% } %>MongoRepository -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import org.neo4j.springframework.data.repository.<% if (reactive) { %>Reactive<% } %>Neo4jRepository -<%_ } _%> -<%_ if (reactive) { _%> -import reactor.core.publisher.Flux -import reactor.core.publisher.Mono -<%_ } _%> -import java.time.Instant -<%_ if (databaseType === 'sql' && reactive) { _%> -import java.time.LocalDateTime -import java.time.ZoneOffset -<%_ } _%> - -/** - * Spring Data <% if (databaseType === 'sql' && !reactive) { %>JPA<% } else if (databaseType === 'sql' && reactive) { %>R2DBC<% } else if (databaseType === 'mongodb') { %>MongoDB<% } else if (databaseType === 'couchbase') { %>Couchbase<% } else if (databaseType === 'neo4j') { %>Neo4j<% } %> for the [PersistentAuditEvent] entity. - */ -<%_ if (databaseType === 'sql' && reactive) { _%> -@Repository -interface PersistenceAuditEventRepository: R2dbcRepository, PersistenceAuditEventRepositoryInternal { - - @Query("INSERT INTO <%= jhiTablePrefix %>_persistent_audit_evt_data VALUES(:eventId, :name, :value)") - fun savePersistenceAuditEventData(eventId: Long, name: String, value: String): Mono -} - -interface PersistenceAuditEventRepositoryInternal { -<%_ } else { _%> -interface PersistenceAuditEventRepository : <% if (reactive) { %>Reactive<% } %><% if (databaseType === 'sql') { %>JpaRepository<% } %><% if (databaseType === 'mongodb') { %>MongoRepository<% } %><% if (databaseType === 'neo4j') { %>Neo4jRepository<% } %><% if (databaseType === 'couchbase') { %>N1qlCouchbaseRepository<% } %><% if (databaseType === 'mongodb' || databaseType === 'couchbase' || databaseType === 'neo4j') { %><% } %> { -<%_ } _%> - - fun findByPrincipal(principal: String): <% if (reactive) { %>Flux<% } else { %>List<% } %> - - <%_ if (!reactive) { _%> - fun findByPrincipalAndAuditEventDateAfterAndAuditEventType( - principal: String, - after: Instant, - type: String - ): List - <%_ } _%> - - fun findAllByAuditEventDateBetween( - fromDate: Instant, - toDate: Instant, - pageable: Pageable - ): <% if (reactive) { %>Flux<% } else { %>Page<% } %> - - fun findByAuditEventDateBefore(before: Instant): <% if (reactive) { %>Flux<% } else { %>List<% } %> - <%_ if (reactive) { _%> - - fun findAllBy(pageable: Pageable): Flux - - fun countByAuditEventDateBetween(fromDate: Instant, toDate: Instant): Mono - <%_ } _%> -} -<%_ if (databaseType === 'sql' && reactive) { _%> - -class PersistenceAuditEventRepositoryInternalImpl(val databaseClient: DatabaseClient): PersistenceAuditEventRepositoryInternal { - - override fun findByPrincipal(principal: String) = - findAllByCriteria(Criteria.where("principal").`is`(principal)) - - override fun findAllByAuditEventDateBetween(fromDate: Instant, toDate: Instant, pageable: Pageable): Flux { - // LocalDateTime seems to be the only type that is supported across all drivers atm - // See https://github.com/r2dbc/r2dbc-h2/pull/139 https://github.com/mirromutth/r2dbc-mysql/issues/105 - val fromDateLocal = LocalDateTime.ofInstant(fromDate, ZoneOffset.UTC) - val toDateLocal = LocalDateTime.ofInstant(toDate, ZoneOffset.UTC) - val criteria = Criteria - .where("event_date").greaterThan(fromDateLocal) - .and("event_date").lessThan(toDateLocal) - return findAllFromSpec(select().matching(criteria).page(pageable)) - } - - override fun findByAuditEventDateBefore(before: Instant): Flux{ - // LocalDateTime seems to be the only type that is supported across all drivers atm - // See https://github.com/r2dbc/r2dbc-h2/pull/139 https://github.com/mirromutth/r2dbc-mysql/issues/105 - val beforeLocal = LocalDateTime.ofInstant(before, ZoneOffset.UTC) - return findAllByCriteria(Criteria.where("event_date").lessThan(beforeLocal)) - } - - override fun findAllBy(pageable: Pageable): Flux = - findAllFromSpec(select().page(pageable)) - - override fun countByAuditEventDateBetween(fromDate: Instant, toDate: Instant): Mono { - // LocalDateTime seems to be the only type that is supported across all drivers atm - // See https://github.com/r2dbc/r2dbc-h2/pull/139 https://github.com/mirromutth/r2dbc-mysql/issues/105 - val fromDateLocal = LocalDateTime.ofInstant(fromDate, ZoneOffset.UTC); - val toDateLocal = LocalDateTime.ofInstant(toDate, ZoneOffset.UTC); - return databaseClient.execute("SELECT COUNT(DISTINCT event_id) FROM <%= jhiTablePrefix %>_persistent_audit_event " + - "WHERE event_date > :fromDate AND event_date < :toDate") - .bind("fromDate", fromDateLocal) - .bind("toDate", toDateLocal) - .asType() - .fetch() - .one() - } - - private fun findAllByCriteria(criteria: Criteria) = - findAllFromSpec(select().matching(criteria)) - - private fun select() = databaseClient.select().from(PersistentAuditEvent::class.java) - - private fun findAllFromSpec(spec: DatabaseClient.TypedSelectSpec): Flux = - spec.`as`(PersistentAuditEvent::class.java).all() - .flatMap {event -> - findAllEventData(event.id!!) - .map { - event.data = it - event - } - } - - - private fun findAllEventData(id: Long): Mono> = databaseClient.select().from("<%= jhiTablePrefix %>_persistent_audit_evt_data") - .project("name", "value") - .matching(Criteria.where("event_id").`is`(id)) - .map { row -> - Pair.of(row.get("name", String::class.java) ?: "", row.get("value", String::class.java) ?: "") - } - .all() - .collectMap(Pair::getFirst, Pair::getSecond) -} -<%_ } _%> diff --git a/generators/server/templates/src/main/kotlin/package/repository/PersistentTokenRepository.kt.ejs b/generators/server/templates/src/main/kotlin/package/repository/PersistentTokenRepository.kt.ejs index f8d7a8c4c..a59a0e3fb 100644 --- a/generators/server/templates/src/main/kotlin/package/repository/PersistentTokenRepository.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/repository/PersistentTokenRepository.kt.ejs @@ -19,10 +19,20 @@ package <%= packageName %>.repository <%_ if (databaseType === 'cassandra') { _%> -import com.datastax.driver.core.BatchStatement -import com.datastax.driver.core.Session -import com.datastax.driver.mapping.MappingManager - +import com.datastax.oss.driver.api.core.CqlIdentifier +import com.datastax.oss.driver.api.core.CqlSession +import com.datastax.oss.driver.api.core.cql.BatchStatement +import com.datastax.oss.driver.api.core.cql.BatchStatementBuilder +import com.datastax.oss.driver.api.core.cql.BoundStatementBuilder +import com.datastax.oss.driver.api.core.cql.DefaultBatchType +import com.datastax.oss.driver.api.core.cql.PreparedStatement +import com.datastax.oss.driver.api.core.cql.ResultSet +import com.datastax.oss.driver.api.mapper.annotations.Dao +import com.datastax.oss.driver.api.mapper.annotations.DaoFactory +import com.datastax.oss.driver.api.mapper.annotations.DaoKeyspace +import com.datastax.oss.driver.api.mapper.annotations.Delete +import com.datastax.oss.driver.api.mapper.annotations.Mapper +import com.datastax.oss.driver.api.mapper.annotations.Select <%_ } _%> import <%= packageName %>.domain.PersistentToken import <%= packageName %>.domain.<%= asEntity('User') %> @@ -35,8 +45,9 @@ import org.springframework.data.jpa.repository.JpaRepository <%_ if (databaseType === 'mongodb') { _%> import org.springframework.data.mongodb.repository.MongoRepository <%_ } _%><%_ if (databaseType === 'neo4j') { _%> -import org.neo4j.springframework.data.repository.Neo4jRepository +import org.springframework.data.neo4j.repository.Neo4jRepository <%_ } if (databaseType === 'cassandra') { _%> +import org.springframework.boot.autoconfigure.cassandra.CassandraProperties import org.springframework.stereotype.Repository import javax.validation.ConstraintViolationException @@ -51,17 +62,20 @@ import java.util.Optional import <%= packageName %>.config.ID_DELIMITER <%_ } _%> -<% if (databaseType === 'sql') { %>/** +/** +<%_ if (databaseType === 'sql') { _%> * Spring Data JPA repository for the [PersistentToken] entity. - */<% } %><% if (databaseType === 'mongodb') { %>/** +<%_ } else if (databaseType === 'mongodb') { _%> * Spring Data MongoDB repository for the [PersistentToken] entity. - */<% } %><% if (databaseType === 'couchbase') { %>/** +<%_ } else if (databaseType === 'couchbase') { _%> * Spring Data Couchbase repository for the [PersistentToken] entity. - */<% } %><% if (databaseType === 'cassandra') { %>/** +<%_ } else if (databaseType === 'cassandra') { _%> * Cassandra repository for the [PersistentToken] entity. - */<% } %><% if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') { %> +<%_ } _%> + */ + <%_ if (['sql', 'mongodb', 'neo4j', 'couchbase'].includes(databaseType)) { _%> interface PersistentTokenRepository : <% if (databaseType === 'sql') { %>JpaRepository<% } %><% if (databaseType === 'mongodb') { %>MongoRepository<% } %><% if (databaseType === 'neo4j') { %>Neo4jRepository<% } %><% if (databaseType === 'couchbase') { %>N1qlCouchbaseRepository<% } %> { -<% if (databaseType === 'couchbase') { %> + <%_ if (databaseType === 'couchbase') { _%> fun findBySeries(series: String): Optional { return findById(PersistentToken.PREFIX + ID_DELIMITER + series) } @@ -72,15 +86,20 @@ interface PersistentTokenRepository : <% if (databaseType === 'sql') { %>JpaRepo fun findByUser(user: User): List = findByLogin(user.login) - fun findByLogin(login: String): List<% } else { %> - fun findByUser(user: User): List<% } %> + fun findByLogin(login: String): List + <%_ } else { _%> + fun findByUser(user: User): List + <%_ } _%> fun findByTokenDateBefore(localDate: LocalDate): List -}<% } else if (databaseType === 'cassandra') { %> +} +<%_ } else if (databaseType === 'cassandra') { _%> @Repository -class PersistentTokenRepository (private val session: Session, private val validator: Validator) { +class PersistentTokenRepository (private val session: CqlSession, private val validator: Validator, cassandraProperties: CassandraProperties) { + + private val persistentTokenMapper = PersistentTokenMapperBuilder(session).build() + private val persistentTokenDao = persistentTokenMapper.persistentTokenDao(CqlIdentifier.fromCql(cassandraProperties.keyspaceName)) - private val mapper = MappingManager(session).mapper(PersistentToken::class.java) private val findPersistentTokenSeriesByUserIdStmt = session.prepare( "SELECT persistent_token_series " + @@ -105,17 +124,16 @@ class PersistentTokenRepository (private val session: Session, private val valid ) fun findById(presentedSeries: String): Optional = - Optional.ofNullable(mapper.get(presentedSeries)) + Optional.ofNullable(persistentTokenDao.get(presentedSeries)) fun findByUser( user: <%= asEntity('User') %>): MutableList { - val stmt = findPersistentTokenSeriesByUserIdStmt.bind() - stmt.setString("user_id", user.id) - val rs = session.execute(stmt) + val statementBuilder = findPersistentTokenSeriesByUserIdStmt.boundStatementBuilder() + statementBuilder.setString("user_id", user.id) + val rs = session.execute(statementBuilder.build()) return rs.all().asSequence() - .map { row -> - val token = row.getString("persistent_token_series") - mapper.get(token) - } + .map { row -> row.getString("persistent_token_series") } + .filterNotNull() + .map { persistentTokenDao.get(it) } .toMutableList() } @@ -124,31 +142,48 @@ class PersistentTokenRepository (private val session: Session, private val valid if (violations != null && !violations.isEmpty()) { throw ConstraintViolationException(violations) } - val batch = BatchStatement() - batch.add( + val batch = BatchStatement.builder(DefaultBatchType.LOGGED) + batch.addStatement( insertPersistentTokenStmt.bind() .setString("series", token.series) - .setTimestamp("token_date", token.tokenDate) + .setInstant("token_date", token.tokenDate) .setString("user_agent", token.userAgent) .setString("token_value", token.tokenValue) .setString("login", token.login) .setString("user_id", token.userId) .setString("ip_address", token.ipAddress) ) - batch.add( + batch.addStatement( insertPersistentTokenSeriesByUserIdStmt.bind() .setString("user_id", token.userId) .setString("persistent_token_series", token.series) ) - session.execute(batch) + session.execute(batch.build()) } fun delete(token: PersistentToken) { - mapper.delete(token) + persistentTokenDao.delete(token) session.execute( deletePersistentTokenSeriesByUserIdStmt.bind() .setString("user_id", token.userId) .setString("persistent_token_series", token.series) ) } -}<% } %> +} + +@Mapper +interface PersistentTokenMapper { + @DaoFactory + fun persistentTokenDao(@DaoKeyspace keyspace: CqlIdentifier): PersistentTokenDao +} + +@Dao +interface PersistentTokenDao { + + @Select + fun get(presentedSeries: String): PersistentToken + + @Delete + fun delete(token: PersistentToken) +} +<%_ } _%> diff --git a/generators/server/templates/src/main/kotlin/package/repository/reactive/ReactiveN1qlCouchbaseRepository.kt.ejs b/generators/server/templates/src/main/kotlin/package/repository/ReactiveN1qlCouchbaseRepository.kt.ejs similarity index 72% rename from generators/server/templates/src/main/kotlin/package/repository/reactive/ReactiveN1qlCouchbaseRepository.kt.ejs rename to generators/server/templates/src/main/kotlin/package/repository/ReactiveN1qlCouchbaseRepository.kt.ejs index c1fe86692..544639726 100644 --- a/generators/server/templates/src/main/kotlin/package/repository/reactive/ReactiveN1qlCouchbaseRepository.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/repository/ReactiveN1qlCouchbaseRepository.kt.ejs @@ -1,7 +1,7 @@ <%# Copyright 2013-2020 the original author or authors from the JHipster project. - This file is part of the JHipster project, see https://jhipster.github.io/ +This file is part of the JHipster project, see https://jhipster.github.io/ for more information. Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,20 +27,21 @@ import reactor.core.publisher.Mono import java.io.Serializable /** - * Couchbase specific [org.springframework.data.repository.Repository] interface uses N1QL for all requests. + * Couchbase specific {@link org.springframework.data.repository.Repository} interface uses N1QL for all requests. */ @NoRepositoryBean -interface ReactiveN1qlCouchbaseRepository : ReactiveCouchbaseSortingRepository { +interface ReactiveN1qlCouchbaseRepository: ReactiveCouchbaseSortingRepository() { @Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter}") - override fun findAll(): Flux + fun findAll(): Flux @Query("SELECT count(*) FROM #{#n1ql.bucket} WHERE #{#n1ql.filter}") - override fun count(): Mono + fun count(): Mono @Query("DELETE FROM #{#n1ql.bucket} WHERE #{#n1ql.filter} returning #{#n1ql.fields}") - fun removeAll(): Flux + fun removeAll(): Flux - @JvmDefault - override fun deleteAll(): Mono = removeAll().then() + default fun deleteAll(): Mono { + return removeAll().then() + } } diff --git a/generators/server/templates/src/main/kotlin/package/repository/UserRepository.kt.ejs b/generators/server/templates/src/main/kotlin/package/repository/UserRepository.kt.ejs index 1fb07c629..40551c441 100644 --- a/generators/server/templates/src/main/kotlin/package/repository/UserRepository.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/repository/UserRepository.kt.ejs @@ -24,15 +24,35 @@ import <%= packageName %>.domain.Authority import <%= packageName %>.domain.<%= asEntity('User') %> <%_ if (databaseType === 'cassandra') { _%> -import com.datastax.driver.core.BatchStatement -import com.datastax.driver.core.BoundStatement -import com.datastax.driver.core.PreparedStatement -import com.datastax.driver.core.Session +import com.datastax.oss.driver.api.core.CqlIdentifier <%_ if (!reactive) { _%> -import com.datastax.driver.mapping.MappingManager - <%_ } else { _%> -import com.datastax.driver.core.querybuilder.Insert -import com.datastax.driver.core.querybuilder.QueryBuilder +import com.datastax.oss.driver.api.core.CqlSession +import com.datastax.oss.driver.api.core.PagingIterable + <%_ } _%> +import com.datastax.oss.driver.api.core.cql.BatchStatement +import com.datastax.oss.driver.api.core.cql.BatchStatementBuilder +import com.datastax.oss.driver.api.core.cql.BoundStatement + <%_ if (!reactive) { _%> +import com.datastax.oss.driver.api.core.cql.BoundStatementBuilder + <%_ } _%> +import com.datastax.oss.driver.api.core.cql.DefaultBatchType +import com.datastax.oss.driver.api.core.cql.PreparedStatement + <%_ if (reactive) { _%> +import com.datastax.oss.driver.api.core.cql.SimpleStatement + <%_ } _%> + <%_ if (!reactive) { _%> +import com.datastax.oss.driver.api.core.cql.ResultSet +import com.datastax.oss.driver.api.mapper.annotations.Dao +import com.datastax.oss.driver.api.mapper.annotations.DaoFactory +import com.datastax.oss.driver.api.mapper.annotations.DaoKeyspace +import com.datastax.oss.driver.api.mapper.annotations.Delete +import com.datastax.oss.driver.api.mapper.annotations.Insert +import com.datastax.oss.driver.api.mapper.annotations.Mapper +import com.datastax.oss.driver.api.mapper.annotations.Select + <%_ } _%> + <%_ if (reactive) { _%> +import com.datastax.oss.driver.api.querybuilder.QueryBuilder +import com.datastax.oss.driver.api.querybuilder.insert.RegularInsert <%_ } _%> <%_ } _%> <%_ if (searchEngine === 'couchbase') { _%> @@ -55,18 +75,24 @@ import org.springframework.data.domain.Pageable import org.springframework.data.jpa.repository.EntityGraph import org.springframework.data.jpa.repository.JpaRepository <%_ } else { _%> -import org.springframework.data.r2dbc.core.DatabaseClient -import org.springframework.data.r2dbc.core.ReactiveDataAccessStrategy -import org.springframework.data.r2dbc.query.Criteria +import org.springframework.r2dbc.core.DatabaseClient +import org.springframework.data.r2dbc.convert.R2dbcConverter +import org.springframework.data.r2dbc.core.R2dbcEntityTemplate import org.springframework.data.r2dbc.repository.Query import org.springframework.data.r2dbc.repository.R2dbcRepository +import org.springframework.data.relational.core.sql.Column +import org.springframework.data.relational.core.sql.Expression +import org.springframework.data.relational.core.sql.Table + +import org.springframework.data.relational.core.query.Criteria.where +import org.springframework.data.relational.core.query.Query.query <%_ } _%> <%_ } _%> <%_ if (databaseType === 'mongodb') { _%> import org.springframework.data.mongodb.repository.<% if (reactive) { %>Reactive<% } %>MongoRepository <%_ } _%> <%_ if (databaseType === 'neo4j') { _%> -import org.neo4j.springframework.data.repository.<% if (reactive) { %>Reactive<% } %>Neo4jRepository +import org.springframework.data.neo4j.repository.<% if (reactive) { %>Reactive<% } %>Neo4jRepository <%_ } _%> <%_ if (reactive && databaseType === 'cassandra') { _%> import org.springframework.data.cassandra.ReactiveResultSet @@ -77,6 +103,9 @@ import org.springframework.data.cassandra.core.mapping.CassandraPersistentEntity <%_ } _%> import org.springframework.stereotype.Repository <%_ if (databaseType === 'cassandra') { _%> + <%_ if (!reactive) { _%> +import org.springframework.boot.autoconfigure.cassandra.CassandraProperties + <%_ } _%> import org.springframework.util.StringUtils <%_ } _%> @@ -103,6 +132,9 @@ import java.time.LocalDateTime import java.util.Optional import java.util.stream.Collectors <%_ } _%> +<%_ if (user.primaryKey.type === 'UUID') { _%> +import java.util.UUID +<%_ } _%> <%_ if (databaseType !== 'cassandra' && !(databaseType === 'sql' && reactive) && authenticationType !== 'oauth2') { _%> import java.time.Instant <%_ } _%> @@ -110,25 +142,24 @@ import java.time.Instant import <%= packageName %>.config.ID_DELIMITER <% } %> /** - * Spring Data <% if (databaseType === 'sql' && !reactive) { %>JPA<% } else if (databaseType === 'sql' && reactive) { %>R2DBC<% } else if (databaseType === 'mongodb') { %>MongoDB<% } else if (databaseType === 'couchbase') { %>Couchbase<% } else if (databaseType === 'cassandra') { %>Cassandra<% } else if (databaseType === 'neo4j') { %>Neo4j RX<% } %> repository for the [<%= asEntity('User') %>] entity. + * Spring Data <% if (databaseType === 'sql' && !reactive) { %>JPA<% } else if (databaseType === 'sql' && reactive) { %>R2DBC<% } else if (databaseType === 'mongodb') { %>MongoDB<% } else if (databaseType === 'couchbase') { %>Couchbase<% } else if (databaseType === 'cassandra') { %>Cassandra<% } else if (databaseType === 'neo4j') { %>Neo4j<% } %> repository for the {@link <%= asEntity('User') %>} entity. */ <%_ - let optionalOrMono = 'Optional'; - if (reactive) { - optionalOrMono = 'Mono'; - } + let optionalOrMono = reactive ? 'Mono' : 'Optional'; + let listOrFlux = reactive ? 'Flux' : 'List'; _%> <%_ if ((databaseType === 'sql' && !reactive) || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') { _%> @Repository -interface UserRepository : <% if (databaseType === 'sql') { %>JpaRepository<<%= asEntity('User') %>, <% if (authenticationType === 'oauth2') { %>String<% } else { %>Long<% } %>><% } %><% if (reactive) { %>Reactive<% } %><% if (databaseType === 'mongodb') { %>MongoRepository<<%= asEntity('User') %>, String><% } %><% if (databaseType === 'neo4j') { %>Neo4jRepository<<%= asEntity('User') %>, String><% } %><% if (databaseType === 'couchbase') { %>N1qlCouchbaseRepository<<%= asEntity('User') %>, String><%if (searchEngine === 'couchbase') { %>, SearchCouchbaseRepository<<%= asEntity('User') %>, String><% } } %> { +interface UserRepository : <% if (databaseType === 'sql') { %>JpaRepository<<%= asEntity('User') %>, <%= user.primaryKey.type %>><% } %><% if (reactive) { %>Reactive<% } %><% if (databaseType === 'mongodb') { %>MongoRepository<<%= asEntity('User') %>, String><% } %><% if (databaseType === 'neo4j') { %>Neo4jRepository<<%= asEntity('User') %>, String><% } %><% if (databaseType === 'couchbase') { %>N1qlCouchbaseRepository<<%= asEntity('User') %>, String><%if (searchEngine === 'couchbase') { %>, SearchCouchbaseRepository<<%= asEntity('User') %>, String><% } } %> { <%_ if (authenticationType !== 'oauth2') { _%> fun findOneByActivationKey(activationKey: String): <%= optionalOrMono %><<%= asEntity('User') %>> <%_ } _%> <%_ if (authenticationType !== 'oauth2') { _%> - fun findAllByActivatedIsFalseAndActivationKeyIsNotNullAndCreatedDateBefore(dateTime: Instant): <% if (reactive) { %>Flux<% } else { %>List<% } %><<%= asEntity('User') %>> + fun findAllByActivatedIsFalseAndActivationKeyIsNotNullAndCreatedDateBefore(dateTime: Instant): <%= listOrFlux %><<%= asEntity('User') %>> <%_ } _%> + <%_ if (authenticationType !== 'oauth2') { _%> fun findOneByResetKey(resetKey: String): <%= optionalOrMono %><<%= asEntity('User') %>> @@ -162,8 +193,7 @@ interface UserRepository : <% if (databaseType === 'sql') { %>JpaRepository<<%= <%_ if (databaseType === 'neo4j') { _%> <% if (!reactive) { %>// See https://github.com/neo4j/sdn-rx/issues/51<% } %> - <<%= asEntity('User') %>> findAll(): <% if (reactive) { %>Flux<% } else { %>List<% } %> - + fun findAll(): <%= listOrFlux %><<%= asEntity('User') %>> <%_ } _%> <%_ if (databaseType === 'sql') { _%> @@ -182,11 +212,17 @@ interface UserRepository : <% if (databaseType === 'sql') { %>JpaRepository<<%= <%_ } _%> <%_ } _%> - fun findAllByLoginNot(pageable: Pageable, login: String): <% if (reactive) { %>Flux<% } else { %>Page<% } %><<%= asEntity('User') %>> - <%_ if (reactive) { _%> + <% if (reactive) { %> + fun findAllByIdNotNull(pageable: Pageable): Flux<<%= asEntity('User') %>> + + fun findAllByIdNotNullAndActivatedIsTrue(pageable: Pageable): Flux<<%= asEntity('User') %>> + + override fun count(): Mono + <% } else { %> + + fun findAllByIdNotNullAndActivatedIsTrue(pageable: Pageable): Page<<%= asEntity('User') %>> + <% } %> - fun countAllByLoginNot(anonymousUser: String): Mono - <%_ } _%> <%_ if (cacheManagerIsAvailable === true) { _%> companion object { @@ -202,27 +238,26 @@ interface UserRepository : <% if (databaseType === 'sql') { %>JpaRepository<<%= interface UserRepository: R2dbcRepositoryString<% } else { %>Long<% } %>>, UserRepositoryInternal { <%_ if (authenticationType !== 'oauth2') { _%> - @Query("SELECT * FROM <%= jhiTablePrefix %>_user WHERE activation_key = :activationKey") fun findOneByActivationKey(activationKey: String): Mono - @Query("SELECT * FROM <%= jhiTablePrefix %>_user WHERE activated = false AND activation_key IS NOT NULL AND created_date < :dateTime") fun findAllByActivatedIsFalseAndActivationKeyIsNotNullAndCreatedDateBefore(dateTime: LocalDateTime): Flux - @Query("SELECT * FROM <%= jhiTablePrefix %>_user WHERE reset_key = :resetKey") fun findOneByResetKey(resetKey: String): Mono - @Query("SELECT * FROM <%= jhiTablePrefix %>_user WHERE LOWER(email) = LOWER(:email)") fun findOneByEmailIgnoreCase(email: String): Mono <%_ } _%> - @Query("SELECT * FROM <%= jhiTablePrefix %>_user WHERE login = :login") + fun findOneByLogin(login: String): Mono - @Query("SELECT COUNT(DISTINCT id) FROM <%= jhiTablePrefix %>_user WHERE login != :anonymousUser") - fun countAllByLoginNot(anonymousUser: String): Mono + fun findAllByIdNotNull(pageable: Pageable): Flux + + fun findAllByIdNotNullAndActivatedIsTrue(pageable: Pageable): Flux + + override fun count(): Mono @Query("INSERT INTO <%= jhiTablePrefix %>_user_authority VALUES(:userId, :authority)") - fun saveUserAuthority(userId: <% if (authenticationType === 'oauth2') { %>String<% } else { %>Long<% } %>, authority: String): Mono + fun saveUserAuthority(userId: <%= user.primaryKey.type %>, authority: String): Mono @Query("DELETE FROM <%= jhiTablePrefix %>_user_authority") fun deleteAllUserAuthorities(): Mono @@ -242,14 +277,13 @@ interface UserRepositoryInternal<% if (authenticationType !== 'oauth2') { %> : D fun findOneWithAuthoritiesByEmailIgnoreCase(email: String): Mono <%_ } _%> - fun findAllByLoginNot(pageable: Pageable, login: String): Flux <%_ if (authenticationType == 'oauth2') { _%> fun create(user: User): Mono <%_ } _%> } -class UserRepositoryInternalImpl(val db: DatabaseClient, val dataAccessStrategy: ReactiveDataAccessStrategy): UserRepositoryInternal { +class UserRepositoryInternalImpl(val db: DatabaseClient, val r2dbcEntityTemplate: R2dbcEntityTemplate, val r2dbcConverter: R2dbcConverter): UserRepositoryInternal { override fun findOneWithAuthoritiesByLogin(login: String): Mono { return findOneWithAuthoritiesBy("login", login); @@ -262,11 +296,11 @@ class UserRepositoryInternalImpl(val db: DatabaseClient, val dataAccessStrategy: <%_ } _%> private fun findOneWithAuthoritiesBy(fieldName: String, fieldValue: Any): Mono { - return db.execute("SELECT * FROM <%= jhiTablePrefix %>_user u LEFT JOIN <%= jhiTablePrefix %>_user_authority ua ON u.id=ua.user_id WHERE u.$fieldName = :$fieldName") + return db.sql("SELECT * FROM <%= jhiTablePrefix %>_user u LEFT JOIN <%= jhiTablePrefix %>_user_authority ua ON u.id=ua.user_id WHERE u.$fieldName = :$fieldName") .bind(fieldName, fieldValue) .map { row, metadata -> return@map Tuples.of( - dataAccessStrategy.getRowMapper(User::class.java).apply(row, metadata), + r2dbcConverter.read(User::class.java, row, metadata), Optional.ofNullable(row.get("authority_name", String::class.java)) ) }.all() @@ -284,22 +318,13 @@ class UserRepositoryInternalImpl(val db: DatabaseClient, val dataAccessStrategy: } } - override fun findAllByLoginNot(pageable: Pageable, login: String): Flux { - return db.select().from(User::class.java) - .matching(Criteria.where("login").not(login)) - .page(pageable) - .`as`(User::class.java) - .all() - } - <%_ if (authenticationType !== 'oauth2') { _%> override fun delete(user: User): Mono { - return db.execute("DELETE FROM <%= jhiTablePrefix %>_user_authority WHERE user_id = :userId") + return db.sql("DELETE FROM <%= jhiTablePrefix %>_user_authority WHERE user_id = :userId") .bind("userId", user.id) .then() - .then(db.delete() - .from(User::class.java) - .matching(Criteria.where("id").`is`(user.id)) + .then(r2dbcEntityTemplate.delete(User::class.java) + .matching(query(where("id").`is`(user.id))).all() .then() ); } @@ -307,28 +332,57 @@ class UserRepositoryInternalImpl(val db: DatabaseClient, val dataAccessStrategy: <%_ } _%> <%_ if (authenticationType === 'oauth2') { _%> override fun create(user: User): Mono { - return db.insert().into(User::class.java).using(user) - .map(dataAccessStrategy.getConverter().populateIdIfNecessary(user)) - .first() + return r2dbcEntityTemplate.into(User::class.java).using(user) .defaultIfEmpty(user) } <%_ } _%> } + +class UserSqlHelper { + fun getColumns(table: Table, columnPrefix: String): MutableList { + val columns = mutableListOf() + columns.add(Column.aliased("id", table, columnPrefix + "_id")) + columns.add(Column.aliased("login", table, columnPrefix + "_login")) + <%_ if (authenticationType !== 'oauth2') { _%> + columns.add(Column.aliased("password_hash", table, columnPrefix + "_password")) + <%_ } _%> + columns.add(Column.aliased("first_name", table, columnPrefix + "_first_name")) + columns.add(Column.aliased("last_name", table, columnPrefix + "_last_name")) + columns.add(Column.aliased("email", table, columnPrefix + "_email")) + columns.add(Column.aliased("activated", table, columnPrefix + "_activated")) + columns.add(Column.aliased("lang_key", table, columnPrefix + "_lang_key")) + columns.add(Column.aliased("image_url", table, columnPrefix + "_image_url")) + <%_ if (authenticationType !== 'oauth2') { _%> + columns.add(Column.aliased("activation_key", table, columnPrefix + "_activation_key")) + columns.add(Column.aliased("reset_key", table, columnPrefix + "_reset_key")) + columns.add(Column.aliased("reset_date", table, columnPrefix + "_reset_date")) + <%_ } _%> + return columns + } +} + + <%_ } else if (databaseType === 'cassandra') { _%> @Repository class UserRepository( - private val session: <% if(reactive) { %>Reactive<% } %>Session, - private val validator: Validator<% if(reactive) { %>, - private val cqlTemplate: ReactiveCassandraTemplate<%_ } %> + <%_ if (reactive) { _%> + private val cqlTemplate: ReactiveCassandraTemplate, + <%_ } _%> + private val session: <% if (reactive) { %>Reactive<% } else { %>Cql<% } %>Session, + <%_ if (!reactive) { _%> + private val validator: Validator<%_ } _%><%_ if (!reactive) { _%>, + private val cassandraProperties: CassandraProperties<% } %> ) { + <%_ if(!reactive) { _%> - private val mapper = MappingManager(session).mapper(User::class.java) - <%_ } _%> - + private val userTokenMapper = UserTokenMapperBuilder(session).build() + private val userDao = userTokenMapper.userTokenDao(CqlIdentifier.fromCql(cassandraProperties.keyspaceName)) + <%_ } else { _%> + private val findAllStmt = session.prepare("SELECT * FROM user")<% if(reactive) { %>.block()<% } %> - + <%_ } _%> private val findOneByActivationKeyStmt = session.prepare( "SELECT id " + "FROM user_by_activation_key " + @@ -410,7 +464,7 @@ class UserRepository( fun findById(id: String): <%= optionalOrMono %><<%= asEntity('User') %>> { <%_ if(!reactive) { _%> - return Optional.ofNullable(mapper.get(id)) + return userDao.get(id) <%_ } else { _%> return cqlTemplate.selectOneById(id, User::class.java) .map { user -> @@ -423,14 +477,12 @@ class UserRepository( } fun findOneByActivationKey(activationKey: String): <%= optionalOrMono %><<%= asEntity('User') %>> { - val stmt = findOneByActivationKeyStmt.bind() - stmt.setString("activation_key", activationKey) + val stmt = findOneByActivationKeyStmt.bind().setString("activation_key", activationKey) return findOneFromIndex(stmt) } fun findOneByResetKey(resetKey: String): <%= optionalOrMono %><<%= asEntity('User') %>> { - val stmt = findOneByResetKeyStmt.bind() - stmt.setString("reset_key", resetKey) + val stmt = findOneByResetKeyStmt.bind().setString("reset_key", resetKey) return findOneFromIndex(stmt) } @@ -438,8 +490,7 @@ class UserRepository( @Cacheable(cacheNames = [USERS_BY_EMAIL_CACHE]) <%_ } _%> fun findOneByEmailIgnoreCase(email: String?): <%= optionalOrMono %><<%= asEntity('User') %>> { - val stmt = findOneByEmailStmt.bind() - stmt.setString("email", email?.toLowerCase()) + val stmt = findOneByEmailStmt.bind().setString("email", email?.toLowerCase()) return findOneFromIndex(stmt) } @@ -447,17 +498,14 @@ class UserRepository( @Cacheable(cacheNames = [USERS_BY_LOGIN_CACHE]) <%_ } _%> fun findOneByLogin(login: String): <%= optionalOrMono %><<%= asEntity('User') %>> { - val stmt = findOneByLoginStmt.bind() - stmt.setString("login", login) + val stmt = findOneByLoginStmt.bind().setString("login", login) return findOneFromIndex(stmt) } - - <%_ if(!reactive) { _%> - fun findAll(): List<<%= asEntity('User') %>> { - return mapper.map(session.execute(findAllStmt.bind())).all() - } + + fun findAll(): <%= listOrFlux %><<%= asEntity('User') %>> { + <%_ if(!reactive) { _%> + return userDao.findAll().all() <%_ } else { _%> - fun findAll(): Flux<<%= asEntity('User') %>> { return cqlTemplate.select(findAllStmt.bind(), User::class.java) .map { user -> if(user.authorities == null) { @@ -465,8 +513,8 @@ class UserRepository( } user } - } <%_ } _%> + } fun save(user: <%= asEntity('User') %>): <% if(reactive) { %>Mono<<% } %><%= asEntity('User') %><% if(reactive) { %>><% } %> { val violations = validator.validate(user) @@ -474,7 +522,7 @@ class UserRepository( throw ConstraintViolationException(violations) } <%_ if(!reactive) { _%> - val oldUser = mapper.get(user.id) + val oldUser = user.id?.let { userDao.get(it) }?.orElse(null) if (oldUser != null) { if (!StringUtils.isEmpty(oldUser.activationKey) && oldUser.activationKey != user.activationKey) { session.execute(deleteByActivationKeyStmt.bind().setString("activation_key", oldUser.activationKey)) @@ -489,33 +537,29 @@ class UserRepository( session.execute(deleteByEmailStmt.bind().setString("email", oldUser.email!!.toLowerCase())) } } - val batch = BatchStatement() - batch.add(mapper.saveQuery(user)) + val batch = BatchStatement.builder(DefaultBatchType.LOGGED) + batch.addStatement(userDao.saveQuery(user)) if (!StringUtils.isEmpty(user.activationKey)) { - batch.add( - insertByActivationKeyStmt.bind() + batch.addStatement(insertByActivationKeyStmt.bind() .setString("activation_key", user.activationKey) .setString("id", user.id) ) } if (!StringUtils.isEmpty(user.resetKey)) { - batch.add( - insertByResetKeyStmt.bind() + batch.addStatement(insertByResetKeyStmt.bind() .setString("reset_key", user.resetKey) .setString("id", user.id) ) } - batch.add( - insertByLoginStmt.bind() + batch.addStatement(insertByLoginStmt.bind() .setString("login", user.login) .setString("id", user.id) ) - batch.add( - insertByEmailStmt.bind() + batch.addStatement(insertByEmailStmt.bind() .setString("email", user.email!!.toLowerCase()) .setString("id", user.id) ) - session.execute(batch) + session.execute(batch.build()) return user <%_ } else { // reactive _%> return this.findById(user.id!!) @@ -536,67 +580,65 @@ class UserRepository( deleteOps } .then( Mono.defer { - val batch = BatchStatement() - batch.add(getInsertStatement(user)) + val batch = BatchStatement.builder(DefaultBatchType.LOGGED) + batch.addStatement(getInsertStatement(user)) if (!StringUtils.isEmpty(user.activationKey)) { - batch.add(insertByActivationKeyStmt.bind() + batch.addStatement(insertByActivationKeyStmt.bind() .setString("activation_key", user.activationKey) .setString("id", user.id)) } if (!StringUtils.isEmpty(user.resetKey)) { - batch.add(insertByResetKeyStmt.bind() + batch.addStatement(insertByResetKeyStmt.bind() .setString("reset_key", user.resetKey) .setString("id", user.id)) } - batch.add(insertByLoginStmt.bind() + batch.addStatement(insertByLoginStmt.bind() .setString("login", user.login) .setString("id", user.id)) - batch.add(insertByEmailStmt.bind() + batch.addStatement(insertByEmailStmt.bind() .setString("email", user.email?.toLowerCase()) .setString("id", user.id)) - session.execute(batch) + session.execute(batch.build()) }) .thenReturn(user); } - private fun getInsertStatement(user: User): Insert { + private fun getInsertStatement(user: User): SimpleStatement { val converter = cqlTemplate.getConverter() val persistentEntity = converter.getMappingContext().getRequiredPersistentEntity(user::class.java) - val toInsert = mutableMapOf() + val toInsert = mutableMapOf() converter.write(user, toInsert, persistentEntity) - val insert = QueryBuilder.insertInto(persistentEntity.getTableName().toCql()) - toInsert.forEach { (key, value) -> insert.value(key, value) } - return insert + val insert = QueryBuilder.insertInto(persistentEntity.getTableName()) + .value("id", QueryBuilder.literal(user.getId())) + toInsert.forEach { (key, value) -> insert.value(key, QueryBuilder.literal(value)) } + return insert.build() <%_ } _%> } fun delete(user: <%= asEntity('User') %>)<% if(reactive) { %>: Mono<% } %> { - val batch = BatchStatement() - batch.add(<% if(!reactive) { %>mapper.deleteQuery(user)<% } else { %>deleteByIdStmt.bind().setString("id", user.id)<% } %>) + val batch = BatchStatement.builder(DefaultBatchType.LOGGED) + batch.addStatement(<% if(!reactive) { %>userDao.deleteQuery(user)<% } else { %>deleteByIdStmt.bind().setString("id", user.id)<% } %>) if (!StringUtils.isEmpty(user.activationKey)) { - batch.add(deleteByActivationKeyStmt.bind().setString("activation_key", user.activationKey)) + batch.addStatement(deleteByActivationKeyStmt.bind().setString("activation_key", user.activationKey)) } if (!StringUtils.isEmpty(user.resetKey)) { - batch.add(deleteByResetKeyStmt.bind().setString("reset_key", user.resetKey)) + batch.addStatement(deleteByResetKeyStmt.bind().setString("reset_key", user.resetKey)) } - batch.add(deleteByLoginStmt.bind().setString("login", user.login)) - batch.add(deleteByEmailStmt.bind().setString("email", user.email!!.toLowerCase())) + batch.addStatement(deleteByLoginStmt.bind().setString("login", user.login)) + batch.addStatement(deleteByEmailStmt.bind().setString("email", user.email!!.toLowerCase())) <%_ if(!reactive) { _%> - session.execute(batch) + session.execute(batch.build()) <%_ } else { _%> - return session.execute(batch).then() + return session.execute(batch.build()).then() <%_ } _%> } <%_ if(!reactive) { _%> private fun findOneFromIndex(stmt: BoundStatement): Optional<<%= asEntity('User') %>> { val rs = session.execute(stmt) - if (rs.isExhausted) { - return Optional.empty() - } - return Optional.ofNullable(rs.one().getString("id")) - .map { id -> Optional.ofNullable(mapper.get(id)) } - .get() + return Optional.ofNullable(rs.one()) + .map { it.getString("id") } + .flatMap { it?.let { userDao.get(it) } } } fun deleteAll() { @@ -635,4 +677,27 @@ class UserRepository( } <%_ } _%> } +<%_ if (!reactive) { _%> +@Dao +interface UserDao { + + @Select + fun get(id: String): Optional + + @Select + fun findAll(): PagingIterable + + @Insert + fun saveQuery(user: User): BoundStatement + + @Delete + fun deleteQuery(user: User): BoundStatement +} + +@Mapper +interface UserTokenMapper { + @DaoFactory + fun userTokenDao(@DaoKeyspace keyspace: CqlIdentifier): UserDao +} + <%_ } _%> <%_ } _%> diff --git a/generators/server/templates/src/main/kotlin/package/repository/rowmapper/UserRowMapper.kt.ejs b/generators/server/templates/src/main/kotlin/package/repository/rowmapper/UserRowMapper.kt.ejs new file mode 100644 index 000000000..e3458f168 --- /dev/null +++ b/generators/server/templates/src/main/kotlin/package/repository/rowmapper/UserRowMapper.kt.ejs @@ -0,0 +1,62 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + +This file is part of the JHipster project, see https://jhipster.github.io/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %>.repository.rowmapper + + +import java.time.Instant +import java.util.function.BiFunction + +import org.springframework.stereotype.Service + +import <%= packageName %>.domain.User +import <%= packageName %>.service.ColumnConverter + +import io.r2dbc.spi.Row + +/** + * Converter between [Row] to [User], with proper type conversions. + */ +@Service +class UserRowMapper(private val converter: ColumnConverter): BiFunction { + /** + * Take a [Row] and a column prefix, and extract all the fields. + * @return the [User] stored in the database. + */ + override fun apply(row: Row, prefix: String): User { + val entity = User() + entity.id = converter.fromRow(row, "${prefix}_id", <%= user.primaryKey.type %>::class.java) + entity.login = converter.fromRow(row, "${prefix}_login", String::class.java) + <%_ if (authenticationType !== 'oauth2') { _%> + entity.password = converter.fromRow(row, "${prefix}_password", String::class.java) + <%_ } _%> + entity.firstName = converter.fromRow(row, "${prefix}_first_name", String::class.java) + entity.lastName = converter.fromRow(row, "${prefix}_last_name", String::class.java) + entity.email = converter.fromRow(row, "${prefix}_email", String::class.java) + entity.activated = converter.fromRow(row, "${prefix}_activated", Boolean::class.java) == true + entity.langKey = converter.fromRow(row, "${prefix}_lang_key", String::class.java) + entity.imageUrl = converter.fromRow(row, "${prefix}_image_url", String::class.java) + <%_ if (authenticationType !== 'oauth2') { _%> + entity.activationKey = converter.fromRow(row, "${prefix}_activation_key", String::class.java) + entity.resetKey = converter.fromRow(row, "${prefix}_reset_key", String::class.java) + entity.resetDate = converter.fromRow(row, "${prefix}_reset_date", Instant::class.java) + <%_ } _%> + return entity + } + +} diff --git a/generators/server/templates/src/main/kotlin/package/security/DomainUserDetailsService.kt.ejs b/generators/server/templates/src/main/kotlin/package/security/DomainUserDetailsService.kt.ejs index 78a296a79..056cf169d 100644 --- a/generators/server/templates/src/main/kotlin/package/security/DomainUserDetailsService.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/security/DomainUserDetailsService.kt.ejs @@ -75,7 +75,7 @@ class DomainUserDetailsService(private val userRepository: UserRepository) : <% private fun createSpringSecurityUser(lowercaseLogin: String, user: <%= asEntity('User') %>) : org.springframework.security.core.userdetails.User { - if (!user.activated) { + if (user.activated == null || user.activated == false) { throw UserNotActivatedException("User $lowercaseLogin was not activated") } val grantedAuthorities = user.authorities.map { SimpleGrantedAuthority(it<% if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j') { %>.name<% } %>) } diff --git a/generators/server/templates/src/main/kotlin/package/security/PersistentTokenRememberMeServices.kt.ejs b/generators/server/templates/src/main/kotlin/package/security/PersistentTokenRememberMeServices.kt.ejs index d8f36c0dc..6dc0f539c 100644 --- a/generators/server/templates/src/main/kotlin/package/security/PersistentTokenRememberMeServices.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/security/PersistentTokenRememberMeServices.kt.ejs @@ -22,16 +22,17 @@ import <%= packageName %>.domain.PersistentToken import <%= packageName %>.repository.PersistentTokenRepository import <%= packageName %>.repository.UserRepository <%_ if (databaseType === 'cassandra') { _%> - -import com.datastax.driver.core.exceptions.DriverException +import com.datastax.oss.driver.api.core.DriverException <%_ } _%> -import io.github.jhipster.config.JHipsterProperties -import io.github.jhipster.security.PersistentTokenCache -import io.github.jhipster.security.RandomUtil +import tech.jhipster.config.JHipsterProperties +import tech.jhipster.security.PersistentTokenCache +import tech.jhipster.security.RandomUtil -import org.slf4j.LoggerFactory<% if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') { %> -import org.springframework.dao.DataAccessException<%}%> +import org.slf4j.LoggerFactory +<%_ if (['sql', 'mongodb', 'neo4j', 'couchbase'].includes(databaseType)) { _%> +import org.springframework.dao.DataAccessException +<%_ } _%> import org.springframework.security.core.Authentication import org.springframework.security.core.userdetails.UserDetails import org.springframework.security.core.userdetails.UsernameNotFoundException @@ -44,12 +45,11 @@ import org.springframework.stereotype.Service import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpServletResponse import java.io.Serializable -<%_ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') { _%> +<%_ if (['sql', 'mongodb', 'neo4j', 'couchbase'].includes(databaseType)) { _%> import java.time.LocalDate -<%_ } _%> -<%_ if (databaseType === 'cassandra') { _%> +<%_ } else if (databaseType === 'cassandra') { _%> +import java.time.Instant import java.time.temporal.ChronoUnit -import java.util.Date <%_ } _%> // Token is valid for one month @@ -120,28 +120,30 @@ class PersistentTokenRememberMeServices( } if (login == null) { - val token = getPersistentToken(cookieTokens)<% if (databaseType === 'sql' || databaseType === 'mongodb') { %> - login = token.user?.login<% } else { %> - login = token.login<%}%> + val token = getPersistentToken(cookieTokens) + <%_ if (databaseType === 'sql' || databaseType === 'mongodb') { _%> + login = token.user?.login + <%_ } else { _%> + login = token.login + <%_ } _%> // Token also matches, so login is valid. Update the token value, keeping the *same* series number. log.debug("Refreshing persistent login token for user '$login', series '${token.series}'") token.apply { - <%_ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') { _%> + <%_ if (['sql', 'mongodb', 'neo4j', 'couchbase'].includes(databaseType)) { _%> tokenDate = LocalDate.now() - <%_ } _%> - <%_ if (databaseType === 'cassandra') { _%> - tokenDate = Date() + <%_ } else if (databaseType === 'cassandra') { _%> + tokenDate = Instant.now() <%_ } _%> tokenValue = RandomUtil.generateRandomAlphanumericString() ipAddress = request.remoteAddr userAgent = request.getHeader("User-Agent") } try { - <% if (databaseType === 'sql') { %>persistentTokenRepository.saveAndFlush(token)<% } else { %>persistentTokenRepository.save(token)<% } %> - <%_ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') { _%> + persistentTokenRepository.save<% if (databaseType === 'sql') { %>AndFlush<% } %>(token) + <%_ if (['sql', 'mongodb', 'neo4j', 'couchbase'].includes(databaseType)) { _%> } catch (e: DataAccessException) { - <%_ } else { _%> + <%_ } else if (databaseType === 'cassandra') { _%> } catch (e: DriverException) { <%_ } _%> log.error("Failed to update token: $e") @@ -176,15 +178,17 @@ class PersistentTokenRememberMeServices( userId = u.id, <%_ } _%> tokenValue = RandomUtil.generateRandomAlphanumericString(), - tokenDate = <% if (databaseType === 'cassandra') { %>Date()<% } else { %>LocalDate.now()<% } %>, + tokenDate = <% if (databaseType === 'cassandra') { %>Instant.now()<% } else { %>LocalDate.now()<% } %>, ipAddress = request.remoteAddr, userAgent = request.getHeader("User-Agent") ) }.orElseThrow { UsernameNotFoundException("User $login was not found in the database") } try { <% if (databaseType === 'sql') { %>persistentTokenRepository.saveAndFlush(token)<% } else { %>persistentTokenRepository.save(token)<% } %> - addCookie(token, request, response)<% if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') { %> - } catch (e: DataAccessException) {<% } else { %> + addCookie(token, request, response) + <%_ if (['sql', 'mongodb', 'neo4j', 'couchbase'].includes(databaseType)) { _%> + } catch (e: DataAccessException) { + <%_ } else if (databaseType === 'cassandra') { _%> } catch (e: DriverException) {<% } %> log.error("Failed to save persistent token $e") } @@ -264,9 +268,9 @@ class PersistentTokenRememberMeServices( if (token.tokenDate!!.plusDays(TOKEN_VALIDITY_DAYS.toLong()).isBefore(LocalDate.now())) { <%_ } _%> <%_ if (databaseType === 'cassandra') { _%> - if (token.tokenDate!!.toInstant() + if (token.tokenDate!! .plus(TOKEN_VALIDITY_DAYS.toLong(), ChronoUnit.DAYS) - .isBefore(Date().toInstant()) + .isBefore(Instant.now()) ) { <%_ } _%> <%_ if (databaseType === 'sql') { _%> diff --git a/generators/server/templates/src/main/kotlin/package/security/SecurityUtils.kt.ejs b/generators/server/templates/src/main/kotlin/package/security/SecurityUtils.kt.ejs index 6d7103804..2ba8e1db2 100644 --- a/generators/server/templates/src/main/kotlin/package/security/SecurityUtils.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/security/SecurityUtils.kt.ejs @@ -135,14 +135,12 @@ fun isAuthenticated(): <% if (!reactive) { %>Boolean<% } else { %>Mono< } /** - * If the current user has a specific authority (security role). - * - * The name of this method comes from the `isUserInRole()` method in the Servlet API + * Checks if the current user has a specific authority. * * @param authority the authority to check. * @return true if the current user has the authority, false otherwise. */ -fun isCurrentUserInRole(authority: String): <% if (!reactive) { %>Boolean<% } else { %>Mono<% } %> { +fun hasCurrentUserThisAuthority(authority: String): <% if (!reactive) { %>Boolean<% } else { %>Mono<% } %> { <%_ if (!reactive) { _%> val authentication = SecurityContextHolder.getContext().authentication diff --git a/generators/server/templates/src/main/kotlin/package/security/jwt/TokenProvider.kt.ejs b/generators/server/templates/src/main/kotlin/package/security/jwt/TokenProvider.kt.ejs index 0341c8aba..3b110806d 100644 --- a/generators/server/templates/src/main/kotlin/package/security/jwt/TokenProvider.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/security/jwt/TokenProvider.kt.ejs @@ -21,7 +21,6 @@ package <%= packageName %>.security.jwt import java.nio.charset.StandardCharsets import java.security.Key import java.util.Date -import javax.annotation.PostConstruct import org.slf4j.LoggerFactory import org.springframework.security.authentication.UsernamePasswordAuthenticationToken @@ -29,10 +28,11 @@ import org.springframework.security.core.Authentication import org.springframework.security.core.authority.SimpleGrantedAuthority import org.springframework.security.core.userdetails.User import org.springframework.stereotype.Component -import org.springframework.util.StringUtils +import org.springframework.util.ObjectUtils -import io.github.jhipster.config.JHipsterProperties +import tech.jhipster.config.JHipsterProperties import io.jsonwebtoken.JwtException +import io.jsonwebtoken.JwtParser import io.jsonwebtoken.Jwts import io.jsonwebtoken.SignatureAlgorithm import io.jsonwebtoken.io.Decoders @@ -50,15 +50,16 @@ class TokenProvider(private val jHipsterProperties: JHipsterProperties) { private var key: Key? = null + private var jwtParser: JwtParser? = null + private var tokenValidityInMilliseconds: Long = 0 private var tokenValidityInMillisecondsForRememberMe: Long = 0 - @PostConstruct - fun init() { + init { val keyBytes: ByteArray val secret = jHipsterProperties.security.authentication.jwt.secret - keyBytes = if (!StringUtils.isEmpty(secret)) { + keyBytes = if (!ObjectUtils.isEmpty(secret)) { log.warn("Warning: the JWT key used is not Base64-encoded. We recommend using the `jhipster.security.authentication.jwt.base64-secret` key for optimum security.") secret.toByteArray(StandardCharsets.UTF_8) } else { @@ -66,6 +67,7 @@ class TokenProvider(private val jHipsterProperties: JHipsterProperties) { Decoders.BASE64.decode(jHipsterProperties.security.authentication.jwt.base64Secret) } this.key = Keys.hmacShaKeyFor(keyBytes) + this.jwtParser = Jwts.parserBuilder().setSigningKey(key).build() this.tokenValidityInMilliseconds = 1000 * jHipsterProperties.security.authentication.jwt.tokenValidityInSeconds this.tokenValidityInMillisecondsForRememberMe = 1000 * jHipsterProperties.security.authentication.jwt .tokenValidityInSecondsForRememberMe @@ -95,27 +97,19 @@ class TokenProvider(private val jHipsterProperties: JHipsterProperties) { } fun getAuthentication(token: String): Authentication { - val claims = Jwts.parserBuilder() - .setSigningKey(key) - .build() - .parseClaimsJws(token) - .body + val claims = jwtParser?.parseClaimsJws(token)?.body - val authorities = claims[AUTHORITIES_KEY].toString().splitToSequence(",") - .mapTo(mutableListOf()) { SimpleGrantedAuthority(it) } + val authorities = claims?.get(AUTHORITIES_KEY)?.toString()?.splitToSequence(",") + ?.filter{ !it.trim().isEmpty() }?.mapTo(mutableListOf()) { SimpleGrantedAuthority(it) } - val principal = User(claims.subject, "", authorities) + val principal = User(claims?.subject, "", authorities) return UsernamePasswordAuthenticationToken(principal, token, authorities) } fun validateToken(authToken: String): Boolean { try { - Jwts.parserBuilder() - .setSigningKey(key) - .build() - .parseClaimsJws(authToken) - + jwtParser?.parseClaimsJws(authToken) return true } catch (e: JwtException) { log.info("Invalid JWT token.") diff --git a/generators/server/templates/src/main/kotlin/package/security/oauth2/AuthorizationHeaderFilter.kt.ejs b/generators/server/templates/src/main/kotlin/package/security/oauth2/AuthorizationHeaderFilter.kt.ejs deleted file mode 100644 index 0696ede07..000000000 --- a/generators/server/templates/src/main/kotlin/package/security/oauth2/AuthorizationHeaderFilter.kt.ejs +++ /dev/null @@ -1,44 +0,0 @@ -<%# -Copyright 2013-2020 the original author or authors from the JHipster project. - -This file is part of the JHipster project, see https://jhipster.github.io/ -for more information. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. --%> -package <%= packageName %>.security.oauth2 - -import com.netflix.zuul.ZuulFilter -import com.netflix.zuul.context.RequestContext -import <%= packageName %>.client.TokenRelayRequestInterceptor -import org.springframework.core.Ordered - -import java.util.Optional - -import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE - -class AuthorizationHeaderFilter(private val headerUtil: AuthorizationHeaderUtil) : ZuulFilter() { - - override fun filterType(): String = PRE_TYPE - - override fun filterOrder(): Int = Ordered.LOWEST_PRECEDENCE - - override fun shouldFilter(): Boolean = true - - override fun run(): Any? { - val ctx = RequestContext.getCurrentContext() - val authorizationHeader = headerUtil.getAuthorizationHeader() - ctx.addZuulRequestHeader(TokenRelayRequestInterceptor.AUTHORIZATION, authorizationHeader) - return null - } -} diff --git a/generators/server/templates/src/main/kotlin/package/security/oauth2/CookieCollection.kt.ejs b/generators/server/templates/src/main/kotlin/package/security/oauth2/CookieCollection.kt.ejs deleted file mode 100644 index d27ad5ae3..000000000 --- a/generators/server/templates/src/main/kotlin/package/security/oauth2/CookieCollection.kt.ejs +++ /dev/null @@ -1,113 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.security.oauth2 - -import javax.servlet.http.Cookie - -class CookieCollection : Collection { - - private val cookieMap = mutableMapOf() - - constructor() - - constructor(vararg cookies: Cookie) : this(cookies.asList()) - - constructor(cookies: Collection) { - addAll(cookies) - } - - override val size: Int - get() = cookieMap.size - - override fun isEmpty(): Boolean = cookieMap.isEmpty() - - override fun contains(element: Cookie) = cookieMap.containsValue(element) - - fun contains(element: String) = cookieMap.containsKey(element) - - override fun containsAll(elements: Collection) = containsAllStringOrCookie(elements) - - fun containsAll(elements: List) = containsAllStringOrCookie(elements) - - fun containsAllStringOrCookie(elements: Collection): Boolean { - for (o in elements) { - if (!contains(o)) { - return false - } - } - return true - } - - override fun iterator(): Iterator = cookieMap.values.iterator() - - fun toArray(): Array = cookieMap.values.toTypedArray() - - fun add(cookie: Cookie): Boolean { - cookieMap[cookie.name] = cookie - return true - } - - fun remove(o: String) = cookieMap.remove(o) != null - - fun remove(o: Cookie) = cookieMap.remove(o.name) != null - - operator fun get(name: String): Cookie? = cookieMap[name] - - fun addAll(collection: Collection): Boolean { - var result = false - for (cookie in collection) { - result = result or add(cookie) - } - return result - } - - fun removeAll(collection: List) = removeAllValues(collection) - - fun removeAll(collection: Collection) = removeAllValues(collection) - - fun removeAllValues(collection: Collection): Boolean { - var result = false - for (cookie in collection) { - when (cookie) { - is String -> result = result or remove(cookie) - is Cookie -> result = result or remove(cookie) - } - } - return result - } - - fun retainAll(collection: Collection) = retainAllValues(collection) - - fun retainAll(collection: List) = retainAllValues(collection) - - fun retainAllValues(collection: Collection): Boolean { - var result = false - val it = cookieMap.entries.iterator() - while (it.hasNext()) { - val e = it.next() - if (!collection.contains(e.key) && !collection.contains(e.value)) { - it.remove() - result = true - } - } - return result - } - - fun clear() = cookieMap.clear() -} diff --git a/generators/server/templates/src/main/kotlin/package/security/oauth2/CookieTokenExtractor.kt.ejs b/generators/server/templates/src/main/kotlin/package/security/oauth2/CookieTokenExtractor.kt.ejs deleted file mode 100644 index 450939a08..000000000 --- a/generators/server/templates/src/main/kotlin/package/security/oauth2/CookieTokenExtractor.kt.ejs +++ /dev/null @@ -1,47 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.security.oauth2 - -import org.springframework.security.oauth2.provider.authentication.BearerTokenExtractor - -import javax.servlet.http.HttpServletRequest - -/** - * Extracts the access token from a cookie. - * Falls back to a [BearerTokenExtractor] extracting information from the Authorization header, if no - * cookie was found. - */ -class CookieTokenExtractor : BearerTokenExtractor() { - /** - * Extract the JWT access token from the request, if present. - * If not, then it falls back to the [BearerTokenExtractor] behaviour. - * - * @param request the request containing the cookies. - * @return the extracted JWT token; or `null`. - */ - override fun extractToken(request: HttpServletRequest): String? { - val accessTokenCookie = OAuth2CookieHelper.getAccessTokenCookie(request) - return if (accessTokenCookie != null) { - accessTokenCookie.value - } else { - super.extractToken(request) - } - } - -} diff --git a/generators/server/templates/src/main/kotlin/package/security/oauth2/CookiesHttpServletRequestWrapper.kt.ejs b/generators/server/templates/src/main/kotlin/package/security/oauth2/CookiesHttpServletRequestWrapper.kt.ejs deleted file mode 100644 index c48d6ccee..000000000 --- a/generators/server/templates/src/main/kotlin/package/security/oauth2/CookiesHttpServletRequestWrapper.kt.ejs +++ /dev/null @@ -1,42 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.security.oauth2 - -import javax.servlet.http.Cookie -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletRequestWrapper - -/** - * A request mapper used to modify the cookies in the original request. - * This is needed such that we can modify the cookies of the request during a token refresh. - * The token refresh happens before authentication by the `OAuth2AuthenticationProcessingFilter` - * so we must make sure that further in the filter chain, we have the new cookies and not the expired/missing ones. - */ -internal class CookiesHttpServletRequestWrapper(request: HttpServletRequest, - /** - * The new cookies of the request. Use these instead of the ones found in the wrapped request. - */ - private val cookies: Array) : HttpServletRequestWrapper(request) { - - /** - * Return the modified cookies instead of the original ones. - * @return the modified cookies. - */ - override fun getCookies(): Array = cookies -} diff --git a/generators/server/templates/src/main/kotlin/package/security/oauth2/CustomClaimConverter.kt.ejs b/generators/server/templates/src/main/kotlin/package/security/oauth2/CustomClaimConverter.kt.ejs new file mode 100644 index 000000000..fb9fc7056 --- /dev/null +++ b/generators/server/templates/src/main/kotlin/package/security/oauth2/CustomClaimConverter.kt.ejs @@ -0,0 +1,82 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + + This file is part of the JHipster project, see https://jhipster.github.io/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %>.security.oauth2 + +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.node.ObjectNode +import org.springframework.core.convert.converter.Converter +import org.springframework.http.HttpEntity +import org.springframework.http.HttpHeaders +import org.springframework.http.HttpMethod +import org.springframework.http.ResponseEntity +import org.springframework.security.oauth2.client.registration.ClientRegistration +import org.springframework.security.oauth2.jwt.MappedJwtClaimSetConverter +import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver +import org.springframework.security.oauth2.server.resource.web.DefaultBearerTokenResolver +import org.springframework.web.client.RestTemplate +import org.springframework.web.context.request.RequestContextHolder +import org.springframework.web.context.request.ServletRequestAttributes + +class CustomClaimConverter(private val registration: ClientRegistration, private val restTemplate: RestTemplate): Converter, Map> { + + private val bearerTokenResolver: BearerTokenResolver = DefaultBearerTokenResolver() + private val delegate: MappedJwtClaimSetConverter = MappedJwtClaimSetConverter.withDefaults(emptyMap()) + val users: MutableMap = hashMapOf() + + + override fun convert(claims: Map): Map? { + val convertedClaims = delegate.convert(claims) + if (RequestContextHolder.getRequestAttributes() != null) { + // Retrieve and set the token + val token = bearerTokenResolver.resolve((RequestContextHolder.getRequestAttributes() as ServletRequestAttributes).request) + val headers = HttpHeaders() + headers.set("Authorization", buildBearer(token)) + + + // Retrieve user infos from OAuth provider if not already loaded + val user = users.computeIfAbsent(claims["sub"].toString()) { + val userInfo: ResponseEntity = restTemplate.exchange( + registration.providerDetails.userInfoEndpoint.uri, + HttpMethod.GET, + HttpEntity(headers), + ObjectNode::class.java + ) + userInfo.body + } + + // Add custom claims + if (user != null) { + convertedClaims["preferred_username"] = user.get("preferred_username").asText() + convertedClaims["given_name"] = user.get("given_name").asText() + convertedClaims["family_name"] = user.get("family_name").asText() + if (user.has("groups")) { + val groups = user.get("groups").map(JsonNode::asText) + convertedClaims["groups"] = groups + } + } + } + + return convertedClaims + } + + private fun buildBearer(token: String?): String { + return "Bearer $token" + } +} + diff --git a/generators/server/templates/src/main/kotlin/package/security/oauth2/OAuth2AuthenticationService.kt.ejs b/generators/server/templates/src/main/kotlin/package/security/oauth2/OAuth2AuthenticationService.kt.ejs deleted file mode 100644 index 4585b4b81..000000000 --- a/generators/server/templates/src/main/kotlin/package/security/oauth2/OAuth2AuthenticationService.kt.ejs +++ /dev/null @@ -1,178 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.security.oauth2 - -import io.github.jhipster.security.PersistentTokenCache -import org.slf4j.LoggerFactory -import org.springframework.http.ResponseEntity -import org.springframework.security.authentication.BadCredentialsException -import org.springframework.security.oauth2.common.OAuth2AccessToken -import org.springframework.web.client.HttpClientErrorException - -import javax.servlet.http.Cookie -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse - -/** - * Number of milliseconds to cache refresh token grants so we don't have to repeat them in case of parallel requests. - */ -private const val REFRESH_TOKEN_VALIDITY_MILLIS = 10000L - -/** - * Manages authentication cases for OAuth2 updating the cookies holding access and refresh tokens accordingly. - * - * It can authenticate users, refresh the token cookies should they expire and log users out. - */ -class OAuth2AuthenticationService( - /** - * Used to contact the OAuth2 token endpoint. - */ - private val authorizationClient: OAuth2TokenEndpointClient, - /** - * Helps us with cookie handling. - */ - private val cookieHelper: OAuth2CookieHelper -) { - - private val log = LoggerFactory.getLogger(javaClass) - - /** - * Caches Refresh grant results for a refresh token value so we can reuse them. - * This avoids hammering UAA in case of several multi-threaded requests arriving in parallel. - */ - private val recentlyRefreshed: PersistentTokenCache = - PersistentTokenCache(REFRESH_TOKEN_VALIDITY_MILLIS) - - /** - * Authenticate the user by username and password. - * - * @param request the request coming from the client. - * @param response the response going back to the server. - * @param params the params holding the username, password and rememberMe. - * @return the [OAuth2AccessToken] as a [ResponseEntity]. Will return `OK (200)`, if successful. - * If the UAA cannot authenticate the user, the status code returned by UAA will be returned. - */ - fun authenticate( - request: HttpServletRequest, - response: HttpServletResponse, - params: Map - ): ResponseEntity { - try { - val username = params["username"] - val password = params["password"] - val rememberMe = java.lang.Boolean.valueOf(params["rememberMe"]) - val accessToken = authorizationClient.sendPasswordGrant(username!!, password!!) - val cookies = OAuth2Cookies() - cookieHelper.createCookies(request, accessToken, rememberMe, cookies) - cookies.addCookiesTo(response) - if (log.isDebugEnabled) { - log.debug("successfully authenticated user ${params["username"]}") - } - return ResponseEntity.ok(accessToken) - } catch (ex: HttpClientErrorException) { - log.error("failed to get OAuth2 tokens from UAA $ex") - throw BadCredentialsException("Invalid credentials") - } - } - - /** - * Try to refresh the access token using the refresh token provided as cookie. - * Note that browsers typically send multiple requests in parallel which means the access token - * will be expired on multiple threads. We don't want to send multiple requests to UAA though, - * so we need to cache results for a certain duration and synchronize threads to avoid sending - * multiple requests in parallel. - * - * @param request the request potentially holding the refresh token. - * @param response the response setting the new cookies (if refresh was successful). - * @param refreshCookie the refresh token cookie. Must not be null. - * @return the new servlet request containing the updated cookies for relaying downstream. - */ - fun refreshToken( - request: HttpServletRequest, - response: HttpServletResponse, - refreshCookie: Cookie - ): HttpServletRequest { - // check if non-remember-me session has expired - if (cookieHelper.isSessionExpired(refreshCookie)) { - log.info("session has expired due to inactivity") - logout(request, response) // logout to clear cookies in browser - return stripTokens(request) // don't include cookies downstream - } - val cookies = getCachedCookies(refreshCookie.value) - synchronized(cookies) { - // check if we have a result from another thread already - if (cookies.accessTokenCookie == null) { // no, we are first! - // send a refresh_token grant to UAA, getting new tokens - val refreshCookieValue = OAuth2CookieHelper.getRefreshTokenValue(refreshCookie) - val accessToken = authorizationClient.sendRefreshGrant(refreshCookieValue) - val rememberMe = OAuth2CookieHelper.isRememberMe(refreshCookie) - cookieHelper.createCookies(request, accessToken, rememberMe, cookies) - // add cookies to response to update browser - cookies.addCookiesTo(response) - } else { - log.debug("reusing cached refresh_token grant") - } - // replace cookies in original request with new ones - val requestCookies = CookieCollection(*request.cookies) - cookies.accessTokenCookie?.apply { requestCookies.add(this) } - cookies.refreshTokenCookie?.apply { requestCookies.add(this) } - return CookiesHttpServletRequestWrapper(request, requestCookies.toArray()) - } - } - - /** - * Get the result from the cache in a thread-safe manner. - * - * @param refreshTokenValue the refresh token for which we want the results. - * @return a RefreshGrantResult for that token. This will either be empty, if we are the first one to do the - * request, or contain some results already, if another thread already handled the grant for us. - */ - private fun getCachedCookies(refreshTokenValue: String): OAuth2Cookies { - synchronized(recentlyRefreshed) { - var ctx: OAuth2Cookies? = recentlyRefreshed.get(refreshTokenValue) - if (ctx == null) { - ctx = OAuth2Cookies() - recentlyRefreshed.put(refreshTokenValue, ctx) - } - return ctx - } - } - - /** - * Logs the user out by clearing all cookies. - * - * @param httpServletRequest the request containing the Cookies. - * @param httpServletResponse the response used to clear them. - */ - fun logout(httpServletRequest: HttpServletRequest, httpServletResponse: HttpServletResponse) { - cookieHelper.clearCookies(httpServletRequest, httpServletResponse) - } - - /** - * Strips token cookies preventing them from being used further down the chain. - * For example, the OAuth2 client won't checked them and they won't be relayed to other services. - * - * @param httpServletRequest the incoming request. - * @return the request to replace it with which has the tokens stripped. - */ - fun stripTokens(httpServletRequest: HttpServletRequest): HttpServletRequest { - val cookies = cookieHelper.stripCookies(httpServletRequest.cookies) - return CookiesHttpServletRequestWrapper(httpServletRequest, cookies) - } -} diff --git a/generators/server/templates/src/main/kotlin/package/security/oauth2/OAuth2CookieHelper.kt.ejs b/generators/server/templates/src/main/kotlin/package/security/oauth2/OAuth2CookieHelper.kt.ejs deleted file mode 100644 index 4a4f3b854..000000000 --- a/generators/server/templates/src/main/kotlin/package/security/oauth2/OAuth2CookieHelper.kt.ejs +++ /dev/null @@ -1,334 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.security.oauth2 - -import <%= packageName %>.config.oauth2.OAuth2Properties - -import org.slf4j.LoggerFactory -import org.springframework.boot.json.JsonParserFactory -import org.springframework.security.jwt.JwtHelper -import org.springframework.security.oauth2.common.OAuth2AccessToken -import org.springframework.security.oauth2.common.OAuth2RefreshToken -import org.springframework.security.oauth2.common.exceptions.InvalidTokenException -import org.springframework.security.oauth2.provider.token.AccessTokenConverter -import org.springframework.util.StringUtils - -import javax.servlet.http.Cookie -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse - -import org.apache.http.conn.util.InetAddressUtils.isIPv4Address -import org.apache.http.conn.util.InetAddressUtils.isIPv6Address -import org.apache.http.conn.util.PublicSuffixMatcherLoader - -/** - * Helps with OAuth2 cookie handling. - */ -class OAuth2CookieHelper(private val oAuth2Properties: OAuth2Properties) { - - /** - * Public suffix matcher (to strip private subdomains off cookie scope). - */ - private var suffixMatcher = PublicSuffixMatcherLoader.getDefault() - - private val log = LoggerFactory.getLogger(javaClass) - - /** - * Used to parse JWT claims. - */ - private val jsonParser = JsonParserFactory.getJsonParser() - - /** - * Create cookies using the provided values. - * - * @param request the request we are handling. - * @param accessToken the access token and enclosed refresh token for our cookies. - * @param rememberMe whether the user had originally checked "remember me". - * @param result will get the resulting cookies set. - */ - fun createCookies( - request: HttpServletRequest, - accessToken: OAuth2AccessToken, - rememberMe: Boolean, - result: OAuth2Cookies - ) { - val domain = getCookieDomain(request) - log.debug("creating cookies for domain $domain") - val accessTokenCookie = Cookie(ACCESS_TOKEN_COOKIE, accessToken.value) - setCookieProperties(accessTokenCookie, request.isSecure, domain) - log.debug("created access token cookie '${accessTokenCookie.name}'") - - val refreshToken = accessToken.refreshToken - val refreshTokenCookie = createRefreshTokenCookie(refreshToken, rememberMe) - setCookieProperties(refreshTokenCookie, request.isSecure, domain) - log.debug("created refresh token cookie '${refreshTokenCookie.name}', age: ${refreshTokenCookie.maxAge}") - - result.setCookies(accessTokenCookie, refreshTokenCookie) - } - - /** - * Create a cookie out of the given refresh token. - * Refresh token cookies contain the base64 encoded refresh token (a JWT token). - * They also contain a hint whether the refresh token was for remember me or not. - * If not, then the cookie will be prefixed by the timestamp it was created at followed by a pipe '|'. - * This gives us the chance to expire session cookies regardless of the token duration. - */ - private fun createRefreshTokenCookie(refreshToken: OAuth2RefreshToken, rememberMe: Boolean): Cookie { - var maxAge = -1 - var name = SESSION_TOKEN_COOKIE - val value = refreshToken.value - if (rememberMe) { - name = REFRESH_TOKEN_COOKIE - // get expiration in seconds from the token's "exp" claim - val exp = getClaim(refreshToken.value, AccessTokenConverter.EXP, Integer::class.java) - if (exp != null) { - val now = (System.currentTimeMillis() / 1000L).toInt() - maxAge = exp.toInt() - now - log.debug("refresh token valid for another $maxAge secs") - // let cookie expire a bit earlier than the token to avoid race conditions - maxAge -= REFRESH_TOKEN_EXPIRATION_WINDOW_SECS.toInt() - } - } - val refreshTokenCookie = Cookie(name, value) - refreshTokenCookie.maxAge = maxAge - return refreshTokenCookie - } - - /** - * Checks if the refresh token session has expired. - * Only makes sense for non-persistent cookies, i.e. when remember me was not checked. - * The motivation for this is that we want to throw out a user after a while if he's inactive. - * We cannot do this via refresh token validity because that one is also used for remember me. - * - * @param refreshCookie the refresh token cookie to check. - * @return true, if the session is expired. - */ - fun isSessionExpired(refreshCookie: Cookie): Boolean { - if (isRememberMe(refreshCookie)) { // no session expiration for "remember me" - return false - } - // read non-remember-me session length in secs - val validity = oAuth2Properties.webClientConfiguration.sessionTimeoutInSeconds - if (validity == null || validity < 0) { // no session expiration configured - return false - } - // token creating timestamp in secs is missing, session does not expire - val iat = getClaim(refreshCookie.value, "iat", Integer::class.java) ?: return false - val now = (System.currentTimeMillis() / 1000L).toInt() - val sessionDuration = now - iat.toInt() - log.debug("session duration $sessionDuration secs, will timeout at $validity") - return sessionDuration > validity // session has expired - } - - /** - * Retrieve the given claim from the given token. - * - * @param refreshToken the JWT token to examine. - * @param claimName name of the claim to get. - * @param clazz the [Class] we expect to find there. - * @return the desired claim. - * @throws InvalidTokenException if we cannot find the claim in the token or it is of wrong type. - */ - private fun getClaim(refreshToken: String, claimName: String, clazz: Class): T? { - val jwt = JwtHelper.decode(refreshToken) - val claims = jwt.claims - val claimsMap = jsonParser.parseMap(claims) - val claimValue = claimsMap[claimName] ?: return null - if (!clazz.isAssignableFrom(claimValue::class.java)) { - throw InvalidTokenException("claim is not of expected type: $claimName") - } - return claimValue as T - } - - /** - * Set cookie properties of access and refresh tokens. - * - * @param cookie the cookie to modify. - * @param isSecure whether it is coming from a secure request. - * @param domain the domain for which the cookie is valid. If `null`, then will fall back to default. - */ - private fun setCookieProperties(cookie: Cookie, isSecure: Boolean, domain: String?) { - cookie.isHttpOnly = true - cookie.path = "/" - cookie.secure = isSecure // if the request comes per HTTPS set the secure option on the cookie - if (domain != null) { - cookie.domain = domain - } - } - - /** - * Logs the user out by clearing all cookies. - * - * @param httpServletRequest the request containing the Cookies. - * @param httpServletResponse the response used to clear them. - */ - fun clearCookies(httpServletRequest: HttpServletRequest, httpServletResponse: HttpServletResponse) { - val domain = getCookieDomain(httpServletRequest) - for (cookieName in COOKIE_NAMES) { - clearCookie(httpServletRequest, httpServletResponse, domain, cookieName) - } - } - - private fun clearCookie( - httpServletRequest: HttpServletRequest, - httpServletResponse: HttpServletResponse, - domain: String?, - cookieName: String - ) { - val cookie = Cookie(cookieName, "") - setCookieProperties(cookie, httpServletRequest.isSecure, domain) - cookie.maxAge = 0 - httpServletResponse.addCookie(cookie) - log.debug("clearing cookie ${cookie.name}") - } - - /** - * Returns the top level domain of the server from the request. This is used to limit the Cookie - * to the top domain instead of the full domain name. - * - * A lot of times, individual gateways of the same domain get their own subdomain but authentication - * shall work across all subdomains of the top level domain. - * - * For example, when sending a request to `app1.domain.com`, - * this returns `.domain.com`. - * - * @param request the HTTP request we received from the client. - * @return the top level domain to set the cookies for. - * Returns `null` if the domain is not under a public suffix (.com, .co.uk), e.g. for localhost. - */ - private fun getCookieDomain(request: HttpServletRequest): String? { - var domain = oAuth2Properties.webClientConfiguration.cookieDomain - if (domain != null) { - return domain - } - // if not explicitly defined, use top-level domain - domain = request.serverName.toLowerCase() - // strip off leading www. - if (domain.startsWith("www.")) { - domain = domain.substring(4) - } - // if it isn't an IP address - if (!isIPv4Address(domain) && !isIPv6Address(domain)) { - // strip off private subdomains, leaving public TLD only - val suffix = suffixMatcher.getDomainRoot(domain) - if (suffix != null && suffix != domain) { - // preserve leading dot - return ".$suffix" - } - } - // no top-level domain, stick with default domain - return null - } - - /** - * Strip our token cookies from the array. - * - * @param cookies the cookies we receive as input. - * @return the new cookie array without our tokens. - */ - internal fun stripCookies(cookies: Array): Array { - val cc = CookieCollection(*cookies) - return if (cc.removeAll(COOKIE_NAMES)) { - cc.toArray() - } else cookies - } - - companion object { - /** - * Name of the access token cookie. - */ - const val ACCESS_TOKEN_COOKIE = OAuth2AccessToken.ACCESS_TOKEN - /** - * Name of the refresh token cookie in case of remember me. - */ - const val REFRESH_TOKEN_COOKIE = OAuth2AccessToken.REFRESH_TOKEN - /** - * Name of the session-only refresh token in case the user did not check remember me. - */ - const val SESSION_TOKEN_COOKIE = "session_token" - /** - * The names of the Cookies we set. - */ - private val COOKIE_NAMES = listOf(ACCESS_TOKEN_COOKIE, REFRESH_TOKEN_COOKIE, SESSION_TOKEN_COOKIE) - /** - * Number of seconds to expire refresh token cookies before the enclosed token expires. - * This makes sure we don't run into race conditions where the cookie is still there but - * expires while we process it. - */ - private const val REFRESH_TOKEN_EXPIRATION_WINDOW_SECS = 3L - - fun getAccessTokenCookie(request: HttpServletRequest): Cookie? = - getCookie(request, ACCESS_TOKEN_COOKIE) - - fun getRefreshTokenCookie(request: HttpServletRequest): Cookie? { - var cookie = getCookie(request, REFRESH_TOKEN_COOKIE) - if (cookie == null) { - cookie = getCookie(request, SESSION_TOKEN_COOKIE) - } - return cookie - } - - /** - * Get a cookie by name from the given servlet request. - * - * @param request the request containing the cookie. - * @param cookieName the case-sensitive name of the cookie to get. - * @return the resulting [Cookie]; or `null`, if not found. - */ - private fun getCookie(request: HttpServletRequest, cookieName: String): Cookie? { - if (request.cookies != null) { - for (cookie in request.cookies) { - if (cookie.name == cookieName) { - val value = cookie.value - if (StringUtils.hasText(value)) { - return cookie - } - } - } - } - return null - } - - /** - * Returns true if the refresh token cookie was set with remember me checked. - * We can recognize this by the name of the cookie. - * - * @param refreshTokenCookie the cookie holding the refresh token. - * @return true, if it was set persistently (i.e. for "remember me"). - */ - fun isRememberMe(refreshTokenCookie: Cookie): Boolean = - refreshTokenCookie.name == REFRESH_TOKEN_COOKIE - - /** - * Extracts the refresh token from the refresh token cookie. - * Since we encode additional information into the cookie, this needs to be called to get - * hold of the enclosed JWT. - * - * @param refreshCookie the cookie we store the value in. - * @return the refresh JWT from the cookie. - */ - fun getRefreshTokenValue(refreshCookie: Cookie): String { - val value = refreshCookie.value - val i = value.indexOf('|') - return if (i > 0) { - value.substring(i + 1) - } else value - } - } -} diff --git a/generators/server/templates/src/main/kotlin/package/security/oauth2/OAuth2Cookies.kt.ejs b/generators/server/templates/src/main/kotlin/package/security/oauth2/OAuth2Cookies.kt.ejs deleted file mode 100644 index 763d3a4f2..000000000 --- a/generators/server/templates/src/main/kotlin/package/security/oauth2/OAuth2Cookies.kt.ejs +++ /dev/null @@ -1,47 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.security.oauth2 - -import javax.servlet.http.Cookie -import javax.servlet.http.HttpServletResponse - -/** - * Holds the access token and refresh token cookies. - */ -class OAuth2Cookies { - var accessTokenCookie: Cookie? = null - private set - var refreshTokenCookie: Cookie? = null - private set - - fun setCookies(accessTokenCookie: Cookie, refreshTokenCookie: Cookie) { - this.accessTokenCookie = accessTokenCookie - this.refreshTokenCookie = refreshTokenCookie - } - - /** - * Add the access token and refresh token as cookies to the response after successful authentication. - * - * @param response the response to add them to. - */ - fun addCookiesTo(response: HttpServletResponse) { - response.addCookie(accessTokenCookie) - response.addCookie(refreshTokenCookie) - } -} diff --git a/generators/server/templates/src/main/kotlin/package/security/oauth2/OAuth2SignatureVerifierClient.kt.ejs b/generators/server/templates/src/main/kotlin/package/security/oauth2/OAuth2SignatureVerifierClient.kt.ejs deleted file mode 100644 index e994f25b1..000000000 --- a/generators/server/templates/src/main/kotlin/package/security/oauth2/OAuth2SignatureVerifierClient.kt.ejs +++ /dev/null @@ -1,41 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.security.oauth2 - -import org.springframework.security.jwt.crypto.sign.SignatureVerifier - -/** - * Abstracts how to create a [SignatureVerifier] to verify JWT tokens with a public key. - * Implementations will have to contact the OAuth2 authorization server to fetch the public key - * and use it to build a [SignatureVerifier] in a server specific way. - * - * @see UaaSignatureVerifierClient - */ -interface OAuth2SignatureVerifierClient { - /** - * Returns the [SignatureVerifier] used to verify JWT tokens. - * Fetches the public key from the Authorization server to create - * this verifier. - * - * @return the new verifier used to verify JWT signatures. - * Will be null if we cannot contact the token endpoint. - * @throws Exception if we could not create a [SignatureVerifier] or contact the token endpoint. - */ - fun getSignatureVerifier(): SignatureVerifier? -} diff --git a/generators/server/templates/src/main/kotlin/package/security/oauth2/OAuth2TokenEndpointClient.kt.ejs b/generators/server/templates/src/main/kotlin/package/security/oauth2/OAuth2TokenEndpointClient.kt.ejs deleted file mode 100644 index 3573ad4ad..000000000 --- a/generators/server/templates/src/main/kotlin/package/security/oauth2/OAuth2TokenEndpointClient.kt.ejs +++ /dev/null @@ -1,51 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.security.oauth2 - -import org.springframework.security.oauth2.common.OAuth2AccessToken - -/** - * Client talking to an OAuth2 Authorization server token endpoint. - * - * @see UaaTokenEndpointClient - * - * @see OAuth2TokenEndpointClientAdapter - */ -interface OAuth2TokenEndpointClient { - /** - * Send a password grant to the token endpoint. - * - * @param username the username to authenticate. - * @param password his password. - * @return the access token and enclosed refresh token received from the token endpoint. - * @throws org.springframework.security.oauth2.common.exceptions.ClientAuthenticationException - * if we cannot contact the token endpoint. - */ - fun sendPasswordGrant(username: String, password: String): OAuth2AccessToken - - /** - * Send a refresh_token grant to the token endpoint. - * - * @param refreshTokenValue the refresh token used to get new tokens. - * @return the new access/refresh token pair. - * @throws org.springframework.security.oauth2.common.exceptions.ClientAuthenticationException - * if we cannot contact the token endpoint. - */ - fun sendRefreshGrant(refreshTokenValue: String): OAuth2AccessToken -} diff --git a/generators/server/templates/src/main/kotlin/package/security/oauth2/OAuth2TokenEndpointClientAdapter.kt.ejs b/generators/server/templates/src/main/kotlin/package/security/oauth2/OAuth2TokenEndpointClientAdapter.kt.ejs deleted file mode 100644 index 599ba5f71..000000000 --- a/generators/server/templates/src/main/kotlin/package/security/oauth2/OAuth2TokenEndpointClientAdapter.kt.ejs +++ /dev/null @@ -1,119 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.security.oauth2 - -import <%= packageName %>.config.oauth2.OAuth2Properties -import io.github.jhipster.config.JHipsterProperties -import org.slf4j.LoggerFactory -import org.springframework.http.HttpEntity -import org.springframework.http.HttpHeaders -import org.springframework.http.HttpStatus -import org.springframework.http.MediaType -import org.springframework.security.oauth2.common.OAuth2AccessToken -import org.springframework.security.oauth2.common.exceptions.InvalidClientException -import org.springframework.util.LinkedMultiValueMap -import org.springframework.util.MultiValueMap -import org.springframework.web.client.HttpClientErrorException -import org.springframework.web.client.RestTemplate - -/** - * Default base class for an [OAuth2TokenEndpointClient]. - * Individual implementations for a particular OAuth2 provider can use this as a starting point. - */ -abstract class OAuth2TokenEndpointClientAdapter( - private val restTemplate: RestTemplate, - private val jHipsterProperties: JHipsterProperties, - private val oAuth2Properties: OAuth2Properties -) : OAuth2TokenEndpointClient { - - private val log = LoggerFactory.getLogger(javaClass) - - /** - * Sends a password grant to the token endpoint. - * - * @param username the username to authenticate. - * @param password his password. - * @return the access token. - */ - override fun sendPasswordGrant(username: String, password: String): OAuth2AccessToken { - val reqHeaders = HttpHeaders() - reqHeaders.contentType = MediaType.APPLICATION_FORM_URLENCODED - val formParams = LinkedMultiValueMap() - formParams.set("username", username) - formParams.set("password", password) - formParams.set("grant_type", "password") - addAuthentication(reqHeaders, formParams) - val entity = HttpEntity>(formParams, reqHeaders) - log.debug("contacting OAuth2 token endpoint to login user: $username") - val responseEntity = restTemplate.postForEntity(getTokenEndpoint(), entity, OAuth2AccessToken::class.java) - if (responseEntity.statusCode != HttpStatus.OK) { - log.debug( - "failed to authenticate user with OAuth2 token endpoint, status: ${responseEntity.statusCodeValue}" - ) - throw HttpClientErrorException(responseEntity.statusCode) - } - return responseEntity.body!! - } - - /** - * Sends a refresh grant to the token endpoint using the current refresh token to obtain new tokens. - * - * @param refreshTokenValue the refresh token to use to obtain new tokens. - * @return the new, refreshed access token. - */ - override fun sendRefreshGrant(refreshTokenValue: String): OAuth2AccessToken { - val params = LinkedMultiValueMap() - params.add("grant_type", "refresh_token") - params.add("refresh_token", refreshTokenValue) - val headers = HttpHeaders() - addAuthentication(headers, params) - val entity = HttpEntity>(params, headers) - log.debug("contacting OAuth2 token endpoint to refresh OAuth2 JWT tokens") - val responseEntity = restTemplate.postForEntity( - getTokenEndpoint(), entity, - OAuth2AccessToken::class.java - ) - if (responseEntity.statusCode != HttpStatus.OK) { - log.debug("failed to refresh tokens: ${responseEntity.statusCodeValue}") - throw HttpClientErrorException(responseEntity.statusCode) - } - val accessToken = responseEntity.body!! - log.info("refreshed OAuth2 JWT cookies using refresh_token grant") - return accessToken - } - - protected abstract fun addAuthentication(reqHeaders: HttpHeaders, formParams: MultiValueMap) - - protected fun getClientSecret() = - oAuth2Properties.webClientConfiguration.secret - ?: throw InvalidClientException("no client-secret configured in application properties") - - protected fun getClientId() = - oAuth2Properties.webClientConfiguration.clientId - ?: throw InvalidClientException("no client-id configured in application properties") - - /** - * Returns the configured OAuth2 token endpoint URI. - * - * @return the OAuth2 token endpoint URI. - */ - private fun getTokenEndpoint() = - jHipsterProperties.security.clientAuthorization.accessTokenUri - ?: throw InvalidClientException("no token endpoint configured in application properties") -} diff --git a/generators/server/templates/src/main/kotlin/package/security/oauth2/UaaSignatureVerifierClient.kt.ejs b/generators/server/templates/src/main/kotlin/package/security/oauth2/UaaSignatureVerifierClient.kt.ejs deleted file mode 100644 index 31d65537b..000000000 --- a/generators/server/templates/src/main/kotlin/package/security/oauth2/UaaSignatureVerifierClient.kt.ejs +++ /dev/null @@ -1,75 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.security.oauth2 - -import <%= packageName %>.config.oauth2.OAuth2Properties -import org.slf4j.LoggerFactory -import org.springframework.beans.factory.annotation.Qualifier -import org.springframework.cloud.client.discovery.DiscoveryClient -import org.springframework.http.HttpEntity -import org.springframework.http.HttpHeaders -import org.springframework.http.HttpMethod -import org.springframework.security.jwt.crypto.sign.RsaVerifier -import org.springframework.security.jwt.crypto.sign.SignatureVerifier -import org.springframework.security.oauth2.common.exceptions.InvalidClientException -import org.springframework.stereotype.Component -import org.springframework.web.client.RestTemplate - -/** - * Client fetching the public key from UAA to create a [SignatureVerifier]. - */ -@Component -class UaaSignatureVerifierClient( - discoveryClient: DiscoveryClient, - @param:Qualifier("<%= !serviceDiscoveryType ? 'restTemplate' : 'loadBalancedRestTemplate' %>") private val restTemplate: RestTemplate, - protected val oAuth2Properties: OAuth2Properties -) : OAuth2SignatureVerifierClient { - - private val log = LoggerFactory.getLogger(javaClass) - - init { - // Load available UAA servers - discoveryClient.services - } - - /** - * Fetches the public key from the UAA. - * - * @return the public key used to verify JWT tokens; or `null`. - */ - override fun getSignatureVerifier(): SignatureVerifier? = - try { - val request = HttpEntity(HttpHeaders()) - val key = restTemplate - .exchange(getPublicKeyEndpoint(), HttpMethod.GET, request, Map::class.java).body!!["value"] as String - RsaVerifier(key) - } catch (ex: IllegalStateException) { - log.warn("could not contact UAA to get public key") - null - } - - /** - * Returns the configured endpoint URI to retrieve the public key. - * - * @return the configured endpoint URI to retrieve the public key. - */ - private fun getPublicKeyEndpoint() = - oAuth2Properties.signatureVerification.publicKeyEndpointUri - ?: throw InvalidClientException("no token endpoint configured in application properties") -} diff --git a/generators/server/templates/src/main/kotlin/package/security/oauth2/UaaTokenEndpointClient.kt.ejs b/generators/server/templates/src/main/kotlin/package/security/oauth2/UaaTokenEndpointClient.kt.ejs deleted file mode 100644 index 571788b6d..000000000 --- a/generators/server/templates/src/main/kotlin/package/security/oauth2/UaaTokenEndpointClient.kt.ejs +++ /dev/null @@ -1,57 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.security.oauth2 - -import <%= packageName %>.config.oauth2.OAuth2Properties -import io.github.jhipster.config.JHipsterProperties -import org.springframework.beans.factory.annotation.Qualifier -import org.springframework.http.HttpHeaders -import org.springframework.stereotype.Component -import org.springframework.util.Base64Utils -import org.springframework.util.MultiValueMap -import org.springframework.web.client.RestTemplate - -import java.nio.charset.StandardCharsets - -/** - * Client talking to UAA's token endpoint to do different OAuth2 grants. - */ -@Component -class UaaTokenEndpointClient( - @Qualifier("<%= !serviceDiscoveryType ? 'restTemplate' : 'loadBalancedRestTemplate' %>") restTemplate: RestTemplate, - jHipsterProperties: JHipsterProperties, - oAuth2Properties: OAuth2Properties -) : OAuth2TokenEndpointClientAdapter(restTemplate, jHipsterProperties, oAuth2Properties), OAuth2TokenEndpointClient { - - /** - * @return a Basic authorization header to be used to talk to UAA. - */ - protected val authorizationHeader: String - get() { - val clientId = getClientId() - val clientSecret = getClientSecret() - val authorization = "$clientId:$clientSecret" - return "Basic " + Base64Utils.encodeToString(authorization.toByteArray(StandardCharsets.UTF_8)) - } - - override fun addAuthentication(reqHeaders: HttpHeaders, formParams: MultiValueMap) { - reqHeaders.add("Authorization", authorizationHeader) - } - -} diff --git a/generators/server/templates/src/main/kotlin/package/service/AuditEventService.kt.ejs b/generators/server/templates/src/main/kotlin/package/service/AuditEventService.kt.ejs deleted file mode 100644 index c22b6dc1d..000000000 --- a/generators/server/templates/src/main/kotlin/package/service/AuditEventService.kt.ejs +++ /dev/null @@ -1,210 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.service - -import io.github.jhipster.config.JHipsterProperties -import <%= packageName %>.config.audit.AuditEventConverter -<%_ if (reactive) { _%> -import <%= packageName %>.domain.PersistentAuditEvent -import reactor.core.publisher.toFlux -<%_ } _%> -import <%= packageName %>.repository.PersistenceAuditEventRepository -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.springframework.boot.actuate.audit.AuditEvent -<%_ if (!reactive) { _%> -import org.springframework.data.domain.Page -<%_ } _%> -import org.springframework.data.domain.Pageable -import org.springframework.scheduling.annotation.Scheduled -import org.springframework.stereotype.Service -<%_ if (databaseType === 'sql') { _%> -import org.springframework.transaction.annotation.Transactional -<%_ } _%> -<%_ if (reactive) { _%> -import reactor.core.publisher.Flux -import reactor.core.publisher.Mono - <%_ if (databaseType === 'sql') { _%> -import reactor.util.function.Tuples - <%_ } _%> -<%_ } _%> -import java.time.Instant -import java.time.temporal.ChronoUnit -<%_ if (!reactive) { _%> -import java.util.Optional -<%_ } _%> -<%_ if (reactive) { _%> -import java.util.HashMap -import java.util.Map - -import org.springframework.boot.actuate.security.AuthenticationAuditListener.AUTHENTICATION_FAILURE -import org.springframework.boot.actuate.security.AuthenticationAuditListener.AUTHENTICATION_SUCCESS -<%_ } _%> - -/** - * Service for managing audit events. - * - * This is the default implementation to support SpringBoot Actuator `AuditEventRepository`. - */ -@Service -<%_ if (databaseType === 'sql' && !reactive) { _%> -@Transactional -<%_ } _%> -class AuditEventService( - private val persistenceAuditEventRepository: PersistenceAuditEventRepository, - private val auditEventConverter: AuditEventConverter, - private val jHipsterProperties: JHipsterProperties -) { - - <%_ if (reactive) { _%> - /** - * Should be the same as in Liquibase migration. - */ - private val EVENT_DATA_COLUMN_MAX_LENGTH = 255 - <%_ } _%> - - private val log = LoggerFactory.getLogger(javaClass) - - /** - * Old audit events should be automatically deleted after 30 days. - * - * This is scheduled to get fired at 12:00 (am). - */ - @Scheduled(cron = "0 0 12 * * ?") - fun removeOldAuditEvents() { - <%_ if (!reactive) { _%> - persistenceAuditEventRepository - .findByAuditEventDateBefore(Instant.now().minus(jHipsterProperties.auditEvents.retentionPeriod.toLong(), ChronoUnit.DAYS)) - .forEach{ - log.debug("Deleting audit data $it") - persistenceAuditEventRepository.delete(it) - } - <%_ } else { _%> - removeOldAuditEventsReactively().block() - } - - <%_ if (databaseType === 'sql') { _%> - @Transactional - <%_ } _%> - fun removeOldAuditEventsReactively(): Mono { - return persistenceAuditEventRepository - .findByAuditEventDateBefore(Instant.now().minus(jHipsterProperties.auditEvents.retentionPeriod.toLong(), ChronoUnit.DAYS)) - .flatMap { - log.debug("Deleting audit data $it") - persistenceAuditEventRepository.delete(it) - }.then() - <%_ } _%> - } - - <%_ if (databaseType === 'sql') { _%> - @Transactional(readOnly = true) - <%_ } _%> - fun findAll(pageable: Pageable): <% if (reactive) { %>Flux<% } else { %>Page<% } %> = - persistenceAuditEventRepository.findAll<% if (reactive) { %>By<% } %>(pageable) - .map { auditEventConverter.convertToAuditEvent(it) } - - <%_ if (databaseType === 'sql') { _%> - @Transactional(readOnly = true) - <%_ } _%> - fun findByDates(fromDate: Instant, toDate: Instant, pageable: Pageable): <% if (reactive) { %>Flux<% } else { %>Page<% } %> = - persistenceAuditEventRepository.findAllByAuditEventDateBetween(fromDate, toDate, pageable) - .map { auditEventConverter.convertToAuditEvent(it) } - - <%_ if (databaseType === 'sql') { _%> - @Transactional(readOnly = true) - <%_ } _%> - fun find(id: <% if (databaseType === 'sql') { %>Long<% } %><% if (databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') { %>String<% } %>): <% if (reactive) { %>Mono<% } else { %>Optional<% } %> = - persistenceAuditEventRepository.findById(id) - .map { auditEventConverter.convertToAuditEvent(it) } - - <%_ if (reactive) { _%> - - <%_ if (databaseType === 'sql') { _%> - @Transactional(readOnly = true) - <%_ } _%> - fun count(): Mono { - return persistenceAuditEventRepository.count() - } - - <%_ if (databaseType === 'sql') { _%> - @Transactional(readOnly = true) - <%_ } _%> - fun countByDates(fromDate: Instant, toDate: Instant): Mono { - return persistenceAuditEventRepository.countByAuditEventDateBetween(fromDate, toDate) - } - - <%_ if (databaseType === 'sql') { _%> - @Transactional(readOnly = true) - <%_ } _%> - fun saveAuthenticationSuccess(login: String): Mono { - val persistentAuditEvent = PersistentAuditEvent() - persistentAuditEvent.principal = login - persistentAuditEvent.auditEventType = AUTHENTICATION_SUCCESS - persistentAuditEvent.auditEventDate = Instant.now() - return persistenceAuditEventRepository.save(persistentAuditEvent) - } - - <%_ if (databaseType === 'sql') { _%> - @Transactional(readOnly = true) - <%_ } _%> - fun saveAuthenticationError(login: String, e: Throwable): Mono { - val persistentAuditEvent = PersistentAuditEvent() - persistentAuditEvent.principal = login - persistentAuditEvent.auditEventType = AUTHENTICATION_FAILURE - persistentAuditEvent.auditEventDate = Instant.now() - val eventData = mutableMapOf() - eventData["type"] = e::class.java.name - eventData["message"] = e.message - persistentAuditEvent.data = truncate(eventData) - return persistenceAuditEventRepository.save(persistentAuditEvent)<% if (databaseType === 'sql') { %> - .flatMapMany { event -> - event.data.entries - .map{ Tuples.of(event!!, it.key, it.value!!) } - .toFlux() - } - .flatMap{ t -> - t.t1.id?.let { - persistenceAuditEventRepository - .savePersistenceAuditEventData(it, t.t2, t.t3) - .thenReturn(t.t1) - } - }.last() - <% } %> - } - - /** - * Truncate event data that might exceed column length. - */ - private fun truncate(data: MutableMap): MutableMap { - val results = mutableMapOf() - data.entries.forEach { - var value = it.value - if (value != null) { - val length = value.length - if (length > EVENT_DATA_COLUMN_MAX_LENGTH) { - value = value.substring(0, EVENT_DATA_COLUMN_MAX_LENGTH) - log.warn("Event data for ${it.key} too long ($length) has been truncated to $EVENT_DATA_COLUMN_MAX_LENGTH. Consider increasing column width.") - } - } - results[it.key] = value - } - return results - } - <%_ } _%> -} diff --git a/generators/server/templates/src/main/kotlin/package/service/ColumnConverter.kt.ejs b/generators/server/templates/src/main/kotlin/package/service/ColumnConverter.kt.ejs new file mode 100644 index 000000000..85a87cd2c --- /dev/null +++ b/generators/server/templates/src/main/kotlin/package/service/ColumnConverter.kt.ejs @@ -0,0 +1,84 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + +This file is part of the JHipster project, see https://jhipster.github.io/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %>.service + +import io.r2dbc.spi.Row +import org.springframework.data.r2dbc.convert.R2dbcConverter +import org.springframework.data.r2dbc.convert.R2dbcCustomConversions +import org.springframework.lang.Nullable +import org.springframework.stereotype.Service +import org.springframework.util.ClassUtils + +/** + * This service provides helper function dealing with the low level {@link Row} and Spring's {@link R2dbcCustomConversions}, so type conversions can be applied. + */ +@Service +class ColumnConverter( + private val conversions: R2dbcCustomConversions, + private val r2dbcConverter: R2dbcConverter +) { + + private val conversionService = r2dbcConverter.conversionService + + /** + * Converts the value to the target class with the help of the {@link ConversionService}. + * @param value to convert. + * @param target class. + * @param the parameter for the intended type. + * @return the value which can be constructed from the input. + */ + @SuppressWarnings("unchecked") + fun convert(@Nullable value: Any?, @Nullable target: Class): T? { + + if (value == null || target == null){ + return null as T + } + + if (ClassUtils.isAssignableValue(target, value)) { + return value as T + } + + if (conversions.hasCustomReadTarget(value::class.java, target)) { + return conversionService.convert(value, target) + } + + return if (Enum::class.java.isAssignableFrom(target)) { + java.lang.Enum.valueOf(target as Class?>, value.toString()) as T + } else conversionService.convert(value, target) + + } + + /** + * Convert a value from the {@link Row} to a type - throws an exception, it it's impossible. + * @param row which contains the column values. + * @param target class. + * @param columnName the name of the column which to convert. + * @param the parameter for the intended type. + * @return the value which can be constructed from the input. + */ + fun fromRow(row: Row, columnName: String, target: Class): T? { + return try { + // try, directly the driver + row.get(columnName, target) + } catch (e: Exception) { + val obj = row.get(columnName) + convert(obj, target) + } + } +} diff --git a/generators/server/templates/src/main/kotlin/package/service/EntityManager.kt.ejs b/generators/server/templates/src/main/kotlin/package/service/EntityManager.kt.ejs new file mode 100644 index 000000000..ecde3b7c5 --- /dev/null +++ b/generators/server/templates/src/main/kotlin/package/service/EntityManager.kt.ejs @@ -0,0 +1,236 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + +This file is part of the JHipster project, see https://jhipster.github.io/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %>.service + +import org.springframework.data.domain.Pageable +import org.springframework.data.domain.Sort +import org.springframework.data.r2dbc.convert.R2dbcConverter +import org.springframework.data.r2dbc.core.R2dbcEntityTemplate +import org.springframework.data.r2dbc.core.StatementMapper +import org.springframework.data.r2dbc.mapping.OutboundRow +import org.springframework.data.r2dbc.query.UpdateMapper +import org.springframework.data.relational.core.query.Criteria +import org.springframework.data.relational.core.mapping.RelationalPersistentEntity +import org.springframework.data.relational.core.sql.Conditions +import org.springframework.data.relational.core.sql.OrderByField +import org.springframework.data.relational.core.sql.Select +import org.springframework.data.relational.core.sql.SelectBuilder.SelectFromAndJoin +import org.springframework.data.relational.core.sql.SelectBuilder.SelectFromAndJoinCondition +import org.springframework.data.relational.core.sql.SelectBuilder.SelectOrdered +import org.springframework.data.relational.core.sql.SqlIdentifier +import org.springframework.data.relational.core.sql.Table +import org.springframework.r2dbc.core.Parameter; +import org.springframework.data.relational.core.sql.render.SqlRenderer +import org.springframework.stereotype.Service +import org.springframework.util.Assert + +import reactor.core.publisher.Flux +import reactor.core.publisher.Mono +import java.util.stream.Stream + +/** + * Helper class to create SQL selects based on the entity, paging parameters and criteria. + * + */ +@Service +class EntityManager( + private val sqlRenderer: SqlRenderer, + private val updateMapper: UpdateMapper, + private val r2dbcEntityTemplate: R2dbcEntityTemplate +) { + + private var statementMapper: StatementMapper? = null + + init { + statementMapper = r2dbcEntityTemplate.dataAccessStrategy.statementMapper + } + + companion object { + const val ENTITY_ALIAS: String = "e" + const val ALIAS_PREFIX: String = "e_" + + private fun createOrderByFields(table: Table, sortToUse: Sort): Collection { + val fields = mutableListOf() + sortToUse.forEach { + val propertyName = it.property + val orderByField = OrderByField.from(table.column(propertyName).`as`(ALIAS_PREFIX + propertyName)) + val sort = if (it.isAscending) orderByField.asc() else orderByField.desc() + fields.add(sort) + } + return fields as Collection + } + } + + data class LinkTable(val tableName: String, val idColumn: String, val referenceColumn: String) { + init { + Assert.notNull(tableName, "tableName is null") + Assert.notNull(idColumn, "idColumn is null") + Assert.notNull(referenceColumn, "referenceColumn is null") + } + } + + /** + * Creates an SQL select statement from the given fragment and pagination parameters. + * @param selectFrom a representation of a select statement. + * @param entityType the entity type which holds the table name. + * @param pageable page parameter, or null, if everything needs to be returned + * @return sql select statement + */ + fun createSelect(selectFrom: SelectFromAndJoin, entityType: Class<*>, pageable: Pageable?, criteria: Criteria?): String { + if (pageable != null) { + if (criteria != null) { + return createSelectImpl(selectFrom.limitOffset(pageable.pageSize.toLong(), pageable.offset).where(Conditions.just(criteria.toString())), entityType, pageable.sort) + } + return createSelectImpl(selectFrom.limitOffset(pageable.pageSize.toLong(), pageable.offset), entityType, pageable.sort) + } else { + if (criteria != null) { + return createSelectImpl(selectFrom.where(Conditions.just(criteria.toString())), entityType, null); + } else { + return createSelectImpl(selectFrom, entityType, null) + } + } + } + + /** + * Creates an SQL select statement from the given fragment and pagination parameters. + * @param selectFrom a representation of a select statement. + * @param entityType the entity type which holds the table name. + * @param pageable page parameter, or null, if everything needs to be returned + * @return sql select statement + */ + fun createSelect(selectFrom: SelectFromAndJoinCondition, entityType: Class<*>, pageable: Pageable?, criteria: Criteria?): String { + if (pageable != null) { + if (criteria != null) { + return createSelectImpl(selectFrom.limitOffset(pageable.pageSize.toLong(), pageable.offset).where(Conditions.just(criteria.toString())), entityType, pageable.sort) + } else { + return createSelectImpl(selectFrom.limitOffset(pageable.pageSize.toLong(), pageable.offset), entityType, pageable.sort) + } + } else { + if (criteria != null) { + return createSelectImpl(selectFrom.where(Conditions.just(criteria.toString())), entityType, null) + } else { + return createSelectImpl(selectFrom, entityType, null) + } + } + } + + private fun createSelectImpl(selectFrom: SelectOrdered, entityType: Class<*>, sortParameter: Sort?): String { + var selected = selectFrom + if (sortParameter != null && sortParameter.isSorted) { + val entity: RelationalPersistentEntity<*> = getPersistentEntity(entityType) + if (entity != null) { + val sort = updateMapper.getMappedObject(sortParameter, entity) + selected = selectFrom.orderBy( + createOrderByFields((Table.create(entity.tableName).`as`(EntityManager.ENTITY_ALIAS)), sort)) + } + } + return createSelect(selected.build()) + } + + private fun getPersistentEntity(entityType: Class<*>): RelationalPersistentEntity<*> { + return r2dbcEntityTemplate.converter.mappingContext + .getPersistentEntity(entityType) as RelationalPersistentEntity<*> + } + + /** + * Delete all the entity with the given type, and return the number of deletions. + * @param entityType the entity type which holds the table name. + * @return the number of deleted entity + */ + fun deleteAll(entityType: Class<*>): Mono { + return r2dbcEntityTemplate.delete(entityType).all() + } + + /** + * Delete all the rows from the given table, and return the number of deletions. + * @param tableName the name of the table to delete. + * @return the number of deleted rows. + */ + fun deleteAll(tableName: String): Mono { + val delete = statementMapper?.createDelete(tableName) + return r2dbcEntityTemplate.databaseClient.sql(statementMapper?.getMappedObject(delete)).fetch().rowsUpdated() + } + + /** + * Generate an actual SQL from the given {@link Select}. + * @param select a representation of a select statement. + * @return the generated SQL select. + */ + fun createSelect(select: Select): String { + return sqlRenderer.render(select) + } + + /** + * Inserts the given entity into the database - and sets the id, if it's an autoincrement field. + * @param the type of the persisted entity. + * @param entity the entity to be inserted into the database. + * @return the persisted entity. + */ + fun insert(entity: S): Mono { + return r2dbcEntityTemplate.insert(entity) + } + + /** + * Updates the table, which links the entity with the referred entities. + * @param table describes the link table, it contains a table name, the column name for the id, and for the referred entity id. + * @param entityId the id of the entity, for which the links are created. + * @param referencedIds the id of the referred entities. + * @return the number of inserted rows. + */ + fun updateLinkTable(table: LinkTable, entityId: Long?, referencedIds: List?): Mono { + + if (referencedIds == null) { + return deleteFromLinkTable(table, entityId).then(Mono.just(0)) + } + + return deleteFromLinkTable(table, entityId) + .then( + Flux.fromIterable(referencedIds) + .flatMap { referenceId: Long? -> + val insert = r2dbcEntityTemplate + .dataAccessStrategy + .statementMapper + .createInsert(table.tableName) + .withColumn(table.idColumn, Parameter.from(entityId)) + .withColumn(table.referenceColumn, Parameter.from(referenceId)) + r2dbcEntityTemplate + .databaseClient + .sql(statementMapper?.getMappedObject(insert)) + .fetch() + .rowsUpdated() + } + .collectList() + .map { updates: List -> + updates.stream().reduce { a: Int, b: Int -> + Integer.sum( + a, + b + ) + }.orElse(0) + }) + } + + fun deleteFromLinkTable(table: LinkTable, entityId: Long?): Mono { + Assert.notNull(entityId, "entityId is null") + val deleteSpec = r2dbcEntityTemplate.dataAccessStrategy.statementMapper + .createDelete(table.tableName) + .withCriteria(Criteria.from(Criteria.where(table.idColumn).`is`(entityId))) + return r2dbcEntityTemplate.databaseClient.sql(statementMapper?.getMappedObject(deleteSpec)).then() + } +} diff --git a/generators/server/templates/src/main/kotlin/package/service/MailService.kt.ejs b/generators/server/templates/src/main/kotlin/package/service/MailService.kt.ejs index 62ce947f3..21ff68ab3 100644 --- a/generators/server/templates/src/main/kotlin/package/service/MailService.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/service/MailService.kt.ejs @@ -20,7 +20,7 @@ package <%= packageName %>.service import <%= packageName %>.domain.<%= asEntity('User') %> -import io.github.jhipster.config.JHipsterProperties +import tech.jhipster.config.JHipsterProperties import java.nio.charset.StandardCharsets import java.util.Locale diff --git a/generators/server/templates/src/main/kotlin/package/service/UserService.kt.ejs b/generators/server/templates/src/main/kotlin/package/service/UserService.kt.ejs index cdca4be68..8fac26b8c 100644 --- a/generators/server/templates/src/main/kotlin/package/service/UserService.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/service/UserService.kt.ejs @@ -18,13 +18,13 @@ -%> package <%= packageName %>.service -import <%= packageName %>.config.ANONYMOUS_USER import <%= packageName %>.config.DEFAULT_LANGUAGE import <%= packageName %>.config.SYSTEM_ACCOUNT <%_ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') { _%> import <%= packageName %>.domain.Authority <%_ } _%> <%_ if (databaseType !== 'no') { _%> +import <%= packageName %>.service.dto.<%= asDto('AdminUser') %> import <%= packageName %>.domain.<%= asEntity('User') %> <%_ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') { _%> import <%= packageName %>.repository.AuthorityRepository @@ -43,7 +43,7 @@ import <%= packageName %>.security.getCurrentUserLogin <%_ } _%> import <%= packageName %>.service.dto.<%= asDto('User') %> <%_ if (authenticationType !== 'oauth2') { _%> -import io.github.jhipster.security.RandomUtil +import tech.jhipster.security.RandomUtil <%_ } _%> <%_ if (databaseType !== 'no') { _%> @@ -197,7 +197,7 @@ class UserService<% if (databaseType !== 'no') { %>( fun requestPasswordReset(mail: String): <% if (reactive) { %>Mono<% } else { %>Optional<% } %><<%= asEntity('User') %>> { return userRepository.findOneByEmailIgnoreCase(mail) <%_ if (!reactive) { _%> - .filter(<%= asEntity('User') %>::activated) + .filter { it.activated == true } .map { it.resetKey = RandomUtil.generateResetKey() it.resetDate = Instant.now() @@ -224,7 +224,7 @@ class UserService<% if (databaseType !== 'no') { %>( <%_ if (databaseType === 'sql' && reactive) { _%> @Transactional <%_ } _%> - fun registerUser(userDTO: <%= asDto('User') %>, password: String): <% if (reactive) { %>Mono<<%= asEntity('User') %>><% } else { %><%= asEntity('User') %><% } %> { + fun registerUser(userDTO: <%= asDto('AdminUser') %>, password: String): <% if (reactive) { %>Mono<<%= asEntity('User') %>><% } else { %><%= asEntity('User') %><% } %> { val login = userDTO.login ?: throw IllegalArgumentException("Empty login not allowed") val email = userDTO.email <%_ if (!reactive) { _%> @@ -279,7 +279,7 @@ class UserService<% if (databaseType !== 'no') { %>( <%_ } else {// reactive _%> return userRepository.findOneByLogin(login.toLowerCase()) .flatMap { existingUser -> - if (!existingUser.activated) { + if (existingUser.activated == false) { <%_ if (cacheManagerIsAvailable === true) { _%> clearUserCaches(existingUser) <%_ } _%> @@ -290,7 +290,7 @@ class UserService<% if (databaseType !== 'no') { %>( } .then(userRepository.findOneByEmailIgnoreCase(email!!)) .flatMap { existingUser -> - if (!existingUser.activated) { + if (existingUser.activated == false) { <%_ if (cacheManagerIsAvailable === true) { _%> clearUserCaches(existingUser) <%_ } _%> @@ -348,7 +348,7 @@ class UserService<% if (databaseType !== 'no') { %>( <%_ if (!reactive) { _%> private fun removeNonActivatedUser(existingUser: <%= asEntity('User') %>): Boolean { - if (existingUser.activated) { + if (existingUser.activated == true) { return false } userRepository.delete(existingUser) @@ -365,7 +365,7 @@ class UserService<% if (databaseType !== 'no') { %>( <%_ if (databaseType === 'sql' && reactive) { _%> @Transactional <%_ } _%> - fun createUser(userDTO: <%= asDto('User') %>): <% if (reactive) { %>Mono<<%= asEntity('User') %>><% } else { %><%= asEntity('User') %><% } %> { + fun createUser(userDTO: <%= asDto('AdminUser') %>): <% if (reactive) { %>Mono<<%= asEntity('User') %>><% } else { %><%= asEntity('User') %><% } %> { val user = <%= asEntity('User') %>( <%_ if (databaseType === 'cassandra') { _%> id = UUID.randomUUID().toString(), @@ -442,7 +442,7 @@ class UserService<% if (databaseType !== 'no') { %>( <%_ if (databaseType === 'sql' && reactive) { _%> @Transactional <%_ } _%> - fun updateUser(userDTO: <%= asDto('User') %>): <% if (reactive) { %>Mono<% } else { %>Optional<% } %><<%= asDto('User') %>> { + fun updateUser(userDTO: <%= asDto('AdminUser') %>): <% if (reactive) { %>Mono<% } else { %>Optional<% } %><<%= asDto('AdminUser') %>> { <%_ if (!reactive) { _%> return Optional.of(userRepository.findById(userDTO.id!!)) .filter(Optional<<%= asEntity('User') %>>::isPresent) @@ -450,7 +450,7 @@ class UserService<% if (databaseType !== 'no') { %>( .map { user -> <%_ } else { _%> return userRepository.findById(userDTO.id!!) - .<%_ if (['sql', 'mongodb'].includes(databaseType)) { _%>flatMap<% } else { %>map<% } %> { user -> + .<%_ if (['sql', 'mongodb', 'neo4j'].includes(databaseType)) { _%>flatMap<% } else { %>map<% } %> { user -> <%_ } _%> <%_ if (databaseType === 'couchbase') { _%> if (user.login != userDTO.login) { @@ -461,7 +461,7 @@ class UserService<% if (databaseType !== 'no') { %>( clearUserCaches(user) <%_ } _%> user.apply { - login = userDTO.login!!.toLowerCase() + login = userDTO.login?.let{it.toLowerCase()} firstName = userDTO.firstName lastName = userDTO.lastName email = userDTO.email?.toLowerCase() @@ -517,7 +517,7 @@ class UserService<% if (databaseType !== 'no') { %>( <%_ } _%> .doOnNext { log.debug("Changed Information for User: $it") } <%_ } _%> - .map { <%= asDto('User') %>(it) } + .map { <%= asDto('AdminUser') %>(it) } } <%_ if (!reactive) { _%> @@ -561,6 +561,9 @@ class UserService<% if (databaseType !== 'no') { %>( <%_ if (['sql', 'mongodb', 'couchbase', 'neo4j'].includes(databaseType)) { _%> * @param imageUrl image URL of user. <%_ } _%> + <%_ if (reactive) { _%> + * @return a completed {@link Mono}. + <%_ } _%> */ <%_ if (databaseType === 'sql' && reactive) { _%> @Transactional @@ -691,19 +694,30 @@ class UserService<% if (databaseType !== 'no') { %>( @Transactional(readOnly = true) <%_ } _%> <%_ if (['sql', 'mongodb', 'neo4j', 'couchbase'].includes(databaseType)) { _%> - fun getAllManagedUsers(pageable: Pageable): <% if (reactive) { %>Flux<% } else { %>Page<% } %><<%= asDto('User') %>> = - userRepository.findAllByLoginNot(pageable, ANONYMOUS_USER).map { <%= asDto('User') %>(it) } + fun getAllManagedUsers(pageable: Pageable): <% if (reactive) { %>Flux<% } else { %>Page<% } %><<%= asDto('AdminUser') %>> { + return userRepository.findAll<% if (reactive) { %>ByIdNotNull<% } %>(pageable).map { <%= asDto('AdminUser') %>(it) } + } + + <%_ if (databaseType === 'sql') { _%> + @Transactional(readOnly = true) + <%_ } _%> + fun getAllPublicUsers(pageable: Pageable): <% if (reactive) { %>Flux<% } else { %>Page<% } %><<%= asDto('User') %>> { + return userRepository.findAllByIdNotNullAndActivatedIsTrue(pageable).map { <%= asDto('User') %>(it) } + } + <%_ if (reactive) { _%> <%_ if (databaseType === 'sql') { _%> @Transactional(readOnly = true) <%_ } _%> - fun countManagedUsers() = userRepository.countAllByLoginNot(ANONYMOUS_USER) + fun countManagedUsers() = userRepository.count() <%_ } _%> <%_ } else { // Cassandra _%> - fun getAllManagedUsers() = - userRepository.findAll() - .filter { ANONYMOUS_USER != it.login } - .map { <%= asDto('User') %>(it) } + + fun getAllManagedUsers() = userRepository.findAll().map { <%= asDto('AdminUser') %>(it) } + + fun getAllPublicUsers() = userRepository.findAll() + .filter { it.activated == true } + .map { <%= asDto('User') %>(it) } <%_ } _%> <%_ if (databaseType === 'sql') { _%> @@ -888,7 +902,7 @@ class UserService<% if (databaseType !== 'no') { %>( <%_ if (databaseType === 'sql') { _%> @Transactional <%_ } _%> - fun getUserFromAuthentication(authToken: AbstractAuthenticationToken): <% if (!reactive) { %>UserDTO<% } else { %>Mono<% } %> { + fun getUserFromAuthentication(authToken: AbstractAuthenticationToken): <% if (!reactive) { %><%= asDto('AdminUser') %><% } else { %>Mono<<%= asDto('AdminUser') %>><% } %> { val attributes: Map = when (authToken) { is OAuth2AuthenticationToken -> authToken.principal.attributes @@ -903,15 +917,17 @@ class UserService<% if (databaseType !== 'no') { %>( .map { Authority(name = it) } <%_ } _%> .toMutableSet() - return <% if (databaseType !== 'no' && !reactive) { %>UserDTO(syncUserWithIdP(attributes, user))<% } else if (!reactive) { %>user<% } %><% if (databaseType === 'no' && reactive) { %>Mono.just(user)<% } else if (reactive) { %>syncUserWithIdP(attributes, user).flatMap { Mono.just(UserDTO(it)) }<% } %> + return <% if (databaseType !== 'no' && !reactive) { %><%= asDto('AdminUser') %>(syncUserWithIdP(attributes, user))<% } else if (!reactive) { %>user<% } %><% if (databaseType === 'no' && reactive) { %>Mono.just(user)<% } else if (reactive) { %>syncUserWithIdP(attributes, user).flatMap { Mono.just(<%= asDto('AdminUser') %>(it)) }<% } %> } <%_ } _%> <%_ if (cacheManagerIsAvailable === true && databaseType !== 'no') { _%> private fun clearUserCaches(user: <%= asEntity('User') %>) { - cacheManager.getCache(UserRepository.USERS_BY_LOGIN_CACHE)?.evict(user.login!!) - if(user.email != null) { - cacheManager.getCache(UserRepository.USERS_BY_EMAIL_CACHE)?.evict(user.email) + user.login?.let{ + cacheManager.getCache(UserRepository.USERS_BY_LOGIN_CACHE)?.evict(it) + } + user.email?.let { + cacheManager.getCache(UserRepository.USERS_BY_EMAIL_CACHE)?.evict(it) } } <%_ } _%> @@ -920,8 +936,9 @@ class UserService<% if (databaseType !== 'no') { %>( companion object { @JvmStatic - private fun getUser(details: Map): <%= databaseType === 'no' ? asDto('User') : asEntity('User') %> { - val user = <%= databaseType === 'no' ? asDto('User') : asEntity('User') %>() + private fun getUser(details: Map): <%= databaseType === 'no' ? asDto('AdminUser') : asEntity('User') %> { + var activated = true + val user = <%= databaseType === 'no' ? asDto('AdminUser') : asEntity('User') %>() // handle resource server JWT, where sub claim is email and uid is ID if (details["uid"] != null) { user.id = details["uid"] as String @@ -941,7 +958,7 @@ class UserService<% if (databaseType !== 'no') { %>( user.lastName = details["family_name"] as String } if (details["email_verified"] != null) { - user.activated = details["email_verified"] as Boolean + activated = details["email_verified"] as Boolean } if (details["email"] != null) { user.email = (details["email"] as String).toLowerCase() @@ -966,7 +983,7 @@ class UserService<% if (databaseType !== 'no') { %>( if (details["picture"] != null) { user.imageUrl = details["picture"] as String } - user.activated = true + user.activated = activated return user } } diff --git a/generators/server/templates/src/main/kotlin/package/service/dto/AdminUserDTO.kt.ejs b/generators/server/templates/src/main/kotlin/package/service/dto/AdminUserDTO.kt.ejs new file mode 100644 index 000000000..4d4b924d0 --- /dev/null +++ b/generators/server/templates/src/main/kotlin/package/service/dto/AdminUserDTO.kt.ejs @@ -0,0 +1,120 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + +This file is part of the JHipster project, see https://jhipster.github.io/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %>.service.dto + +import <%= packageName %>.config.LOGIN_REGEX +<%_ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j') { _%> +import <%= packageName %>.domain.Authority +<%_ } _%> +<%_ if (databaseType !== 'no') { _%> +import <%= packageName %>.domain.<%= asEntity('User') %> +<%_ } _%> + +import javax.validation.constraints.* +<%_ if (databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase' || databaseType === 'sql') { _%> +import java.time.Instant +<%_ } _%> +<%_ if (user.primaryKey.type === 'UUID') { _%> +import java.util.UUID +<%_ } _%> + +/** + * A DTO representing a user, with his authorities. + */ +open class <%= asDto('AdminUser') %>( + var id: <%= user.primaryKey.type %>? = null, + + @field:NotBlank + @field:Pattern(regexp = LOGIN_REGEX) + @field:Size(min = 1, max = 50) + var login: String? = null, + + @field:Size(max = 50) + var firstName: String? = null, + + @field:Size(max = 50) + var lastName: String? = null, + + @field:Email + @field:Size(min = 5, max = 254) + var email: String? = null, + <%_ if (databaseType !== 'cassandra') { _%> + + @field:Size(max = 256) + var imageUrl: String? = null, + <%_ } _%> + + var activated: Boolean? = false, + + @field:Size(min = 2, max = 10) + var langKey: String? = null, + <%_ if (databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase' || databaseType === 'sql') { _%> + + var createdBy: String? = null, + + var createdDate: Instant? = null, + + var lastModifiedBy: String? = null, + + var lastModifiedDate: Instant? = null, + <%_ } _%> + + var authorities: MutableSet = mutableSetOf() +) { + + <%_ if (databaseType !== 'no') { _%> + constructor(user: <%= asEntity('User') %>?) : this( + user?.id, + user?.login, + user?.firstName, + user?.lastName, + user?.email, + <%_ if (databaseType !== 'cassandra') { _%> + user?.imageUrl, + <%_ } _%> + user?.activated, + user?.langKey, + <%_ if (databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase' || databaseType === 'sql') { _%> + user?.createdBy, + user?.createdDate, + user?.lastModifiedBy, + user?.lastModifiedDate, + <%_ } _%> + + user?.authorities?.<% if (!['sql', 'mongodb', 'neo4j'].includes(databaseType)) { %>toMutableSet()<% } else { %>map { it.name }?.filterNotNullTo(mutableSetOf())<% } %> ?: mutableSetOf() + ) + <%_ } _%> + + override fun toString(): String { + return "<%= asDto('AdminUser') %>{" + + "login='" + login + '\'' + + ", firstName='" + firstName + '\'' + + ", lastName='" + lastName + '\'' + + ", email='" + email + '\'' +<% if (databaseType !== 'cassandra') { %> + ", imageUrl='" + imageUrl + '\'' +<% } %> + ", activated=" + activated + + ", langKey='" + langKey + '\'' +<% if (databaseType === 'mongodb' || databaseType === 'couchbase' || databaseType === 'sql') { %> + ", createdBy=" + createdBy + + ", createdDate=" + createdDate + + ", lastModifiedBy='" + lastModifiedBy + '\'' + + ", lastModifiedDate=" + lastModifiedDate +<% } %> + ", authorities=" + authorities + + "}"; + } +} diff --git a/generators/server/templates/src/main/kotlin/package/service/dto/UserDTO.kt.ejs b/generators/server/templates/src/main/kotlin/package/service/dto/UserDTO.kt.ejs index 41d67e4a3..a6db3243a 100644 --- a/generators/server/templates/src/main/kotlin/package/service/dto/UserDTO.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/service/dto/UserDTO.kt.ejs @@ -18,90 +18,32 @@ -%> package <%= packageName %>.service.dto -import <%= packageName %>.config.LOGIN_REGEX <%_ if (databaseType !== 'no') { _%> import <%= packageName %>.domain.<%= asEntity('User') %> <%_ } _%> -import javax.validation.constraints.Email -import javax.validation.constraints.NotBlank -import javax.validation.constraints.Pattern -import javax.validation.constraints.Size -<%_ if (databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase' || databaseType === 'sql') { _%> - -import java.time.Instant +<%_ if (user.primaryKey.type === 'UUID') { _%> +import java.util.UUID <%_ } _%> - /** - * A DTO representing a user, with his authorities. + * A DTO representing a user, with only the public attributes. */ open class <%= asDto('User') %>( - var id: <% if (databaseType === 'mongodb' || databaseType === 'couchbase' || databaseType === 'neo4j' || databaseType === 'cassandra' || authenticationType === 'oauth2') { %>String<% } else { %>Long<% } %>? = null, - - @field:NotBlank - @field:Pattern(regexp = LOGIN_REGEX) - @field:Size(min = 1, max = 50) + var id: <%= user.primaryKey.type %>? = null, var login: String? = null, - - @field:Size(max = 50) - var firstName: String? = null, - - @field:Size(max = 50) - var lastName: String? = null, - - @field:Email - @field:Size(min = 5, max = 254) - var email: String? = null, - <%_ if (databaseType !== 'cassandra') { _%> - - @field:Size(max = 256) - var imageUrl: String? = null, - <%_ } _%> - - var activated: Boolean = false, - - @field:Size(min = 2, max = 10) - var langKey: String? = null, - <%_ if (databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase' || databaseType === 'sql') { _%> - - var createdBy: String? = null, - - var createdDate: Instant? = null, - - var lastModifiedBy: String? = null, - - var lastModifiedDate: Instant? = null, + <%_ for (field of user.fields.filter(field => !field.builtIn && field.relatedByOtherEntity)) { _%> + val <%= field.fieldName %>: String? = null, <%_ } _%> +){ - var authorities: Set? = null - -) { <%_ if (databaseType !== 'no') { _%> - constructor(user: <%= asEntity('User') %>) : - this( - user.id, user.login, user.firstName, user.lastName, user.email, - <% if (databaseType !== 'cassandra') { %>user.imageUrl, <% } %>user.activated, user.langKey, - <%_ if (databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase' || databaseType === 'sql') { _%> - user.createdBy, user.createdDate, user.lastModifiedBy, user.lastModifiedDate, - <%_ } _%> - <% if (databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'sql') { %>user.authorities.map { it.name }.filterNotNullTo(mutableSetOf())<% } else { %>user.authorities<% } %> - ) + constructor(user: <%= asEntity('User') %>): this(user.id, user.login) <%_ } _%> - - fun isActivated(): Boolean = activated - + override fun toString() = "<%= asDto('User') %>{" + "login='" + login + '\'' + - ", firstName='" + firstName + '\'' + - ", lastName='" + lastName + '\'' + - ", email='" + email + '\'' +<% if (databaseType !== 'cassandra') { %> - ", imageUrl='" + imageUrl + '\'' +<% } %> - ", activated=" + activated + - ", langKey='" + langKey + '\'' +<% if (databaseType === 'mongodb' || databaseType === 'couchbase' || databaseType === 'sql') { %> - ", createdBy=" + createdBy + - ", createdDate=" + createdDate + - ", lastModifiedBy='" + lastModifiedBy + '\'' + - ", lastModifiedDate=" + lastModifiedDate +<% } %> - ", authorities=" + authorities + +<%_ for (field of user.fields.filter(field => !field.builtIn && field.relatedByOtherEntity)) { _%> + ", <%= field.fieldName %>='" + <%= field.fieldName %> + '\'' + +<%_ } _%> "}" } diff --git a/generators/server/templates/src/main/kotlin/package/service/mapper/UserMapper.kt.ejs b/generators/server/templates/src/main/kotlin/package/service/mapper/UserMapper.kt.ejs index 883b09b92..97e6c2536 100644 --- a/generators/server/templates/src/main/kotlin/package/service/mapper/UserMapper.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/service/mapper/UserMapper.kt.ejs @@ -22,10 +22,16 @@ package <%= packageName %>.service.mapper import <%= packageName %>.domain.Authority <%_ } _%> import <%= packageName %>.domain.<%= asEntity('User') %> +import <%= packageName %>.service.dto.<%= asDto('AdminUser') %> import <%= packageName %>.service.dto.<%= asDto('User') %> import org.springframework.stereotype.Service +import org.mapstruct.BeanMapping +import org.mapstruct.Mappings +import org.mapstruct.Mapping +import org.mapstruct.Named + /** * Mapper for the entity [<%= asEntity('User') %>] and its DTO called [<%= asDto('User') %>]. * @@ -42,11 +48,18 @@ class UserMapper { fun userToUserDTO(user: <%= asEntity('User') %>): <%= asDto('User') %> = <%= asDto('User') %>(user) - fun userDTOsToUsers(userDTOs: List<<%= asDto('User') %>?>) = + fun usersToAdminUserDTOs(users: List<<%= asEntity('User') %>>): MutableList<<%= asDto('AdminUser') %>> = + users.asSequence() + .filterNotNull() + .mapTo(mutableListOf()) { userToAdminUserDTO(it) } + + fun userToAdminUserDTO(user: <%= asEntity('User') %>) = <%= asDto('AdminUser') %>(user) + + fun userDTOsToUsers(userDTOs: List<<%= asDto('AdminUser') %>?>) = userDTOs.asSequence() .mapNotNullTo(mutableListOf()) { userDTOToUser(it) } - fun userDTOToUser(userDTO: <%= asDto('User') %>?) = + fun userDTOToUser(userDTO: <%= asDto('AdminUser') %>?) = when (userDTO) { null -> null else -> { @@ -81,5 +94,71 @@ class UserMapper { authoritiesAsString?.filterNotNullTo(mutableSetOf()) ?: mutableSetOf() <%_ } _%> - fun userFromId(id: <% if (databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase' || databaseType === 'cassandra' || authenticationType === 'oauth2') { %>String<% } else { %>Long<% } %>?) = id?.let { <%= asEntity('User') %>(id = it) } + fun userFromId(id: <%= user.primaryKey.type %>?) = id?.let { <%= asEntity('User') %>(id = it) } + + @Named("id") + @BeanMapping(ignoreByDefault = true) + @Mapping(target = "id", source = "id") + fun toDtoId(user: <%= asEntity('User') %>?): <%= asDto('User') %>? { + if (user == null) { + return null + } + val userDto = <%= asDto('User') %>() + userDto.id = user.id + return userDto + } + + @Named("idSet") + @BeanMapping(ignoreByDefault = true) + @Mapping(target = "id", source = "id") + fun toDtoIdSet(users: Set<<%= asEntity('User') %>>?): Set<<%= asDto('User') %>>? { + if ( users == null ) { + return null + } + + val userSet = hashSetOf<<%= asDto('User') %>>() + users.forEach { + this.toDtoId(it)?.let { + userSet.add(it) + } + } + return userSet + } + + @Named("login") + @BeanMapping(ignoreByDefault = true) + @Mappings( + Mapping(target = "id", source = "id"), + Mapping(target = "login", source = "login") + ) + fun toDtoLogin(user: <%= asEntity('User') %>?): <%= asDto('User') %>? { + if (user == null) { + return null + } + val userDto = <%= asDto('User') %>() + userDto.id = user.id + userDto.login = user.login + return userDto + } + + @Named("loginSet") + @BeanMapping(ignoreByDefault = true) + @Mappings( + Mapping(target = "id", source = "id"), + Mapping(target = "login", source = "login") + ) + fun toDtoLoginSet(users: Set<<%= asEntity('User') %>>?): Set<<%= asDto('User') %>>? { + if ( users == null ) { + return null + } + + val userSet = hashSetOf<<%= asDto('User') %>>() + users.forEach { + this.toDtoLogin(it)?.let { + userSet.add(it) + } + } + + return userSet + } } diff --git a/generators/server/templates/src/main/kotlin/package/web/filter/ModifyServersOpenApiFilter.kt.ejs b/generators/server/templates/src/main/kotlin/package/web/filter/ModifyServersOpenApiFilter.kt.ejs new file mode 100644 index 000000000..5a8f9ec32 --- /dev/null +++ b/generators/server/templates/src/main/kotlin/package/web/filter/ModifyServersOpenApiFilter.kt.ejs @@ -0,0 +1,159 @@ +package <%= packageName %>.web.filter + +import com.fasterxml.jackson.core.JsonProcessingException +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.node.ObjectNode +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.io.IOException +import java.util.Objects +import java.util.zip.GZIPInputStream +import java.util.zip.GZIPOutputStream +import org.reactivestreams.Publisher +import org.slf4j.LoggerFactory +import org.springframework.cloud.gateway.filter.GatewayFilterChain +import org.springframework.cloud.gateway.filter.GlobalFilter +import org.springframework.core.Ordered +import org.springframework.core.io.buffer.DataBuffer +import org.springframework.core.io.buffer.DataBufferFactory +import org.springframework.core.io.buffer.DataBufferUtils +import org.springframework.core.io.buffer.DefaultDataBufferFactory +import org.springframework.http.HttpHeaders +import org.springframework.http.server.reactive.ServerHttpResponse +import org.springframework.http.server.reactive.ServerHttpResponseDecorator +import org.springframework.stereotype.Component +import org.springframework.web.server.ServerWebExchange +import reactor.core.publisher.Flux +import reactor.core.publisher.Mono + +@Component +class ModifyServersOpenApiFilter: GlobalFilter, Ordered { + + override fun filter(exchange: ServerWebExchange, chain: GatewayFilterChain): Mono { + val path = exchange.request.uri.path + return if (path.startsWith("/services") && path.contains("/v3/api-docs")) { + val originalResponse = exchange.response + val bufferFactory = originalResponse.bufferFactory() + val decoratedResponse = createModifyServersOpenApiInterceptor(path, originalResponse, bufferFactory) + + // replace response with decorator + chain.filter(exchange.mutate().response(decoratedResponse).build()) + } else { + chain.filter(exchange) + } + } + + override fun getOrder() = -1 + + fun createModifyServersOpenApiInterceptor( + path: String, + originalResponse: ServerHttpResponse, + bufferFactory: DataBufferFactory + ): ModifyServersOpenApiInterceptor { + return ModifyServersOpenApiInterceptor(path, originalResponse, bufferFactory) + } + + class ModifyServersOpenApiInterceptor( + private val path: String, + private val originalResponse: ServerHttpResponse, + private val bufferFactory: DataBufferFactory + ): ServerHttpResponseDecorator(originalResponse) { + + private val log = LoggerFactory.getLogger(javaClass) + + private var rewritedBody = "" + + fun getRewritedBody() = rewritedBody + + override fun writeWith(body: Publisher): Mono { + rewritedBody = "" + if (body is Flux) { + return super.writeWith(body.buffer().map { + rewriteBodyWithServers(it) + }) + } + // when body is not a flux + return super.writeWith(body) + } + + private fun rewriteBodyWithServers(dataBuffers: MutableList): DataBuffer { + val dataBufferFactory = DefaultDataBufferFactory() + val join = dataBufferFactory.join(dataBuffers) + val content = ByteArray(join.readableByteCount()) + join.read(content) + + // release memory + DataBufferUtils.release(join) + val strBody = contentToString(content) + + try { + // create custom server + val mapper = ObjectMapper() + val jsonBody: JsonNode = mapper.readTree(strBody) + val serversToJson = mapper.createObjectNode() + serversToJson.set("url", mapper.valueToTree(path.replace("/v3/api-docs", ""))) + serversToJson.set("description", mapper.valueToTree("added by global filter")) + + // add custom server + val servers = mapper.createArrayNode() + servers.add(serversToJson) + (jsonBody as ObjectNode).set("servers", servers) + rewritedBody = jsonBody.toString() + return rewritedBodyToDataBuffer() + } catch (e: JsonProcessingException) { + log.error("Error when modify servers from api-doc of {}: {}", path, e.message) + } + return join + } + + private fun rewritedBodyToDataBuffer(): DataBuffer { + if (isZippedResponse()) { + val zippedBody = zipContent(rewritedBody) + originalResponse.headers.contentLength = zippedBody.size.toLong() + return bufferFactory.wrap(zippedBody) + } + originalResponse.headers.contentLength = rewritedBody.toByteArray().size.toLong() + return bufferFactory.wrap(rewritedBody.toByteArray()) + } + + private fun contentToString(content: ByteArray): String { + if (isZippedResponse()) { + val unzippedContent = unzipContent(content) + return String(unzippedContent, Charsets.UTF_8) + } + return String(content, Charsets.UTF_8) + } + + private fun isZippedResponse() = + !originalResponse.headers.isEmpty() && + originalResponse.headers[HttpHeaders.CONTENT_ENCODING] != null && + Objects.requireNonNull(originalResponse.headers[HttpHeaders.CONTENT_ENCODING]).contains("gzip") + + private fun unzipContent(content: ByteArray): ByteArray { + try { + val gzipInputStream = GZIPInputStream(ByteArrayInputStream(content)) + val unzippedContent = gzipInputStream.readAllBytes() + gzipInputStream.close() + return unzippedContent + } catch (e: IOException) { + log.error("Error when unzip content during modify servers from api-doc of {}: {}", path, e.message) + } + return content + } + + private fun zipContent(content: String): ByteArray { + try { + val byteArrayOutputStream = ByteArrayOutputStream(content.length) + val gzipOutputStream = GZIPOutputStream(byteArrayOutputStream) + gzipOutputStream.write(content.encodeToByteArray()) + gzipOutputStream.flush() + gzipOutputStream.close() + return byteArrayOutputStream.toByteArray() + } catch ( e: IOException) { + log.error("Error when zip content during modify servers from api-doc of {}: {}", path, e.message) + } + return content.encodeToByteArray() + } + } +} diff --git a/generators/server/templates/src/main/kotlin/package/web/filter/RefreshTokenFilter.kt.ejs b/generators/server/templates/src/main/kotlin/package/web/filter/RefreshTokenFilter.kt.ejs deleted file mode 100755 index f02d97180..000000000 --- a/generators/server/templates/src/main/kotlin/package/web/filter/RefreshTokenFilter.kt.ejs +++ /dev/null @@ -1,130 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.web.filter - -import <%= packageName %>.security.oauth2.OAuth2AuthenticationService -import <%= packageName %>.security.oauth2.OAuth2CookieHelper -import org.slf4j.LoggerFactory -import org.springframework.security.oauth2.common.exceptions.ClientAuthenticationException -import org.springframework.security.oauth2.common.exceptions.InvalidTokenException -import org.springframework.security.oauth2.common.exceptions.UnauthorizedClientException -import org.springframework.security.oauth2.provider.token.TokenStore -import org.springframework.web.client.HttpClientErrorException -import org.springframework.web.filter.GenericFilterBean - -import javax.servlet.FilterChain -import javax.servlet.ServletException -import javax.servlet.ServletRequest -import javax.servlet.ServletResponse -import javax.servlet.http.Cookie -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse -import java.io.IOException - -/** - * Number of seconds before expiry to start refreshing access tokens so we don't run into race conditions when forwarding - * requests downstream. Otherwise, access tokens may still be valid when we check here but may then be expired - * when relayed to another microservice a wee bit later. - */ -private const val REFRESH_WINDOW_SECS = 30 - -/** - * Filters incoming requests and refreshes the access token before it expires. - */ -class RefreshTokenFilter( - /** - * The [OAuth2AuthenticationService] is doing the actual work. We are just a simple filter after all. - */ - private val authenticationService: OAuth2AuthenticationService, - private val tokenStore: TokenStore -) : GenericFilterBean() { - - private val log = LoggerFactory.getLogger(javaClass) - - /** - * Check access token cookie and refresh it, if it is either not present, expired or about to expire. - */ - @Throws(IOException::class, ServletException::class) - override fun doFilter(servletRequest: ServletRequest, servletResponse: ServletResponse, filterChain: FilterChain) { - var httpServletRequest = servletRequest as HttpServletRequest - val httpServletResponse = servletResponse as HttpServletResponse - httpServletRequest = try { - refreshTokensIfExpiring(httpServletRequest, httpServletResponse) - } catch (ex: ClientAuthenticationException) { - log.warn("Security exception: could not refresh tokens $ex") - authenticationService.stripTokens(httpServletRequest) - } - - filterChain.doFilter(httpServletRequest, servletResponse) - } - - /** - * Refresh the access and refresh tokens if they are about to expire. - * - * @param httpServletRequest the servlet request holding the current cookies. If no refresh cookie is present, - * then we are out of luck. - * @param httpServletResponse the servlet response that gets the new set-cookie headers, if they had to be - * refreshed. - * @return a new request to use downstream that contains the new cookies, if they had to be refreshed. - * @throws InvalidTokenException if the tokens could not be refreshed. - */ - fun refreshTokensIfExpiring( - httpServletRequest: HttpServletRequest, - httpServletResponse: HttpServletResponse - ): HttpServletRequest { - var newHttpServletRequest = httpServletRequest - // get access token from cookie - val accessTokenCookie = OAuth2CookieHelper.getAccessTokenCookie(httpServletRequest) - if (mustRefreshToken(accessTokenCookie)) { // we either have no access token, or it is expired, or it is about to expire - // get the refresh token cookie and, if present, request new tokens - val refreshCookie = OAuth2CookieHelper.getRefreshTokenCookie(httpServletRequest) - if (refreshCookie != null) { - try { - newHttpServletRequest = - authenticationService.refreshToken(httpServletRequest, httpServletResponse, refreshCookie) - } catch (ex: HttpClientErrorException) { - throw UnauthorizedClientException("could not refresh OAuth2 token", ex) - } - } else if (accessTokenCookie != null) { - log.warn("access token found, but no refresh token, stripping them all") - val token = tokenStore.readAccessToken(accessTokenCookie.value) - if (token.isExpired || token.expiresIn < REFRESH_WINDOW_SECS) { - throw InvalidTokenException("access token has expired, or expires within " + REFRESH_WINDOW_SECS + " seconds, but there's no refresh token") - } - } - } - return newHttpServletRequest - } - - /** - * Check if we must refresh the access token. - * We must refresh it, if we either have no access token, or it is expired, or it is about to expire. - * - * @param accessTokenCookie the current access token. - * @return true, if it must be refreshed; false, otherwise. - */ - private fun mustRefreshToken(accessTokenCookie: Cookie?): Boolean { - if (accessTokenCookie == null) { - return true - } - val token = tokenStore.readAccessToken(accessTokenCookie.value) - // check if token is expired or about to expire - return token.isExpired || token.expiresIn < REFRESH_WINDOW_SECS - } -} diff --git a/generators/server/templates/src/main/kotlin/package/web/filter/RefreshTokenFilterConfigurer.kt.ejs b/generators/server/templates/src/main/kotlin/package/web/filter/RefreshTokenFilterConfigurer.kt.ejs deleted file mode 100755 index ee0ef2dc5..000000000 --- a/generators/server/templates/src/main/kotlin/package/web/filter/RefreshTokenFilterConfigurer.kt.ejs +++ /dev/null @@ -1,50 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.web.filter - -import <%= packageName %>.security.oauth2.OAuth2AuthenticationService - -import org.springframework.security.config.annotation.SecurityConfigurerAdapter -import org.springframework.security.config.annotation.web.builders.HttpSecurity -import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter -import org.springframework.security.oauth2.provider.token.TokenStore -import org.springframework.security.web.DefaultSecurityFilterChain - -/** - * Configures a [RefreshTokenFilter] to refresh access tokens if they are about to expire. - * - * @see RefreshTokenFilter - */ -class RefreshTokenFilterConfigurer( - /** - * [RefreshTokenFilter] needs the [OAuth2AuthenticationService] to refresh cookies using the refresh token. - */ - private val authenticationService: OAuth2AuthenticationService, - private val tokenStore: TokenStore -) : SecurityConfigurerAdapter() { - - /** - * Install [RefreshTokenFilter] as a servlet Filter. - */ - @Throws(Exception::class) - override fun configure(http: HttpSecurity) { - val customFilter = RefreshTokenFilter(authenticationService, tokenStore) - http.addFilterBefore(customFilter, OAuth2AuthenticationProcessingFilter::class.java) - } -} diff --git a/generators/server/templates/src/main/kotlin/package/web/filter/RouteDetectorFilter.kt.ejs b/generators/server/templates/src/main/kotlin/package/web/filter/RouteDetectorFilter.kt.ejs deleted file mode 100644 index 50b03ce15..000000000 --- a/generators/server/templates/src/main/kotlin/package/web/filter/RouteDetectorFilter.kt.ejs +++ /dev/null @@ -1,102 +0,0 @@ -<%# - Copyright 2013-2019 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License") - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.web.filter - -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.springframework.beans.factory.annotation.Qualifier -import org.springframework.cloud.netflix.zuul.filters.ZuulProperties -import org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping -import org.springframework.core.annotation.Order -import org.springframework.http.ResponseEntity -import org.springframework.stereotype.Component -import org.springframework.web.client.RestTemplate - -import javax.servlet.* -import javax.servlet.http.HttpServletRequest -import java.io.IOException -import java.net.URI -import java.net.URISyntaxException -import java.util.HashSet -import java.util.regex.Matcher -import java.util.regex.Pattern - -/** - * Detects if a call is to be forwarded to a microservice and adds it to zuul routes - */ -@Component -@Order(1) -class RouteDetectorFilter(@Qualifier("restTemplate") private val restTemplate: RestTemplate, private val zuulProperties: ZuulProperties, private val zuulHandlerMapping: ZuulHandlerMapping): Filter { - private val log = LoggerFactory.getLogger(RouteDetectorFilter::class.java) - - @Throws(IOException::class) - override fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) { - - val requestURL = (request as HttpServletRequest).getRequestURI() - - val pattern = Pattern.compile("/services/(.*?)/.*") - val matcher = pattern.matcher(requestURL) - - // match a service-call by a rule like /services/{serviceName}/** - if (matcher.find()) { - val serviceName = matcher.group(1) - - // test, if the service is missing in zuul routes - if (!zuulProperties.getRoutes().containsKey(serviceName)) { - try { - val uri = URI( - "http", - null, - serviceName, - 80, - "/management/health", - null, - null - ) - - // try to reach the health endpoint - val responseEntity = restTemplate.getForEntity(uri, String::class.java) - if (!responseEntity.getStatusCode().isError()) { - val route = ZuulProperties.ZuulRoute( - serviceName, - "/" + serviceName + "/**", - null, - "http://" + serviceName + "/", - true, - false, - hashSetOf() - ) - - // update routes - zuulProperties.getRoutes().put(serviceName, route) - zuulHandlerMapping.setDirty(true) - log.info("added route $route dynamically") - } else { - log.warn("could not reach health endpoint of service $serviceName") - } - } catch (e: URISyntaxException) { - log.error("could not parse URI $e") - } - } - - } - - chain.doFilter(request, response) - } -} diff --git a/generators/server/templates/src/main/kotlin/package/web/filter/SpaWebFilter.kt.ejs b/generators/server/templates/src/main/kotlin/package/web/filter/SpaWebFilter.kt.ejs index 4e226276a..b5d034283 100644 --- a/generators/server/templates/src/main/kotlin/package/web/filter/SpaWebFilter.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/web/filter/SpaWebFilter.kt.ejs @@ -30,7 +30,7 @@ class SpaWebFilter : WebFilter { val path = exchange.request.uri.path if(!path.startsWith("/api") && !path.startsWith("/management")<% if (authenticationType === 'oauth2') { %> && !path.startsWith("/login")<% } %> <%_ if (applicationType === 'gateway' || applicationType === 'monolith') { _%> - && !path.startsWith("/services") && !path.startsWith("/swagger") && !path.startsWith("/v2/api-docs") + && !path.startsWith("/services") && !path.startsWith("/swagger") && !path.startsWith("/v2/api-docs") && !path.startsWith("/v3/api-docs") <%_ } _%> && path.matches(Regex("[^\\\\.]*"))) { return chain.filter(exchange.mutate().request(exchange.request.mutate().path("/index.html").build()).build()) diff --git a/generators/server/templates/src/main/kotlin/package/web/rest/AccountResource.kt.ejs b/generators/server/templates/src/main/kotlin/package/web/rest/AccountResource.kt.ejs index 8865fe107..1850e6b2c 100644 --- a/generators/server/templates/src/main/kotlin/package/web/rest/AccountResource.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/web/rest/AccountResource.kt.ejs @@ -23,6 +23,7 @@ package <%= packageName %>.web.rest import <%= packageName %>.security.getCurrentUserLogin <%_ } _%> import <%= packageName %>.service.UserService +import <%= packageName %>.service.dto.<%= asDto('AdminUser') %> import <%= packageName %>.service.dto.<%= asDto('User') %> import org.slf4j.LoggerFactory @@ -57,7 +58,7 @@ class AccountResource(private val userService: UserService) { * @throws AccountResourceException `500 (Internal Server Error)` if the user couldn't be returned. */ @GetMapping("/account") - fun getAccount(principal: Principal?): <% if (reactive) { %>Mono<<%= asDto('User') %>><% } else { %><%= asDto('User') %><% } %> = + fun getAccount(principal: Principal?): <% if (reactive) { %>Mono<<%= asDto('AdminUser') %>><% } else { %><%= asDto('AdminUser') %><% } %> = if (principal is AbstractAuthenticationToken) { userService.getUserFromAuthentication(principal) } else { @@ -145,6 +146,7 @@ import <%= packageName %>.security.getCurrentUserLogin import <%= packageName %>.service.MailService import <%= packageName %>.service.UserService import <%= packageName %>.service.dto.PasswordChangeDTO +import <%= packageName %>.service.dto.<%= asDto('AdminUser') %> import <%= packageName %>.service.dto.<%= asDto('User') %> import <%= packageName %>.web.rest.errors.EmailAlreadyUsedException import <%= packageName %>.web.rest.errors.InvalidPasswordException @@ -152,9 +154,7 @@ import <%= packageName %>.web.rest.errors.LoginAlreadyUsedException import <%= packageName %>.web.rest.vm.KeyAndPasswordVM import <%= packageName %>.web.rest.vm.ManagedUserVM -<% if (authenticationType === 'session' && !reactive) { %> import org.apache.commons.lang3.StringUtils -<% } %> import org.slf4j.LoggerFactory import org.springframework.http.HttpStatus <% if (authenticationType === 'session' && !reactive) { %> @@ -214,7 +214,7 @@ class AccountResource( @PostMapping("/register") @ResponseStatus(HttpStatus.CREATED) fun registerAccount(@Valid @RequestBody managedUserVM: ManagedUserVM) <% if (reactive) { %>: Mono <% } %>{ - if (!checkPasswordLength(managedUserVM.password)) { + if (isPasswordLengthInvalid(managedUserVM.password)) { throw InvalidPasswordException() } <%_ if (!reactive) { _%> @@ -272,9 +272,9 @@ class AccountResource( * @throws RuntimeException `500 (Internal Server Error)` if the user couldn't be returned. */ @GetMapping("/account") - fun getAccount(): <% if (reactive) { %>Mono<<%= asDto('User') %>><% } else { %><%= asDto('User') %><% } %> = + fun getAccount(): <% if (reactive) { %>Mono<<%= asDto('AdminUser') %>><% } else { %><%= asDto('AdminUser') %><% } %> = userService.getUserWithAuthorities() - .map { <%= asDto('User') %>(it) } + .map { <%= asDto('AdminUser') %>(it) } <%_ if (!reactive) { _%> .orElseThrow { AccountResourceException("User could not be found") } <%_ } else { _%> @@ -290,7 +290,7 @@ class AccountResource( */ @PostMapping("/account") <%_ if (!reactive) { _%> - fun saveAccount(@Valid @RequestBody userDTO: <%= asDto('User') %>) { + fun saveAccount(@Valid @RequestBody userDTO: <%= asDto('AdminUser') %>) { val userLogin = getCurrentUserLogin() .orElseThrow { AccountResourceException("") } val existingUser = userRepository.findOneByEmailIgnoreCase(userDTO.email) @@ -307,7 +307,7 @@ class AccountResource( ) } <%_ } else { _%> - fun saveAccount(@Valid @RequestBody userDTO: <%= asDto('User') %>): Mono = + fun saveAccount(@Valid @RequestBody userDTO: <%= asDto('AdminUser') %>): Mono = getCurrentUserLogin() .switchIfEmpty(Mono.error(AccountResourceException("Current user login not found"))) .flatMap { userLogin -> @@ -337,7 +337,7 @@ class AccountResource( */ @PostMapping(path = ["/account/change-password"]) fun changePassword(@RequestBody passwordChangeDto: PasswordChangeDTO) <% if (reactive) { %>: Mono <% } %>{ - if (!checkPasswordLength(passwordChangeDto.newPassword)) { + if (isPasswordLengthInvalid(passwordChangeDto.newPassword)) { throw InvalidPasswordException() } <% if (reactive) { %>return <% } %>userService.changePassword(passwordChangeDto.currentPassword!!, passwordChangeDto.newPassword!!) @@ -432,7 +432,7 @@ class AccountResource( */ @PostMapping(path = ["/account/reset-password/finish"]) fun finishPasswordReset(@RequestBody keyAndPassword: KeyAndPasswordVM) <% if (reactive) { %>: Mono <% } %>{ - if (!checkPasswordLength(keyAndPassword.newPassword)) { + if (isPasswordLengthInvalid(keyAndPassword.newPassword)) { throw InvalidPasswordException() } <%_ if (!reactive) { _%> @@ -449,8 +449,5 @@ class AccountResource( } } -private fun checkPasswordLength(password: String?) = - !password.isNullOrEmpty() && - password.length >= ManagedUserVM.PASSWORD_MIN_LENGTH && - password.length <= ManagedUserVM.PASSWORD_MAX_LENGTH +private fun isPasswordLengthInvalid(password: String?) = password.isNullOrEmpty() || password.length < ManagedUserVM.PASSWORD_MIN_LENGTH || password.length > ManagedUserVM.PASSWORD_MAX_LENGTH <%_ } _%> diff --git a/generators/server/templates/src/main/kotlin/package/web/rest/AuditResource.kt.ejs b/generators/server/templates/src/main/kotlin/package/web/rest/AuditResource.kt.ejs deleted file mode 100644 index 65069329c..000000000 --- a/generators/server/templates/src/main/kotlin/package/web/rest/AuditResource.kt.ejs +++ /dev/null @@ -1,137 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.web.rest - -import <%= packageName %>.service.AuditEventService - -import io.github.jhipster.web.util.PaginationUtil -<%_ if (!reactive) { _%> -import io.github.jhipster.web.util.ResponseUtil -<%_ } _%> -import org.springframework.boot.actuate.audit.AuditEvent -import org.springframework.data.domain.Pageable -import org.springframework.http.HttpStatus -import org.springframework.http.ResponseEntity -<%_ if (reactive) { _%> -import org.springframework.data.domain.PageImpl -import org.springframework.http.server.reactive.ServerHttpRequest -<%_ } _%> -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.PathVariable -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RequestParam -import org.springframework.web.bind.annotation.RestController -<%_ if (!reactive) { _%> -import org.springframework.web.servlet.support.ServletUriComponentsBuilder -<%_ } else { _%> -import org.springframework.web.server.ResponseStatusException -import org.springframework.web.util.UriComponentsBuilder -import reactor.core.publisher.Flux -import reactor.core.publisher.Mono -import reactor.core.publisher.switchIfEmpty -<%_ } _%> - -import java.time.Instant -import java.time.LocalDate -import java.time.ZoneId - -/** - * REST controller for getting the `AuditEvent`s. - */ -@RestController -@RequestMapping("/management/audits") -class AuditResource(private val auditEventService: AuditEventService) { - - /** - * `GET /audits` : get a page of `AuditEvent`s. - * - <%_ if (reactive) { _%> - * @param request a [ServerHttpRequest] request. - <%_ } _%> - * @param pageable the pagination information. - * @return the `ResponseEntity` with status `200 (OK)` and the list of `AuditEvent`s in body. - */ - @GetMapping - <%_ if (!reactive) { _%> - fun getAll(pageable: Pageable): ResponseEntity> { - val page = auditEventService.findAll(pageable) - val headers = PaginationUtil.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page) - return ResponseEntity(page.content, headers, HttpStatus.OK) - } - <%_ } else { _%> - fun getAll(request: ServerHttpRequest, pageable: Pageable): Mono>> { - return auditEventService.count() - .map { PageImpl(listOf(), pageable, it) } - .map { PaginationUtil.generatePaginationHttpHeaders(UriComponentsBuilder.fromHttpRequest(request), it) } - .map { ResponseEntity.ok().headers(it).body(auditEventService.findAll(pageable)) } - } - <%_ } _%> - - /** - * `GET /audits` : get a page of `AuditEvent`s between the `fromDate` and `toDate`. - * - * @param fromDate the start of the time period of `AuditEvent`s to get. - * @param toDate the end of the time period of `AuditEvent`s to get. - <%_ if (reactive) { _%> - * @param request a [ServerHttpRequest] request. - <%_ } _%> - * @param pageable the pagination information. - * @return the `ResponseEntity` with status `200 (OK)` and the list of `AuditEvent`s in body. - */ - @GetMapping(params = ["fromDate", "toDate"]) - fun getByDates( - @RequestParam(value = "fromDate") fromDate: LocalDate, - @RequestParam(value = "toDate") toDate: LocalDate, - <%_ if (reactive) { _%> - request: ServerHttpRequest, - <%_ } _%> - pageable: Pageable - ): <% if (!reactive) { %>ResponseEntity><% } else { %>Mono>><% } %> { - - val from = fromDate.atStartOfDay(ZoneId.systemDefault()).toInstant() - val to = toDate.atStartOfDay(ZoneId.systemDefault()).plusDays(1).toInstant() - - <%_ if (!reactive) { _%> - val page = auditEventService.findByDates(from, to, pageable) - val headers = PaginationUtil.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page) - return ResponseEntity(page.content, headers, HttpStatus.OK) - <%_ } else { _%> - val events = auditEventService.findByDates(from, to, pageable) - return auditEventService.countByDates(from, to) - .map { PageImpl(listOf(), pageable, it) } - .map { PaginationUtil.generatePaginationHttpHeaders(UriComponentsBuilder.fromHttpRequest(request), it) } - .map { ResponseEntity.ok().headers(it).body(events) } - <%_ } _%> - } - - /** - * `GET /audits/:id` : get an `AuditEvent` by id. - * - * @param id the id of the entity to get. - * @return the `ResponseEntity` with status `200 (OK)` and the AuditEvent in body, or status `404 (Not Found)`. - */ - @GetMapping("/{id:.+}") - <%_ if (!reactive) { _%> - fun get(@PathVariable id: <%= pkType %>?): ResponseEntity = - ResponseUtil.wrapOrNotFound(auditEventService.find(id!!)) - <%_ } else { _%> - fun get(@PathVariable id: <%= pkType %>?) = auditEventService.find(id!!) - .switchIfEmpty { Mono.error(ResponseStatusException(HttpStatus.NOT_FOUND)) } - <%_ } _%> -} diff --git a/generators/server/templates/src/main/kotlin/package/web/rest/AuthResource.kt.ejs b/generators/server/templates/src/main/kotlin/package/web/rest/AuthResource.kt.ejs deleted file mode 100755 index a6cf62b20..000000000 --- a/generators/server/templates/src/main/kotlin/package/web/rest/AuthResource.kt.ejs +++ /dev/null @@ -1,79 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.web.rest - -import <%= packageName %>.security.oauth2.OAuth2AuthenticationService -import org.slf4j.LoggerFactory -import org.springframework.http.MediaType -import org.springframework.http.ResponseEntity -import org.springframework.security.core.context.SecurityContextHolder -import org.springframework.security.oauth2.common.OAuth2AccessToken -import org.springframework.web.bind.annotation.RequestBody -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RequestMethod -import org.springframework.web.bind.annotation.RestController - -import javax.servlet.http.HttpServletRequest -import javax.servlet.http.HttpServletResponse - -/** - * Authentication endpoint for web client. - * Used to authenticate a user using OAuth2 access tokens or log him out. - * - * @author markus.oellinger - */ -@RestController -@RequestMapping("/auth") -class AuthResource(private val authenticationService: OAuth2AuthenticationService) { - - private val log = LoggerFactory.getLogger(javaClass) - - /** - * Authenticates a user setting the access and refresh token cookies. - * - * @param request the [HttpServletRequest] holding - among others - the headers passed from the client. - * @param response the [HttpServletResponse] getting the cookies set upon successful authentication. - * @param params the login params (username, password, rememberMe). - * @return the access token of the authenticated user. Will return an error code if it fails to authenticate the user. - */ - @RequestMapping( - value = ["/login"], method = [RequestMethod.POST], - consumes = [MediaType.APPLICATION_JSON_VALUE], produces = [MediaType.APPLICATION_JSON_VALUE] - ) - fun authenticate( - request: HttpServletRequest, - response: HttpServletResponse, - @RequestBody - params: Map - ): ResponseEntity = authenticationService.authenticate(request, response, params) - - /** - * Logout current user deleting his cookies. - * - * @param request the [HttpServletRequest] holding - among others - the headers passed from the client. - * @param response the [HttpServletResponse] getting the cookies set upon successful authentication. - * @return an empty response entity. - */ - @RequestMapping(value = ["/logout"], method = [RequestMethod.POST]) - fun logout(request: HttpServletRequest, response: HttpServletResponse): ResponseEntity<*> { - log.info("logging out user ${SecurityContextHolder.getContext().authentication.name}") - authenticationService.logout(request, response) - return ResponseEntity.noContent().build() - } -} diff --git a/generators/server/templates/src/main/kotlin/package/web/rest/GatewayResource.kt.ejs b/generators/server/templates/src/main/kotlin/package/web/rest/GatewayResource.kt.ejs index 460c6f066..748cc06e4 100644 --- a/generators/server/templates/src/main/kotlin/package/web/rest/GatewayResource.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/web/rest/GatewayResource.kt.ejs @@ -22,14 +22,10 @@ import <%= packageName %>.web.rest.vm.RouteVM import <%= packageName %>.security.ADMIN import org.springframework.cloud.client.discovery.DiscoveryClient -<%_ if (!reactive) { _%> -import org.springframework.cloud.netflix.zuul.filters.RouteLocator -<%_ } else { _%> import org.springframework.beans.factory.annotation.Value import org.springframework.cloud.gateway.route.Route import org.springframework.cloud.gateway.route.RouteLocator import reactor.core.publisher.Flux -<%_ } _%> import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.security.access.annotation.Secured @@ -52,33 +48,22 @@ class GatewayResource(private val routeLocator: RouteLocator, private val discov @GetMapping("/routes") @Secured(ADMIN) fun activeRoutes(): ResponseEntity> { - <%_ if (!reactive) { _%> - val routeVMs = - routeLocator.routes.mapNotNull { route -> - RouteVM( - path = route.fullPath, - serviceId = route.id, - serviceInstances = discoveryClient.getInstances(route.location) - ) + val routes = routeLocator.routes + val routeVMs = mutableListOf() + routes.subscribe { route -> + val routeVM = RouteVM() + // Manipulate strings to make Gateway routes look like Zuul's + val predicate = route.predicate.toString() + val path = predicate.substring(predicate.indexOf("[") + 1, predicate.indexOf("]")) + routeVM.path = path + val serviceId = route.id.substring(route.id.indexOf("_") + 1).toLowerCase() + routeVM.serviceId = serviceId + // Exclude gateway app from routes + if (serviceId.toLowerCase() != appName.toLowerCase()) { + routeVM.serviceInstances = discoveryClient.getInstances(serviceId) + routeVMs.add(routeVM) } - <%_ } else { _%> - val routes = routeLocator.routes - val routeVMs = mutableListOf() - routes.subscribe { route -> - val routeVM = RouteVM() - // Manipulate strings to make Gateway routes look like Zuul's - val predicate = route.predicate.toString() - val path = predicate.substring(predicate.indexOf("[") + 1, predicate.indexOf("]")) - routeVM.path = path - val serviceId = route.id.substring(route.id.indexOf("_") + 1).toLowerCase() - routeVM.serviceId = serviceId - // Exclude gateway app from routes - if (serviceId.toLowerCase() != appName.toLowerCase()) { - routeVM.serviceInstances = discoveryClient.getInstances(serviceId) - routeVMs.add(routeVM) - } - } - <%_ } _%> + } return ResponseEntity.ok(routeVMs) } } diff --git a/generators/server/templates/src/main/kotlin/package/web/rest/LogoutResource.kt.ejs b/generators/server/templates/src/main/kotlin/package/web/rest/LogoutResource.kt.ejs index 488e8dc9f..31b66120c 100644 --- a/generators/server/templates/src/main/kotlin/package/web/rest/LogoutResource.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/web/rest/LogoutResource.kt.ejs @@ -47,6 +47,9 @@ class LogoutResource(registrations: <% if (reactive) { %>Reactive<% } %>ClientRe * @param request the [HttpServletRequest]. <%_ } _%> * @param idToken the ID token. + <%_ if (reactive) { _%> + * @param session the current {@link WebSession}. + <%_ } _%> * @return the [ResponseEntity] with status `200 (OK)` and a body with a global logout URL and ID token. */ @PostMapping("/api/logout") diff --git a/generators/server/templates/src/main/kotlin/package/web/rest/PublicUserResource.kt.ejs b/generators/server/templates/src/main/kotlin/package/web/rest/PublicUserResource.kt.ejs new file mode 100644 index 000000000..cf00fdd6e --- /dev/null +++ b/generators/server/templates/src/main/kotlin/package/web/rest/PublicUserResource.kt.ejs @@ -0,0 +1,171 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + +This file is part of the JHipster project, see https://jhipster.github.io/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %>.web.rest + +<%_ if (searchEngine === 'elasticsearch') { _%> +import <%= packageName %>.repository.search.UserSearchRepository +<%_ } _%> +<%_ if (authenticationType !== 'oauth2') { _%> +import org.springframework.data.domain.Sort +import java.util.Collections +<%_ } _%> +import <%= packageName %>.service.UserService +import <%= packageName %>.service.dto.<%= asDto('User') %> + +<%_ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') { _%> +import tech.jhipster.web.util.PaginationUtil +<%_ } _%> + +import org.slf4j.LoggerFactory +<%_ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') { _%> + <%_ if (!reactive) { _%> +import org.springframework.data.domain.Page + <%_ } else { _%> +import org.springframework.data.domain.PageImpl + <%_ } _%> +import org.springframework.data.domain.Pageable + <%_ if (!reactive) { _%> +import org.springframework.http.HttpHeaders + <%_ } _%> +<%_ } _%> +import org.springframework.http.HttpStatus +import org.springframework.http.ResponseEntity +<%_ if (reactive) { _%> +import org.springframework.http.server.reactive.ServerHttpRequest +<%_ } _%> +import org.springframework.web.bind.annotation.* +<%_ if (!reactive) { _%> +import org.springframework.web.servlet.support.ServletUriComponentsBuilder +<%_ } _%> +<%_ if (reactive) { _%> +import org.springframework.web.server.ResponseStatusException +import org.springframework.web.util.UriComponentsBuilder +import reactor.core.publisher.Flux +import reactor.core.publisher.Mono +<%_ } _%> + +<%_ if (!reactive) { _%> +import java.util.* +<%_ } _%> +<%_ if (reactive) { _%> +import java.util.ArrayList +import java.util.List +import java.util.Arrays +<%_ } _%> +<%_ if (searchEngine === 'elasticsearch' && !reactive) { _%> +import java.util.stream.Collectors +import java.util.stream.StreamSupport + +import org.elasticsearch.index.query.QueryBuilders.* +<%_ } _%> + +@RestController +@RequestMapping("/api") +class PublicUserResource( + private val userService: UserService<%_ if (searchEngine === 'elasticsearch') { _%>, + private val userSearchRepository: UserSearchRepository<% } %> +) { + <%_ if (authenticationType !== 'oauth2') { _%> + companion object { + private val ALLOWED_ORDERED_PROPERTIES = arrayOf("id", "login", "firstName", "lastName", "email", "activated", "langKey") + } + <%_ } _%> + + private val log = LoggerFactory.getLogger(javaClass) + + /** + * {@code GET /users} : get all users with only the public informations - calling this are allowed for anyone. + *<% if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType == 'neo4j' || databaseType === 'couchbase') { %> + <%_ if (reactive) { _%> + * @param request a {@link ServerHttpRequest} request. + <%_ } _%> + * @param pageable the pagination information.<% } %> + * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body all users. + */ + @GetMapping("/users") + <%_ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') { _%> + <%_ if (!reactive) { _%> + fun getAllPublicUsers(pageable: Pageable): ResponseEntity>> { + log.debug("REST request to get all public User names") + <%_ if (authenticationType !== 'oauth2') { _%> + if (!onlyContainsAllowedProperties(pageable)) { + return ResponseEntity.badRequest().build() + } + <%_ } _%> + + val page = userService.getAllPublicUsers(pageable) + val headers = PaginationUtil.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page) + return ResponseEntity(page.content, headers, HttpStatus.OK) + } + <%_ } else { _%> + fun getAllPublicUsers(request: ServerHttpRequest, pageable: Pageable): Mono>>> { + log.debug("REST request to get all public User names") + <%_ if (authenticationType !== 'oauth2') { _%> + if (!onlyContainsAllowedProperties(pageable)) { + return Mono.just(ResponseEntity.badRequest().build()) + } + <%_ } _%> + + return userService.countManagedUsers() + .map { PageImpl<<%= asDto('User') %>>(listOf(), pageable, it) } + .map { PaginationUtil.generatePaginationHttpHeaders(UriComponentsBuilder.fromHttpRequest(request), it) } + .map { ResponseEntity.ok().headers(it).body(userService.getAllPublicUsers(pageable)) } + } + <%_ } _%> + <%_ if (authenticationType !== 'oauth2') { _%> + private fun onlyContainsAllowedProperties(pageable: Pageable) = + pageable.sort.map(Sort.Order::getProperty).all(ALLOWED_ORDERED_PROPERTIES::contains) + <%_ } _%> + + /** + * Gets a list of all roles. + * @return a string list of all roles. + */ + @GetMapping("/authorities") + fun getAuthorities() = userService.getAuthorities()<% if (reactive) { %>.collectList()<% } %> + + <%_ } else { // Cassandra _%> + fun getAllPublicUsers(): <% if (reactive) { %>Flux<% } else { %>List<% } %><<%= asDto('User') %>> = userService.getAllPublicUsers() + + <%_ } _%> + + <%_ if (searchEngine !== false) { _%> + + /** + * {@code SEARCH /_search/users/:query} : search for the User corresponding to the query. + * + * @param query the query to search. + * @return the result of the search. + */ + @GetMapping("/_search/users/{query}") + fun search(@PathVariable query: String): <% if(reactive) { %>MonoList<<%= asDto('User') %>><% if(reactive) { %>><% } %> { + <%/* TODO fix this */%> + <%_ if (searchEngine === 'elasticsearch') { _%> + <%_ if (!reactive) { _%> + return userSearchRepository.search(queryStringQuery(query)).map { <%= asDto('User') %>(it) } + <%_ } else { _%> + return userSearchRepository.search(query).map { <%= asDto('User') %>(it) }.collectList() + <%_ } _%> + <%_ } else { _%> + return userRepository.search(User.PREFIX, query)<% if (reactive) { %>.collectList()<% } %> + <%_ } _%> + } +<%_ } _%> + +} diff --git a/generators/server/templates/src/main/kotlin/package/web/rest/UserJWTController.kt.ejs b/generators/server/templates/src/main/kotlin/package/web/rest/UserJWTController.kt.ejs index 2f150272c..46ae878a1 100644 --- a/generators/server/templates/src/main/kotlin/package/web/rest/UserJWTController.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/web/rest/UserJWTController.kt.ejs @@ -16,19 +16,10 @@ See the License for the specific language governing permissions and limitations under the License. -%> -<%_ -let withAudit = reactive && ['sql', 'mongodb', 'couchbase', 'neo4j'].includes(databaseType); -_%> package <%= packageName %>.web.rest -<%_ if (withAudit) { _%> -import <%= packageName %>.config.ANONYMOUS_USER -<%_ } _%> import <%= packageName %>.security.jwt.JWTFilter import <%= packageName %>.security.jwt.TokenProvider -<%_ if (withAudit) { _%> -import <%= packageName %>.service.AuditEventService -<%_ } _%> import <%= packageName %>.web.rest.vm.LoginVM import com.fasterxml.jackson.annotation.JsonProperty @@ -40,9 +31,6 @@ import org.springframework.http.ResponseEntity import org.springframework.security.authentication.ReactiveAuthenticationManager <%_ } _%> import org.springframework.security.authentication.UsernamePasswordAuthenticationToken -<%_ if (withAudit) { _%> -import org.springframework.security.core.Authentication -<%_ } _%> <%_ if (!reactive) { _%> import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder import org.springframework.security.core.context.SecurityContextHolder @@ -65,10 +53,11 @@ import javax.validation.Valid @RequestMapping("/api") class UserJWTController( private val tokenProvider: TokenProvider, - <% if (!reactive) { %>private val authenticationManagerBuilder: AuthenticationManagerBuilder <% } else { %> - private val authenticationManager: ReactiveAuthenticationManager<% if (withAudit) { %>, - private val auditEventService: AuditEventService<% } %> - <% } %> + <%_ if (!reactive) { _%> + private val authenticationManagerBuilder: AuthenticationManagerBuilder + <%_ } else { _%> + private val authenticationManager: ReactiveAuthenticationManager + <%_ } _%> ) { <%_ if (!reactive) { _%> @PostMapping("/authenticate") @@ -78,8 +67,7 @@ class UserJWTController( val authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken) SecurityContextHolder.getContext().authentication = authentication - val rememberMe = loginVM.isRememberMe ?: false - val jwt = tokenProvider.createToken(authentication, rememberMe) + val jwt = tokenProvider.createToken(authentication, loginVM.isRememberMe ?: false) val httpHeaders = HttpHeaders() httpHeaders.add(JWTFilter.AUTHORIZATION_HEADER, "Bearer $jwt") return ResponseEntity(JWTToken(jwt), httpHeaders, HttpStatus.OK) @@ -89,10 +77,6 @@ class UserJWTController( fun authorize(@Valid @RequestBody loginVM: Mono): Mono> = loginVM.flatMap { login -> authenticationManager.authenticate(UsernamePasswordAuthenticationToken(login.username, login.password)) - <%_ if (withAudit) { _%> - .onErrorResume { onAuthenticationError(login, it) } - .flatMap { onAuthenticationSuccess(login, it) } - <%_ } _%> .map { tokenProvider.createToken(it, true == login.isRememberMe) } }.map{ jwt -> @@ -100,25 +84,6 @@ class UserJWTController( httpHeaders.add(JWTFilter.AUTHORIZATION_HEADER, "Bearer $jwt") ResponseEntity(JWTToken(jwt), httpHeaders, HttpStatus.OK) } - - <%_ if (withAudit) { _%> - private fun onAuthenticationSuccess(login: LoginVM, auth: Authentication): Mono { - return Mono.just(login) - .map {it.username} - .filter { ANONYMOUS_USER != it } - .flatMap { auditEventService.saveAuthenticationSuccess(it!!) } - .thenReturn(auth) - } - - private fun onAuthenticationError(login: LoginVM, throwable: Throwable): Mono { - return Mono.just(login) - .map {it.username} - .filter { ANONYMOUS_USER != it } - .flatMap { auditEventService.saveAuthenticationError(it!!, throwable) } - .then(Mono.error(throwable)) - } - - <%_ } _%> <%_ } _%> /** diff --git a/generators/server/templates/src/main/kotlin/package/web/rest/UserResource.kt.ejs b/generators/server/templates/src/main/kotlin/package/web/rest/UserResource.kt.ejs index 452526251..95a67fc99 100644 --- a/generators/server/templates/src/main/kotlin/package/web/rest/UserResource.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/web/rest/UserResource.kt.ejs @@ -19,34 +19,31 @@ package <%= packageName %>.web.rest import <%= packageName %>.config.LOGIN_REGEX -<%_ if (authenticationType !== 'oauth2' || searchEngine === 'elasticsearch') { _%> +<%_ if (authenticationType !== 'oauth2') { _%> import <%= packageName %>.domain.<%= asEntity('User') %> <%_ } _%> <%_ if (authenticationType !== 'oauth2') { _%> import <%= packageName %>.repository.UserRepository <%_ } _%> -<%_ if (searchEngine === 'elasticsearch') { _%> -import <%= packageName %>.repository.search.UserSearchRepository -<%_ } _%> import <%= packageName %>.security.ADMIN <%_ if (authenticationType !== 'oauth2') { _%> import <%= packageName %>.service.MailService import org.springframework.data.domain.Sort <%_ } _%> import <%= packageName %>.service.UserService -import <%= packageName %>.service.dto.<%= asDto('User') %> +import <%= packageName %>.service.dto.<%= asDto('AdminUser') %> <%_ if (authenticationType !== 'oauth2') { _%> import <%= packageName %>.web.rest.errors.BadRequestAlertException import <%= packageName %>.web.rest.errors.EmailAlreadyUsedException import <%= packageName %>.web.rest.errors.LoginAlreadyUsedException <%_ } _%> -import io.github.jhipster.web.util.HeaderUtil +import tech.jhipster.web.util.HeaderUtil <%_ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') { _%> -import io.github.jhipster.web.util.PaginationUtil +import tech.jhipster.web.util.PaginationUtil <%_ } _%> <%_ if (!reactive) { _%> -import io.github.jhipster.web.util.ResponseUtil +import tech.jhipster.web.util.ResponseUtil <%_ } _%> import org.slf4j.LoggerFactory @@ -85,6 +82,7 @@ import reactor.core.publisher.Flux import reactor.core.publisher.Mono <%_ } _%> +import javax.validation.constraints.Pattern <%_ if (authenticationType !== 'oauth2') { _%> import javax.validation.Valid import java.net.URI @@ -121,12 +119,11 @@ import org.elasticsearch.index.query.QueryBuilders.queryStringQuery * Another option would be to have a specific JPA entity graph to handle this case. */ @RestController -@RequestMapping("/api") +@RequestMapping("/api/admin") class UserResource( private val userService: UserService<%_ if (authenticationType !== 'oauth2') { _%>, private val userRepository: UserRepository, - private val mailService: MailService<% } if (searchEngine === 'elasticsearch') { _%>, - private val userSearchRepository: UserSearchRepository<% } %> + private val mailService: MailService<% } %> ) { <%_ if (authenticationType !== 'oauth2') { _%> @@ -143,7 +140,7 @@ class UserResource( <%_ if (authenticationType !== 'oauth2') { _%> /** - * `POST /users` : Creates a new user. + * `POST /admin/users` : Creates a new user. * * Creates a new user if the login and email are not already used, and sends an * mail with an activation link. @@ -161,7 +158,7 @@ class UserResource( <%_ if (!reactive) { _%> @Throws(URISyntaxException::class) <%_ } _%> - fun createUser(@Valid @RequestBody userDTO: <%= asDto('User') %>): <% if (reactive) { %>Mono>><% } else { %>ResponseEntity<<%= asEntity('User') %>><% } %> { + fun createUser(@Valid @RequestBody userDTO: <%= asDto('AdminUser') %>): <% if (reactive) { %>Mono>><% } else { %>ResponseEntity<<%= asEntity('User') %>><% } %> { log.debug("REST request to save User : $userDTO") if (userDTO.id != null) { @@ -175,7 +172,7 @@ class UserResource( } else { val newUser = userService.createUser(userDTO) mailService.sendCreationEmail(newUser) - return ResponseEntity.created(URI("/api/users/" + newUser.login)) + return ResponseEntity.created(URI("/api/admin/users/" + newUser.login)) .headers(HeaderUtil.createAlert(applicationName, <% if (enableTranslation) {%>"userManagement.created"<% } else { %> "A user is created with identifier $newUser.login"<% } %>, newUser.login)) .body(newUser) } @@ -199,7 +196,7 @@ class UserResource( .doOnSuccess(mailService::sendCreationEmail) .map { user -> try { - ResponseEntity.created(URI("/api/users/" + user.login)) + ResponseEntity.created(URI("/api/admin/users/" + user.login)) .headers(HeaderUtil.createAlert(applicationName, "userManagement.created", user.login)) .body(user) } catch (e: URISyntaxException) { @@ -210,7 +207,7 @@ class UserResource( } /** - * `PUT /users` : Updates an existing User. + * `PUT /admin/users` : Updates an existing User. * * @param userDTO the user to update. * @return the `ResponseEntity` with status `200 (OK)` and with body the updated user. @@ -220,7 +217,7 @@ class UserResource( @PutMapping("/users") @PreAuthorize("hasAuthority(\"$ADMIN\")") <%_ if (!reactive) { _%> - fun updateUser(@Valid @RequestBody userDTO: <%= asDto('User') %>): ResponseEntity<<%= asDto('User') %>> { + fun updateUser(@Valid @RequestBody userDTO: <%= asDto('AdminUser') %>): ResponseEntity<<%= asDto('AdminUser') %>> { log.debug("REST request to update User : $userDTO") var existingUser = userRepository.findOneByEmailIgnoreCase(userDTO.email) if (existingUser.isPresent && existingUser.get().id != userDTO.id) { @@ -237,7 +234,7 @@ class UserResource( HeaderUtil.createAlert(applicationName, <% if (enableTranslation) { %>"userManagement.updated"<% } else { %>"A user is updated with identifier $userDTO.login"<% } %>, userDTO.login) ) <%_ } else { _%> - fun updateUser(@Valid @RequestBody userDTO: <%= asDto('User') %>) : Mono>> { + fun updateUser(@Valid @RequestBody userDTO: <%= asDto('AdminUser') %>) : Mono>> { log.debug("REST request to update User : $userDTO") return userRepository.findOneByEmailIgnoreCase(userDTO.email!!) .filter { user -> user.id != userDTO.id } @@ -267,7 +264,7 @@ class UserResource( <%_ } _%> /** - * `GET /users` : get all users. + * `GET /admin/users` : get all users with all the details - calling this are only allowed for the administrators. *<% if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') { %> <%_ if (reactive) { _%> * @param request a [ServerHttpRequest] request. @@ -276,9 +273,11 @@ class UserResource( * @return the `ResponseEntity` with status `200 (OK)` and with body all users. */ @GetMapping("/users") + @PreAuthorize("hasAuthority(\"$ADMIN\")") <%_ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') { _%> <%_ if (!reactive) { _%> - fun getAllUsers(pageable: Pageable): ResponseEntity>> { + fun getAllUsers(pageable: Pageable): ResponseEntity>> { + log.debug("REST request to get all User for an admin"); <%_ if (authenticationType !== 'oauth2') { _%> if (!onlyContainsAllowedProperties(pageable)) { return ResponseEntity.badRequest().build() @@ -292,7 +291,8 @@ class UserResource( fun getAllUsers( request: ServerHttpRequest, pageable: Pageable - ): Mono>>> { + ): Mono>>> { + log.debug("REST request to get all User for an admin"); <%_ if (authenticationType !== 'oauth2') { _%> if (!onlyContainsAllowedProperties(pageable)) { return Mono.just(ResponseEntity.badRequest().build()) @@ -300,7 +300,7 @@ class UserResource( <%_ } _%> return userService.countManagedUsers() - .map { total -> PageImpl(mutableListOf<<%= asDto('User') %>>(), pageable, total!!) } + .map { total -> PageImpl(mutableListOf<<%= asDto('AdminUser') %>>(), pageable, total!!) } .map { page -> PaginationUtil.generatePaginationHttpHeaders(UriComponentsBuilder.fromHttpRequest(request), page) } .map { headers -> ResponseEntity.ok().headers(headers).body(userService.getAllManagedUsers(pageable)) } } @@ -310,83 +310,55 @@ class UserResource( pageable.sort.map(Sort.Order::getProperty).all { ALLOWED_ORDERED_PROPERTIES.contains(it) } <%_ } _%> - /** - * Gets a list of all roles. - * @return a string list of all roles. - */ - @GetMapping("/users/authorities") - @PreAuthorize("hasAuthority(\"$ADMIN\")") - fun getAuthorities() = userService.getAuthorities()<% if (reactive) { %>.collectList()<% } %> <%_ } else { // Cassandra _%> fun getAllUsers() = userService.getAllManagedUsers() <%_ } _%> /** - * `GET /users/:login` : get the "login" user. + * `GET /admin/users/:login` : get the "login" user. * * @param login the login of the user to find. * @return the `ResponseEntity` with status `200 (OK)` and with body the "login" user, or with status `404 (Not Found)`. */ - @GetMapping("/users/{login:$LOGIN_REGEX}") + @GetMapping("/users/{login}") + @PreAuthorize("hasAuthority(\"$ADMIN\")") <%_ if (!reactive) { _%> - fun getUser(@PathVariable login: String): ResponseEntity<<%= asDto('User') %>> { + fun getUser(@PathVariable @Pattern(regexp = LOGIN_REGEX) login: String): ResponseEntity<<%= asDto('AdminUser') %>> { log.debug("REST request to get User : $login") return ResponseUtil.wrapOrNotFound( userService.getUserWithAuthoritiesByLogin(login) - .map { <%= asDto('User') %>(it) }) + .map { <%= asDto('AdminUser') %>(it) }) <%_ } else { _%> - fun getUser(@PathVariable login: String): Mono<<%= asDto('User') %>> { + fun getUser(@PathVariable login: String): Mono<<%= asDto('AdminUser') %>> { log.debug("REST request to get User : $login") return userService.getUserWithAuthoritiesByLogin(login) - .map { <%= asDto('User') %>(it) } + .map { <%= asDto('AdminUser') %>(it) } .switchIfEmpty(Mono.error(ResponseStatusException(HttpStatus.NOT_FOUND))) <%_ } _%> } <%_ if (authenticationType !== 'oauth2') { _%> /** - * `DELETE /users/:login` : delete the "login" User. + * `DELETE /admin/users/:login` : delete the "login" User. * * @param login the login of the user to delete. * @return the `ResponseEntity` with status `204 (NO_CONTENT)`. */ - @DeleteMapping("/users/{login:$LOGIN_REGEX}") + @DeleteMapping("/users/{login}") @PreAuthorize("hasAuthority(\"$ADMIN\")") <%_ if (!reactive) { _%> - fun deleteUser(@PathVariable login: String): ResponseEntity { + fun deleteUser(@PathVariable @Pattern(regexp = LOGIN_REGEX) login: String): ResponseEntity { log.debug("REST request to delete User: $login") userService.deleteUser(login) return ResponseEntity.noContent() .headers(HeaderUtil.createAlert(applicationName, <% if (enableTranslation) {%>"userManagement.deleted"<% } else { %> "A user is deleted with identifier $login"<% } %>, login)).build() <%_ } else { _%> @ResponseStatus(code = HttpStatus.NO_CONTENT) - fun deleteUser(@PathVariable login: String): Mono> { + fun deleteUser(@PathVariable @Pattern(regexp = LOGIN_REGEX) login: String): Mono> { log.debug("REST request to delete User: $login") return userService.deleteUser(login) .map { ResponseEntity.noContent().headers(HeaderUtil.createAlert(applicationName, "userManagement.deleted", login)).build() } <%_ } _%> } <%_ } _%> -<%_ if (searchEngine !== false) { _%> - - /** - * `SEARCH /_search/users/:query` : search for the User corresponding to the query. - * - * @param query the query to search. - * @return the result of the search. - */ - @GetMapping("/_search/users/{query}") - fun search(@PathVariable query: String) = - <%_ if (searchEngine === 'elasticsearch') { _%> - <%_ if (!reactive) { _%> - StreamSupport - .stream(userSearchRepository.search(queryStringQuery(query)).spliterator(), false) - .collect(Collectors.toList()) - <%_ } else { _%> - userSearchRepository.search(query).collectList() - <%_ } _%> - <%_ } else { _%> - userRepository.search(User.PREFIX, query)<% if (reactive) { %>.collectList()<% } %> - <%_ } _%> -<%_ } _%> } diff --git a/generators/server/templates/src/main/kotlin/package/web/rest/errors/ExceptionTranslator.kt.ejs b/generators/server/templates/src/main/kotlin/package/web/rest/errors/ExceptionTranslator.kt.ejs index a622bd8eb..0622d2b2c 100644 --- a/generators/server/templates/src/main/kotlin/package/web/rest/errors/ExceptionTranslator.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/web/rest/errors/ExceptionTranslator.kt.ejs @@ -18,8 +18,8 @@ -%> package <%= packageName %>.web.rest.errors -import io.github.jhipster.config.JHipsterConstants -import io.github.jhipster.web.util.HeaderUtil +import tech.jhipster.config.JHipsterConstants +import tech.jhipster.web.util.HeaderUtil import org.apache.commons.lang3.StringUtils import org.springframework.beans.factory.annotation.Value @@ -112,12 +112,17 @@ _%> return Mono.just(entity) <%_ } _%> } + <%_ if (!reactive) { _%> + val nativeRequest = request?.getNativeRequest(HttpServletRequest::class.java); + val requestUri = if (nativeRequest != null) nativeRequest.requestURI else StringUtils.EMPTY + <%_ } _%> + val builder = Problem.builder() .withType(if (Problem.DEFAULT_TYPE == problem.type) DEFAULT_TYPE else problem.type) .withStatus(problem.status) .withTitle(problem.title) <%_ if (!reactive) { _%> - .with(PATH_KEY, request!!.getNativeRequest(HttpServletRequest::class.java)!!.requestURI) + .with(PATH_KEY, requestUri) <%_ } else { _%> .with(PATH_KEY, request!!.request.path.value()) <%_ } _%> @@ -149,7 +154,13 @@ _%> : <%- returnType %> { <%_ } _%> val result = ex.bindingResult - val fieldErrors = result.fieldErrors.map { FieldErrorVM(it.objectName.replaceFirst(Regex("<%= dtoSuffix %>$"), ""), it.field, it.code) } + val fieldErrors = result.fieldErrors.map { + FieldErrorVM( + it.objectName.replaceFirst(Regex("<%= dtoSuffix %>$"), ""), + it.field, + if (StringUtils.isNotBlank(it.defaultMessage)) it.defaultMessage else it.code + ) + } val problem = Problem.builder() .withType(CONSTRAINT_VIOLATION_TYPE) diff --git a/generators/server/templates/src/main/kotlin/package/web/rest/vm/ManagedUserVM.kt.ejs b/generators/server/templates/src/main/kotlin/package/web/rest/vm/ManagedUserVM.kt.ejs index 61c94e4fc..221eac647 100644 --- a/generators/server/templates/src/main/kotlin/package/web/rest/vm/ManagedUserVM.kt.ejs +++ b/generators/server/templates/src/main/kotlin/package/web/rest/vm/ManagedUserVM.kt.ejs @@ -18,15 +18,15 @@ -%> package <%= packageName %>.web.rest.vm -import <%= packageName %>.service.dto.<%= asDto('User') %> +import <%= packageName %>.service.dto.<%= asDto('AdminUser') %> <%_ if (authenticationType !== 'oauth2') { _%> import javax.validation.constraints.Size <%_ } _%> /** - * View Model extending the [<%= asDto('User') %>], which is meant to be used in the user management UI. + * View Model extending the [<%= asDto('AdminUser') %>], which is meant to be used in the user management UI. */ -class ManagedUserVM : <%= asDto('User') %>() { +class ManagedUserVM : <%= asDto('AdminUser') %>() { <%_ if (authenticationType !== 'oauth2') { _%> @field:Size(min = PASSWORD_MIN_LENGTH, max = PASSWORD_MAX_LENGTH) diff --git a/generators/server/templates/src/test/kotlin/package/AbstractCassandraTest.kt.ejs b/generators/server/templates/src/test/kotlin/package/AbstractCassandraTest.kt.ejs index 52d2d3005..3132b3e91 100644 --- a/generators/server/templates/src/test/kotlin/package/AbstractCassandraTest.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/AbstractCassandraTest.kt.ejs @@ -18,23 +18,35 @@ -%> package <%= packageName %> -import io.github.jhipster.config.JHipsterConstants -import com.datastax.driver.core.Cluster -import com.datastax.driver.core.Session -import org.apache.cassandra.exceptions.ConfigurationException -import org.apache.thrift.transport.TTransportException +import java.nio.file.Files.newDirectoryStream +import java.nio.file.Paths.get +import java.util.Spliterator.SORTED +import java.util.Spliterators.spliteratorUnknownSize +import java.util.stream.StreamSupport.stream + +import tech.jhipster.config.JHipsterConstants + +import com.datastax.oss.driver.api.core.CqlSession import org.cassandraunit.CQLDataLoader import org.cassandraunit.dataset.cql.ClassPathCQLDataSet import org.junit.jupiter.api.BeforeAll +import org.springframework.test.context.ContextConfiguration; +import org.springframework.context.ApplicationContextInitializer +import org.springframework.context.ConfigurableApplicationContext +import org.springframework.test.context.support.TestPropertySourceUtils import org.springframework.test.context.ActiveProfiles import org.testcontainers.containers.GenericContainer import org.testcontainers.containers.wait.strategy.Wait import java.io.IOException +import java.net.InetSocketAddress import java.net.URISyntaxException import java.nio.file.Files +import java.nio.file.Path import java.nio.file.Paths +import java.util.Iterator +import java.util.Spliterator import java.time.Duration @@ -42,6 +54,7 @@ import java.time.Duration * Base class for starting/stopping Cassandra during tests. */ @ActiveProfiles(JHipsterConstants.SPRING_PROFILE_TEST) +@ContextConfiguration(initializers = [AbstractCassandraTest.CassandraPortInitializer::class]) open class AbstractCassandraTest { companion object { @@ -57,20 +70,18 @@ open class AbstractCassandraTest { @JvmStatic @BeforeAll - @Throws( - TTransportException::class, ConfigurationException::class, IOException::class, URISyntaxException::class - ) + @Throws(IOException::class, URISyntaxException::class) fun startServer() { if (!started) { CASSANDRA_CONTAINER.start() - val cluster = Cluster.Builder() - .addContactPoint("127.0.0.1") - .withPort(CASSANDRA_CONTAINER.getMappedPort(CASSANDRA_TEST_PORT)) - .withoutMetrics() - .withoutJMXReporting() + val session = CqlSession.builder() + .addContactPoint(InetSocketAddress( + CASSANDRA_CONTAINER.containerIpAddress, + CASSANDRA_CONTAINER.getMappedPort(CASSANDRA_TEST_PORT) + )) + .withLocalDatacenter("datacenter1") .build() - val session = cluster.connect() createTestKeyspace(session) val dataLoader = CQLDataLoader(session) applyScripts(dataLoader, "config/cql/changelog/", "*.cql") @@ -80,7 +91,7 @@ open class AbstractCassandraTest { } @JvmStatic - private fun createTestKeyspace(session: Session) { + private fun createTestKeyspace(session: CqlSession) { val createQuery = "CREATE KEYSPACE $CASSANDRA_UNIT_KEYSPACE WITH replication={'class' : 'SimpleStrategy', 'replication_factor':1}" session.execute(createQuery) @@ -94,17 +105,24 @@ open class AbstractCassandraTest { // protect for empty directory val dirUrl = ClassLoader.getSystemResource(cqlDir) ?: return - val scripts = mutableListOf() - Files.newDirectoryStream(Paths.get(dirUrl.toURI()), pattern).use { stream -> - for (entry in stream) { - scripts.add(entry.fileName.toString()) - } - } - scripts.sort() + val pathIterator = newDirectoryStream(get(dirUrl.toURI()), pattern).iterator() + val pathSpliterator = spliteratorUnknownSize(pathIterator, SORTED) + + stream(pathSpliterator, false) + .map(Path::getFileName) + .map(Path::toString) + .sorted() + .map { cqlDir + it } + .map { ClassPathCQLDataSet(it, false, false, CASSANDRA_UNIT_KEYSPACE)} + .forEach(dataLoader::load) + } + } - for (fileName in scripts) { - dataLoader.load(ClassPathCQLDataSet(cqlDir + fileName, false, false, CASSANDRA_UNIT_KEYSPACE)) - } + class CassandraPortInitializer: ApplicationContextInitializer { + override fun initialize(applicationContext: ConfigurableApplicationContext) { + TestPropertySourceUtils.addInlinedPropertiesToEnvironment(applicationContext, + "spring.data.cassandra.port=" + AbstractCassandraTest.CASSANDRA_CONTAINER.getMappedPort(AbstractCassandraTest.CASSANDRA_TEST_PORT) + ) } } diff --git a/generators/server/templates/src/test/kotlin/package/AbstractNeo4jIT.kt.ejs b/generators/server/templates/src/test/kotlin/package/AbstractNeo4jIT.kt.ejs index 8a93d1e73..6ac2a09f5 100644 --- a/generators/server/templates/src/test/kotlin/package/AbstractNeo4jIT.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/AbstractNeo4jIT.kt.ejs @@ -33,6 +33,10 @@ class AbstractNeo4jIT: BeforeAllCallback { val neo4jContainer = KGenericContainer("<%= DOCKER_NEO4J %>") .withExposedPorts(7687) neo4jContainer.start() + System.setProperty( + "spring.neo4j.uri", + neo4jContainer.boldUrl + ) started.set(true) } } diff --git a/generators/server/templates/src/test/kotlin/package/CassandraKeyspaceIT.kt.ejs b/generators/server/templates/src/test/kotlin/package/CassandraKeyspaceIT.kt.ejs index 6e23d5904..4fe961c1c 100644 --- a/generators/server/templates/src/test/kotlin/package/CassandraKeyspaceIT.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/CassandraKeyspaceIT.kt.ejs @@ -18,17 +18,10 @@ -%> package <%= packageName %> -<%_ if (cacheProvider === 'redis') { _%> -import <%= packageName %>.RedisTestContainerExtension -<%_ } _%> - -import com.datastax.driver.core.Metadata -import com.datastax.driver.core.Session - +import <%= packageName %>.IntegrationTest +import com.datastax.oss.driver.api.core.CqlSession +import com.datastax.oss.driver.api.core.metadata.Metadata import org.junit.jupiter.api.Test -<%_ if (cacheProvider === 'redis') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest <%_ if (messageBroker === 'kafka') { _%> @@ -37,19 +30,15 @@ import org.springframework.kafka.test.context.EmbeddedKafka import org.assertj.core.api.Assertions.assertThat -@SpringBootTest(classes = [<%= mainClass %>::class]) -<%_ if (cacheProvider === 'redis') { _%> -@ExtendWith(RedisTestContainerExtension::class) -<%_ } _%> +@IntegrationTest class CassandraKeyspaceIT : AbstractCassandraTest() { @Autowired - private lateinit var session: Session + private lateinit var session: CqlSession @Test - @Throws(Exception::class) fun shouldListCassandraUnitKeyspace() { - val metadata: Metadata = session.cluster.metadata + val metadata: Metadata = session.getMetadata() assertThat(metadata.getKeyspace(CASSANDRA_UNIT_KEYSPACE)).isNotNull } } diff --git a/generators/server/templates/src/test/kotlin/package/IntegrationTest.kt.ejs b/generators/server/templates/src/test/kotlin/package/IntegrationTest.kt.ejs new file mode 100644 index 000000000..3a9838767 --- /dev/null +++ b/generators/server/templates/src/test/kotlin/package/IntegrationTest.kt.ejs @@ -0,0 +1,59 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + +This file is part of the JHipster project, see https://jhipster.github.io/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %> + +import <%= packageName %>.<%= mainClass %> +<%_ if (databaseType === 'neo4j') { _%> +import <%= packageName %>.AbstractNeo4jIT +<%_ } _%> +<%_ if (reactiveSqlTestContainers) { _%> +import <%= packageName %>.ReactiveSqlTestContainerExtension +<%_ } _%> +<%_ if (cacheProvider === 'redis') { _%> +import <%= packageName %>.RedisTestContainerExtension +<%_ } _%> +<%_ if (authenticationType === 'oauth2') { _%> +import <%= packageName %>.config.TestSecurityConfiguration +<%_ } _%> +<%_ if (cacheProvider === 'redis' || databaseType === 'neo4j' || reactiveSqlTestContainers) { _%> +import org.junit.jupiter.api.extension.ExtendWith +<%_ } _%> + +import org.springframework.boot.test.context.SpringBootTest + +/** + * Base composite annotation for integration tests. + */ +@kotlin.annotation.Target(AnnotationTarget.CLASS) +@kotlin.annotation.Retention(AnnotationRetention.RUNTIME) +<%_ if (authenticationType === 'oauth2') { _%> +@SpringBootTest(classes = [<%= mainClass %>::class, TestSecurityConfiguration::class]) +<%_ } else { _%> +@SpringBootTest(classes = [<%= mainClass %>::class]) +<%_ } _%> +<%_ if (cacheProvider === 'redis') { _%> +@ExtendWith(RedisTestContainerExtension::class) +<%_ } _%> +<%_ if (databaseType === 'neo4j') { _%> +@ExtendWith(AbstractNeo4jIT::class) +<%_ } _%> +<%_ if (reactiveSqlTestContainers) { _%> +@ExtendWith(ReactiveSqlTestContainerExtension::class) +<%_ } _%> +annotation class IntegrationTest {} diff --git a/generators/server/templates/src/test/kotlin/package/ReactiveSqlTestContainerExtension.kt.ejs b/generators/server/templates/src/test/kotlin/package/ReactiveSqlTestContainerExtension.kt.ejs new file mode 100644 index 000000000..a4634d334 --- /dev/null +++ b/generators/server/templates/src/test/kotlin/package/ReactiveSqlTestContainerExtension.kt.ejs @@ -0,0 +1,81 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + +This file is part of the JHipster project, see https://jhipster.github.io/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %> + +import org.apache.commons.lang3.StringUtils +import org.junit.jupiter.api.extension.BeforeAllCallback +import org.junit.jupiter.api.extension.ExtensionContext +<%_ if (prodDatabaseType === 'mysql') { _%> +import org.testcontainers.containers.MySQLContainer +<%_ } else if (prodDatabaseType === 'mariadb') { _%> +import org.testcontainers.containers.MariaDBContainer +<%_ } else if (prodDatabaseType === 'postgresql') { _%> +import org.testcontainers.containers.PostgreSQLContainer +<%_ } else if (prodDatabaseType === 'mssql') { _%> +import org.testcontainers.containers.MSSQLServerContainer +<%_ } _%> +import java.util.Collections +import java.util.concurrent.atomic.AtomicBoolean + +class ReactiveSqlTestContainerExtension: BeforeAllCallback { + + private val started: AtomicBoolean = AtomicBoolean(false) + + companion object { + + private val container: <%_ if (prodDatabaseType === 'mysql') { _%> + MySQLContainer<*> = MySQLContainer("<%= DOCKER_MYSQL %>") + <%_ } else if (prodDatabaseType === 'mariadb') { _%> + MariaDBContainer<*> = MariaDBContainer("<%= DOCKER_MARIADB %>") + <%_ } else if (prodDatabaseType === 'postgresql') { _%> + PostgreSQLContainer<*> = PostgreSQLContainer("<%= DOCKER_POSTGRESQL %>") + <%_ } else if (prodDatabaseType === 'mssql') { _%> + MSSQLServerContainer<*> = MSSQLServerContainer("<%= DOCKER_MSSQL %>") + <%_ } _%>.apply { + <%_ if (prodDatabaseType !== 'mssql') { _%> + withDatabaseName("<%= baseName %>") + <%_ } _%> + withTmpFs(Collections.singletonMap("/testtmpfs", "rw")) + } + } + + + + @Throws(Exception::class) + override fun beforeAll(extensionContext: ExtensionContext) { + if (!started.get() && useTestcontainers()) { + container.start() + System.setProperty("spring.r2dbc.url", container.jdbcUrl.replace("jdbc", "r2dbc")) + System.setProperty("spring.r2dbc.username", container.username) + System.setProperty("spring.r2dbc.password", container.password) + System.setProperty("spring.liquibase.url", container.jdbcUrl) + System.setProperty("spring.liquibase.user", container.username) + System.setProperty("spring.liquibase.password", container.password) + started.set(true) + } + } + + private fun useTestcontainers(): Boolean { + + val systemProperties = StringUtils.defaultIfBlank(System.getProperty("spring.profiles.active"), "") + val environmentVariables = StringUtils.defaultIfBlank(System.getenv("SPRING_PROFILES_ACTIVE"), "") + + return systemProperties.contains("testcontainers") || environmentVariables.contains("testcontainers") + } +} diff --git a/generators/server/templates/src/test/kotlin/package/RedisTestContainerExtension.kt.ejs b/generators/server/templates/src/test/kotlin/package/RedisTestContainerExtension.kt.ejs index f32929efd..c2f4c5313 100644 --- a/generators/server/templates/src/test/kotlin/package/RedisTestContainerExtension.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/RedisTestContainerExtension.kt.ejs @@ -28,13 +28,16 @@ import java.util.concurrent.atomic.AtomicBoolean class RedisTestContainerExtension: BeforeAllCallback { private val started = AtomicBoolean(false) + companion object { + @JvmStatic + val redis = KGenericContainer("<%= DOCKER_REDIS %>").withExposedPorts(6379) + } + @Throws(Exception::class) override fun beforeAll(extensionContext: ExtensionContext) { if(!started.get()) { - val redis = KGenericContainer("<%= DOCKER_REDIS %>") - .withExposedPorts(6379) redis.start() - System.setProperty("redis.test.server", "redis://" + redis.getContainerIpAddress() + ":" + redis.getMappedPort(6379)) + System.setProperty("jhipster.cache.redis.server", "redis://" + redis.containerIpAddress + ":" + redis.getMappedPort(6379)) started.set(true) } } diff --git a/generators/server/templates/src/test/kotlin/package/config/CassandraConfigurationIT.kt.ejs b/generators/server/templates/src/test/kotlin/package/config/CassandraConfigurationIT.kt.ejs deleted file mode 100644 index f3c873757..000000000 --- a/generators/server/templates/src/test/kotlin/package/config/CassandraConfigurationIT.kt.ejs +++ /dev/null @@ -1,41 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.config - -import <%= packageName %>.AbstractCassandraTest -import <%= packageName %>.config.cassandra.CassandraConfiguration - -import io.github.jhipster.config.JHipsterConstants - -import org.springframework.boot.autoconfigure.cassandra.CassandraProperties -import org.springframework.context.annotation.Configuration -import org.springframework.context.annotation.Profile - -@Configuration -@Profile(JHipsterConstants.SPRING_PROFILE_TEST) -class CassandraConfigurationIT : CassandraConfiguration() { - - /** - * Override how to get the port to connect to the Cassandra cluster. - * - * This uses the TestContainers API to get the mapped port in Docker. - */ - override fun getPort(properties: CassandraProperties) = - AbstractCassandraTest.CASSANDRA_CONTAINER.getMappedPort(AbstractCassandraTest.CASSANDRA_TEST_PORT) -} diff --git a/generators/server/templates/src/test/kotlin/package/config/ElasticsearchTestConfiguration.kt.ejs b/generators/server/templates/src/test/kotlin/package/config/ElasticsearchTestConfiguration.kt.ejs deleted file mode 100644 index fdb6aa7cf..000000000 --- a/generators/server/templates/src/test/kotlin/package/config/ElasticsearchTestConfiguration.kt.ejs +++ /dev/null @@ -1,37 +0,0 @@ -<%# -Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ -for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. --%> -package <%=packageName%>.config - -import org.assertj.core.util.Files -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchProperties -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.context.annotation.Primary - -import java.io.File - -@Configuration -class ElasticsearchTestConfiguration { - @Autowired - fun elasticsearchProperties(elasticsearchProperties: ElasticsearchProperties) { - val tempdir = Files.newTemporaryFolder() - elasticsearchProperties.properties["path.home"] = tempdir.absolutePath - } -} diff --git a/generators/server/templates/src/test/kotlin/package/config/JHipsterBlockHoundIntegration.kt.ejs b/generators/server/templates/src/test/kotlin/package/config/JHipsterBlockHoundIntegration.kt.ejs new file mode 100644 index 000000000..413e68348 --- /dev/null +++ b/generators/server/templates/src/test/kotlin/package/config/JHipsterBlockHoundIntegration.kt.ejs @@ -0,0 +1,32 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + +This file is part of the JHipster project, see https://jhipster.github.io/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %>.config + +import reactor.blockhound.BlockHound +import reactor.blockhound.integration.BlockHoundIntegration + +class JHipsterBlockHoundIntegration: BlockHoundIntegration { + override fun applyTo(builder: BlockHound.Builder) { + // Workaround until https://github.com/reactor/reactor-core/issues/2137 is fixed + builder.allowBlockingCallsInside("reactor.core.scheduler.BoundedElasticScheduler\$BoundedState", "dispose") + builder.allowBlockingCallsInside("reactor.core.scheduler.BoundedElasticScheduler", "schedule") + builder.allowBlockingCallsInside("org.springframework.validation.beanvalidation.SpringValidatorAdapter", "validate") + } + +} diff --git a/generators/server/templates/src/test/kotlin/package/config/OAuth2TestConfiguration.kt.ejs b/generators/server/templates/src/test/kotlin/package/config/OAuth2TestConfiguration.kt.ejs deleted file mode 100644 index 211c585f2..000000000 --- a/generators/server/templates/src/test/kotlin/package/config/OAuth2TestConfiguration.kt.ejs +++ /dev/null @@ -1,37 +0,0 @@ -<%# -Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ -for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. --%> -package <%=packageName%>.config - -import org.springframework.context.annotation.Configuration -import org.springframework.security.config.annotation.web.builders.HttpSecurity -import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer -import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurer -import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer - -@Configuration -@EnableResourceServer -class OAuth2TestConfiguration: ResourceServerConfigurer { - // We set stateless to false to prevent the SecurityContext to be cleared when the respective filter is invoked - // Otherwise it is impossible to use @WithMockUser in combination with oauth2 in tests - override fun configure(security: ResourceServerSecurityConfigurer) { - security.stateless(false) - } - - override fun configure(http: HttpSecurity) { } -} diff --git a/generators/server/templates/src/test/kotlin/package/config/SecurityBeanOverrideConfiguration.kt.ejs b/generators/server/templates/src/test/kotlin/package/config/SecurityBeanOverrideConfiguration.kt.ejs deleted file mode 100644 index 83e74fa2e..000000000 --- a/generators/server/templates/src/test/kotlin/package/config/SecurityBeanOverrideConfiguration.kt.ejs +++ /dev/null @@ -1,47 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.config - -import org.springframework.cloud.client.loadbalancer.RestTemplateCustomizer -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.context.annotation.Primary -import org.springframework.security.oauth2.provider.token.TokenStore -import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter -import org.springframework.web.client.RestTemplate - -/** - * Overrides UAA specific beans, so they do not interfere the testing. - * This configuration must be included in `@SpringBootTest` in order to take effect. - */ -@Configuration -class SecurityBeanOverrideConfiguration { - - @Bean - @Primary - fun tokenStore(): TokenStore? = null - - @Bean - @Primary - fun jwtAccessTokenConverter(): JwtAccessTokenConverter? = null - - @Bean - @Primary - fun loadBalancedRestTemplate(customizer: RestTemplateCustomizer): RestTemplate? = null -} diff --git a/generators/server/templates/src/test/kotlin/package/config/StaticResourcesWebConfigurerTest.kt.ejs b/generators/server/templates/src/test/kotlin/package/config/StaticResourcesWebConfigurerTest.kt.ejs index 297de3735..af6b0ad4f 100644 --- a/generators/server/templates/src/test/kotlin/package/config/StaticResourcesWebConfigurerTest.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/config/StaticResourcesWebConfigurerTest.kt.ejs @@ -21,8 +21,8 @@ package <%= packageName %>.config import <%= packageName %>.config.StaticResourcesWebConfiguration.Companion.RESOURCE_LOCATIONS import <%= packageName %>.config.StaticResourcesWebConfiguration.Companion.RESOURCE_PATHS import com.nhaarman.mockitokotlin2.anyOrNull -import io.github.jhipster.config.JHipsterDefaults -import io.github.jhipster.config.JHipsterProperties +import tech.jhipster.config.JHipsterDefaults +import tech.jhipster.config.JHipsterProperties import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.springframework.http.CacheControl @@ -81,19 +81,19 @@ class StaticResourcesWebConfigurerTest { @Test - fun shoudCreateCacheControlBasedOnJhipsterDefaultProperties() { + fun shouldCreateCacheControlBasedOnJhipsterDefaultProperties() { val cacheExpected = CacheControl.maxAge(JHipsterDefaults.Http.Cache.timeToLiveInDays.toLong(), TimeUnit.DAYS).cachePublic() assertThat(staticResourcesWebConfiguration.getCacheControl()) - .extracting(CacheControl::getHeaderValue) + .extracting { it.headerValue } .isEqualTo(cacheExpected.headerValue) } @Test - fun shoudCreateCacheControlWithSpecificConfigurationInProperties() { + fun shouldCreateCacheControlWithSpecificConfigurationInProperties() { props.http.cache.timeToLiveInDays = MAX_AGE_TEST val cacheExpected = CacheControl.maxAge(MAX_AGE_TEST.toLong(), TimeUnit.DAYS).cachePublic() assertThat(staticResourcesWebConfiguration.getCacheControl()) - .extracting(CacheControl::getHeaderValue) + .extracting { it.headerValue } .isEqualTo(cacheExpected.headerValue) } diff --git a/generators/server/templates/src/test/kotlin/package/config/TestSecurityConfiguration.kt.ejs b/generators/server/templates/src/test/kotlin/package/config/TestSecurityConfiguration.kt.ejs index c31e7263a..0ed566713 100644 --- a/generators/server/templates/src/test/kotlin/package/config/TestSecurityConfiguration.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/config/TestSecurityConfiguration.kt.ejs @@ -47,7 +47,7 @@ class TestSecurityConfiguration { metadata["end_session_endpoint"] = "https://jhipster.org/logout" return ClientRegistration.withRegistrationId("oidc") - .redirectUriTemplate("{baseUrl}/{action}/oauth2/code/{registrationId}") + .redirectUri("{baseUrl}/{action}/oauth2/code/{registrationId}") .clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) .scope("read:user") diff --git a/generators/server/templates/src/test/kotlin/package/config/WebConfigurerTest.kt.ejs b/generators/server/templates/src/test/kotlin/package/config/WebConfigurerTest.kt.ejs index be678ef29..3bcc12dba 100644 --- a/generators/server/templates/src/test/kotlin/package/config/WebConfigurerTest.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/config/WebConfigurerTest.kt.ejs @@ -18,11 +18,8 @@ -%> package <%= packageName %>.config -import io.github.jhipster.config.JHipsterConstants -import io.github.jhipster.config.JHipsterProperties -<%_ if (!skipClient) { _%> -import io.github.jhipster.web.filter.CachingHttpHeadersFilter -<%_ } _%> +import tech.jhipster.config.JHipsterConstants +import tech.jhipster.config.JHipsterProperties <%_ if (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory') { _%> import org.h2.server.web.WebServlet <%_ } _%> @@ -46,6 +43,7 @@ import java.io.File import org.assertj.core.api.Assertions.assertThat <%_ } _%> +import org.assertj.core.api.Assertions.assertThatCode import org.mockito.ArgumentMatchers import org.mockito.ArgumentMatchers.any import org.mockito.ArgumentMatchers.anyString @@ -89,10 +87,12 @@ class WebConfigurerTest { @Test @Throws(ServletException::class) - fun testStartUpProdServletContext() { + fun shouldStartUpProdServletContext() { env.setActiveProfiles(JHipsterConstants.SPRING_PROFILE_PRODUCTION) - webConfigurer.onStartup(servletContext) + assertThatCode { + webConfigurer.onStartup(servletContext) + }.doesNotThrowAnyException() <%_ if (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory') { _%> verify(servletContext, never()) .addServlet(ArgumentMatchers.eq("H2Console"), any(WebServlet::class.java)) @@ -101,10 +101,12 @@ class WebConfigurerTest { @Test @Throws(ServletException::class) - fun testStartUpDevServletContext() { + fun shouldStartUpDevServletContext() { env.setActiveProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) - webConfigurer.onStartup(servletContext) + assertThatCode { + webConfigurer.onStartup(servletContext) + }.doesNotThrowAnyException() <%_ if (devDatabaseType === 'h2Disk' || devDatabaseType === 'h2Memory') { _%> verify(servletContext) .addServlet(ArgumentMatchers.eq("H2Console"), any(WebServlet::class.java)) @@ -113,13 +115,13 @@ class WebConfigurerTest { <%_ if (!skipClient) { _%> @Test - fun testCustomizeServletContainer() { + fun shouldCustomizeServletContainer() { env.setActiveProfiles(JHipsterConstants.SPRING_PROFILE_PRODUCTION) val container = UndertowServletWebServerFactory() webConfigurer.customize(container) assertThat(container.mimeMappings.get("abs")).isEqualTo("audio/x-mpeg") - assertThat(container.mimeMappings.get("html")).isEqualTo("text/html;charset=utf-8") - assertThat(container.mimeMappings.get("json")).isEqualTo("text/html;charset=utf-8") + assertThat(container.mimeMappings.get("html")).isEqualTo("text/html") + assertThat(container.mimeMappings.get("json")).isEqualTo("application/json") <%_ if (!skipClient) { _%> if (container.documentRoot != null) { assertThat(container.documentRoot).isEqualTo(File("<%= CLIENT_DIST_DIR %>")) @@ -130,8 +132,8 @@ class WebConfigurerTest { @Test @Throws(Exception::class) - fun testCorsFilterOnApiPath() { - props.cors.allowedOrigins = listOf("*") + fun shouldCorsFilterOnApiPath() { + props.cors.allowedOrigins = listOf("other.domain.com") props.cors.allowedMethods = listOf("GET", "POST", "PUT", "DELETE") props.cors.allowedHeaders = listOf("*") props.cors.maxAge = 1800L @@ -163,7 +165,7 @@ class WebConfigurerTest { @Test @Throws(Exception::class) - fun testCorsFilterOnOtherPath() { + fun shouldCorsFilterOnOtherPath() { props.cors.allowedOrigins = listOf("*") props.cors.allowedMethods = listOf("GET", "POST", "PUT", "DELETE") props.cors.allowedHeaders = listOf("*") @@ -184,7 +186,7 @@ class WebConfigurerTest { @Test @Throws(Exception::class) - fun testCorsFilterDeactivated() { + fun shouldCorsFilterDeactivatedForNullAllowedOrigins() { props.cors.allowedOrigins = null val mockMvc = MockMvcBuilders.standaloneSetup(WebConfigurerTestController()) @@ -201,7 +203,7 @@ class WebConfigurerTest { @Test @Throws(Exception::class) - fun testCorsFilterDeactivated2() { + fun shouldCorsFilterDeactivatedForEmptyAllowedOrigins() { props.cors.allowedOrigins = mutableListOf() val mockMvc = MockMvcBuilders.standaloneSetup(WebConfigurerTestController()) diff --git a/generators/server/templates/src/test/kotlin/package/config/apidocs/GatewaySwaggerResourcesProviderTest.kt.ejs b/generators/server/templates/src/test/kotlin/package/config/apidocs/GatewaySwaggerResourcesProviderTest.kt.ejs new file mode 100644 index 000000000..97aa7db88 --- /dev/null +++ b/generators/server/templates/src/test/kotlin/package/config/apidocs/GatewaySwaggerResourcesProviderTest.kt.ejs @@ -0,0 +1,79 @@ +package <%= packageName %>.config.apidocs + +import org.assertj.core.api.Assertions.assertThat +import org.mockito.Mockito.`when` +import <%= packageName %>.config.apidocs.GatewaySwaggerResourcesProvider.Companion.swaggerResource + +import java.net.URI +import java.util.List +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.mockito.InjectMocks +import org.mockito.Mock +import org.springframework.cloud.gateway.route.Route +import org.springframework.cloud.gateway.route.RouteLocator +import org.springframework.test.context.junit.jupiter.SpringExtension +import org.springframework.test.util.ReflectionTestUtils +import reactor.core.publisher.Flux +import springfox.documentation.swagger.web.SwaggerResource +import springfox.documentation.swagger.web.SwaggerResourcesProvider + +@ExtendWith(SpringExtension::class) +class GatewaySwaggerResourcesProviderTest { + + @InjectMocks + private lateinit var gatewaySwaggerResourcesProvider: GatewaySwaggerResourcesProvider + + @Mock + private lateinit var routeLocator: RouteLocator + + @Mock + private lateinit var swaggerResourcesProvider: SwaggerResourcesProvider + + @Test + fun shouldGet() { + // Given + ReflectionTestUtils.setField(gatewaySwaggerResourcesProvider, "gatewayName", "burger") + `when`(swaggerResourcesProvider.get()) + .thenReturn( + List.of( + swaggerResource("default", "/v3/api-docs"), + swaggerResource("default", "/v3/api-docs?group=management"), + swaggerResource("default", "/v3/api-docs?group=openapi") + ) + ) + `when`(routeLocator.getRoutes()) + .thenReturn( + Flux.just( + Route + .async() + .id("ReactiveCompositeDiscoveryClient_BURGER") + .uri(URI.create("lb://BURGER")) + .predicate { true } + .build(), + Route + .async() + .id("ReactiveCompositeDiscoveryClient_BEER") + .uri(URI.create("lb://BEER")) + .predicate { true } + .build() + ) + ) + + // When + val result = gatewaySwaggerResourcesProvider.get() + + // Then + assertThat(result).isNotEmpty() + assertThat(result.size).isEqualTo(3) + + assertThat(result[0].name).isEqualTo("burger (default)") + assertThat(result[0].url).isEqualTo("/v3/api-docs") + + assertThat(result[1].name).isEqualTo("burger (management)") + assertThat(result[1].url).isEqualTo("/v3/api-docs?group=management") + + assertThat(result[2].name).isEqualTo("beer") + assertThat(result[2].url).isEqualTo("/services/beer/v3/api-docs") + } +} \ No newline at end of file diff --git a/generators/server/templates/src/test/kotlin/package/config/timezone/HibernateTimeZoneIT.kt.ejs b/generators/server/templates/src/test/kotlin/package/config/timezone/HibernateTimeZoneIT.kt.ejs index 967443956..f5c29d914 100644 --- a/generators/server/templates/src/test/kotlin/package/config/timezone/HibernateTimeZoneIT.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/config/timezone/HibernateTimeZoneIT.kt.ejs @@ -18,26 +18,13 @@ -%> package <%= packageName %>.config.timezone -import <%= packageName %>.<%= mainClass %> -<%_ if (cacheProvider === 'redis') { _%> -import <%= packageName %>.RedisTestContainerExtension -<%_ } _%> -<%_ if (authenticationType === 'uaa' && applicationType !== 'uaa') { _%> -import <%= packageName %>.config.SecurityBeanOverrideConfiguration -<%_ } _%> -<%_ if (authenticationType === 'oauth2') { _%> -import <%= packageName %>.config.TestSecurityConfiguration -<%_ } _%> +import <%= packageName %>.IntegrationTest import <%= packageName %>.repository.timezone.DateTimeWrapper import <%= packageName %>.repository.timezone.DateTimeWrapperRepository import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test -<%_ if (cacheProvider === 'redis') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> import org.springframework.beans.factory.annotation.Autowired import org.springframework.beans.factory.annotation.Value -import org.springframework.boot.test.context.SpringBootTest import org.springframework.jdbc.core.JdbcTemplate import org.springframework.jdbc.support.rowset.SqlRowSet import org.springframework.transaction.annotation.Transactional @@ -59,16 +46,7 @@ import org.assertj.core.api.Assertions.assertThat /** * Integration tests for the ZoneId Hibernate configuration. */ -<%_ if (authenticationType === 'uaa' && applicationType !== 'uaa') { _%> -@SpringBootTest(classes = [SecurityBeanOverrideConfiguration::class, <%= mainClass %>::class]) -<%_ } else if (authenticationType === 'oauth2') { _%> -@SpringBootTest(classes = [<%= mainClass %>::class, TestSecurityConfiguration::class]) -<%_ } else { _%> -@SpringBootTest(classes = [<%= mainClass %>::class]) -<%_ } _%> -<%_ if (cacheProvider === 'redis') { _%> -@ExtendWith(RedisTestContainerExtension::class) -<%_ } _%> +@IntegrationTest class HibernateTimeZoneIT { @Autowired diff --git a/generators/server/templates/src/test/kotlin/package/cucumber/CucumberContextConfiguration.kt.ejs b/generators/server/templates/src/test/kotlin/package/cucumber/CucumberTestContextConfiguration.kt.ejs similarity index 65% rename from generators/server/templates/src/test/kotlin/package/cucumber/CucumberContextConfiguration.kt.ejs rename to generators/server/templates/src/test/kotlin/package/cucumber/CucumberTestContextConfiguration.kt.ejs index e8bdaa7ec..c4e7d988d 100644 --- a/generators/server/templates/src/test/kotlin/package/cucumber/CucumberContextConfiguration.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/cucumber/CucumberTestContextConfiguration.kt.ejs @@ -1,7 +1,7 @@ <%# Copyright 2013-2020 the original author or authors from the JHipster project. - This file is part of the JHipster project, see https://www.jhipster.tech/ +This file is part of the JHipster project, see https://jhipster.github.io/ for more information. Licensed under the Apache License, Version 2.0 (the "License"); @@ -19,20 +19,11 @@ package <%= packageName %>.cucumber import <%= packageName %>.<%= mainClass %> -import io.cucumber.java.Before +import io.cucumber.spring.CucumberContextConfiguration import org.springframework.boot.test.context.SpringBootTest -import org.springframework.test.context.ContextConfiguration import org.springframework.test.context.web.WebAppConfiguration -@SpringBootTest +@CucumberContextConfiguration +@SpringBootTest(classes = [<%= mainClass %>::class]) @WebAppConfiguration -@ContextConfiguration(classes = [<%= mainClass %>::class]) -class CucumberContextConfiguration { - - @Before - fun setup_cucumber_spring_context() { - // Dummy method so cucumber will recognize this class as glue - // and use its context configuration. - } - -} +class CucumberTestContextConfiguration diff --git a/generators/server/templates/src/test/kotlin/package/gateway/responserewriting/SwaggerBasePathRewritingFilterTest.kt.ejs b/generators/server/templates/src/test/kotlin/package/gateway/responserewriting/SwaggerBasePathRewritingFilterTest.kt.ejs deleted file mode 100644 index 76831fe5b..000000000 --- a/generators/server/templates/src/test/kotlin/package/gateway/responserewriting/SwaggerBasePathRewritingFilterTest.kt.ejs +++ /dev/null @@ -1,112 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.gateway.responserewriting - -import com.netflix.zuul.context.RequestContext -import org.apache.commons.io.IOUtils -import org.junit.jupiter.api.Test -import org.springframework.mock.web.MockHttpServletRequest -import org.springframework.mock.web.MockHttpServletResponse - -import java.io.ByteArrayInputStream -import java.nio.charset.StandardCharsets -import java.util.zip.GZIPInputStream - -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertFalse -import org.junit.jupiter.api.Assertions.assertTrue -import springfox.documentation.swagger2.web.Swagger2Controller.DEFAULT_URL - -/** - * Tests [SwaggerBasePathRewritingFilter] class. - */ -class SwaggerBasePathRewritingFilterTest { - - private val filter = SwaggerBasePathRewritingFilter() - - @Test - fun shouldFilter_on_default_swagger_url() { - val request = MockHttpServletRequest("GET", DEFAULT_URL) - RequestContext.getCurrentContext().request = request - - assertTrue(filter.shouldFilter()) - } - - /** - * Zuul DebugFilter can be triggered by "deug" parameter. - */ - @Test - fun shouldFilter_on_default_swagger_url_with_param() { - val request = MockHttpServletRequest("GET", DEFAULT_URL) - request.setParameter("debug", "true") - RequestContext.getCurrentContext().request = request - - assertTrue(filter.shouldFilter()) - } - - @Test - fun shouldNotFilter_on_wrong_url() { - val request = MockHttpServletRequest("GET", "/management/info") - RequestContext.getCurrentContext().request = request - - assertFalse(filter.shouldFilter()) - } - - @Test - @Throws(Exception::class) - fun run_on_valid_response() { - val request = MockHttpServletRequest("GET", "/service1$DEFAULT_URL") - val context = RequestContext.getCurrentContext() - context.request = request - - val response = MockHttpServletResponse() - context.responseGZipped = false - context.response = response - - val `in` = IOUtils.toInputStream("{\"basePath\":\"/\"}", StandardCharsets.UTF_8) - context.responseDataStream = `in` - - filter.run() - - assertEquals("UTF-8", response.characterEncoding) - assertEquals("{\"basePath\":\"/service1\"}", context.responseBody) - } - - @Test - @Throws(Exception::class) - fun run_on_valid_response_gzip() { - val request = MockHttpServletRequest("GET", "/service1$DEFAULT_URL") - val context = RequestContext.getCurrentContext() - context.request = request - - val response = MockHttpServletResponse() - context.responseGZipped = true - context.response = response - - context.responseDataStream = ByteArrayInputStream(gzipData("{\"basePath\":\"/\"}")) - - filter.run() - - assertEquals("UTF-8", response.characterEncoding) - - val responseDataStream = GZIPInputStream(context.responseDataStream) - val responseBody = IOUtils.toString(responseDataStream, StandardCharsets.UTF_8) - assertEquals("{\"basePath\":\"/service1\"}", responseBody) - } -} diff --git a/generators/server/templates/src/test/kotlin/package/repository/CustomAuditEventRepositoryIT.kt.ejs b/generators/server/templates/src/test/kotlin/package/repository/CustomAuditEventRepositoryIT.kt.ejs deleted file mode 100644 index 3a2b6e1b8..000000000 --- a/generators/server/templates/src/test/kotlin/package/repository/CustomAuditEventRepositoryIT.kt.ejs +++ /dev/null @@ -1,212 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.repository - -import <%= packageName %>.<%= mainClass %> -<%_ if (cacheProvider === 'redis') { _%> -import <%= packageName %>.RedisTestContainerExtension -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import <%= packageName %>.AbstractNeo4jIT -<%_ } _%> -import <%= packageName %>.config.ANONYMOUS_USER -<%_ if (authenticationType === 'oauth2') { _%> -import <%= packageName %>.config.TestSecurityConfiguration -<%_ } _%> -import <%= packageName %>.config.audit.AuditEventConverter -import <%= packageName %>.domain.PersistentAuditEvent -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -<%_ if (cacheProvider === 'redis') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.actuate.audit.AuditEvent -import org.springframework.boot.test.context.SpringBootTest -<%_ if (!reactive) { _%> -import org.springframework.mock.web.MockHttpServletRequest -import org.springframework.mock.web.MockHttpSession -import org.springframework.security.web.authentication.WebAuthenticationDetails -<%_ } _%> -<%_ if (databaseType === 'sql') { _%> -import org.springframework.transaction.annotation.Transactional -<%_ } _%> - -import java.time.Instant -import java.time.temporal.ChronoUnit - -<%_ if (databaseType === 'couchbase') { _%> -import <%= packageName %>.web.rest.mockAuthentication -<%_ } _%> -import org.assertj.core.api.Assertions.assertThat - -/** - * Integration tests for [CustomAuditEventRepository]. - */ -<%_ if (authenticationType === 'oauth2') { _%> -@SpringBootTest(classes = [<%= mainClass %>::class, TestSecurityConfiguration::class]) -<%_ } else { _%> -@SpringBootTest(classes = [<%= mainClass %>::class]) -<%_ } _%> -<%_ if (databaseType === 'sql') { _%> -@Transactional -<%_ } _%> -<%_ if (cacheProvider === 'redis') { _%> -@ExtendWith(RedisTestContainerExtension::class) -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -@ExtendWith(AbstractNeo4jIT::class) -<%_ } _%> -class CustomAuditEventRepositoryIT <% if (databaseType === 'cassandra') { %>: AbstractCassandraTest() <% } %> { - - @Autowired - private lateinit var persistenceAuditEventRepository: PersistenceAuditEventRepository - - @Autowired - private lateinit var auditEventConverter: AuditEventConverter - - private lateinit var customAuditEventRepository: CustomAuditEventRepository - - @BeforeEach - fun setup() { - <%_ if (databaseType === 'couchbase') { _%> - mockAuthentication() - <%_ } _%> - customAuditEventRepository = CustomAuditEventRepository(persistenceAuditEventRepository, auditEventConverter) - persistenceAuditEventRepository.deleteAll() - val oneHourAgo = Instant.now().minusSeconds(3600) - - val testUserEvent = PersistentAuditEvent( - principal = "test-user", - auditEventType = "test-type", - auditEventDate = oneHourAgo, - data = mutableMapOf("test-key" to "test-value") - ) - - val testOldUserEvent = PersistentAuditEvent( - principal = "test-user", - auditEventType = "test-type", - auditEventDate = oneHourAgo.minusSeconds(10000) - ) - - val testOtherUserEvent = PersistentAuditEvent( - principal = "other-test-user", - auditEventType = "test-type", - auditEventDate = oneHourAgo - ) - } - - @Test - fun addAuditEvent() { - val data = mutableMapOf("test-key" to "test-value") - val event = AuditEvent("test-user", "test-type", data) - customAuditEventRepository.add(event) - val persistentAuditEvents = persistenceAuditEventRepository.findAll() - assertThat(persistentAuditEvents).hasSize(1) - val persistentAuditEvent = persistentAuditEvents[0] - assertThat(persistentAuditEvent.principal).isEqualTo(event.principal) - assertThat(persistentAuditEvent.auditEventType).isEqualTo(event.type) - <%_ if (databaseType !== 'neo4j') { _%> - assertThat(persistentAuditEvent.data).containsKey("test-key") - assertThat(persistentAuditEvent.data["test-key"]).isEqualTo("test-value") - <%_ } _%> - assertThat(persistentAuditEvent.auditEventDate!!.truncatedTo(ChronoUnit.MILLIS)) - .isEqualTo(event.timestamp!!.truncatedTo(ChronoUnit.MILLIS)) - } - - @Test - fun addAuditEventTruncateLargeData() { - val data = mutableMapOf() - val largeData = StringBuilder() - for (i in 0 until EVENT_DATA_COLUMN_MAX_LENGTH + 10) { - largeData.append("a") - } - data["test-key"] = largeData - val event = AuditEvent("test-user", "test-type", data) - customAuditEventRepository.add(event) - val persistentAuditEvents = persistenceAuditEventRepository.findAll() - assertThat(persistentAuditEvents).hasSize(1) - val persistentAuditEvent = persistentAuditEvents[0] - assertThat(persistentAuditEvent.principal).isEqualTo(event.principal) - assertThat(persistentAuditEvent.auditEventType).isEqualTo(event.type) - <%_ if (databaseType !== 'neo4j') { _%> - assertThat(persistentAuditEvent.data).containsKey("test-key") - val actualData = persistentAuditEvent.data["test-key"] - assertThat(actualData!!.length).isEqualTo(EVENT_DATA_COLUMN_MAX_LENGTH) - assertThat(actualData).isSubstringOf(largeData) - <%_ } _%> - assertThat(persistentAuditEvent.auditEventDate!!.truncatedTo(ChronoUnit.MILLIS)) - .isEqualTo(event.timestamp!!.truncatedTo(ChronoUnit.MILLIS)) - } - <%_ if (!reactive) { _%> - - @Test - fun testAddEventWithWebAuthenticationDetails() { - val session = MockHttpSession(null, "test-session-id") - val request = MockHttpServletRequest() - request.session = session - request.remoteAddr = "1.2.3.4" - val details = WebAuthenticationDetails(request) - val data = mutableMapOf("test-key" to details) - val event = AuditEvent("test-user", "test-type", data) - customAuditEventRepository.add(event) - val persistentAuditEvents = persistenceAuditEventRepository.findAll() - assertThat(persistentAuditEvents).hasSize(1) - <%_ if (databaseType !== 'neo4j') { _%> - val persistentAuditEvent = persistentAuditEvents[0] - assertThat(persistentAuditEvent.data["remoteAddress"]).isEqualTo("1.2.3.4") - assertThat(persistentAuditEvent.data["sessionId"]).isEqualTo("test-session-id") - <%_ } _%> - } - <%_ } _%> - - @Test - fun testAddEventWithNullData() { - val data = mutableMapOf("test-key" to null) - val event = AuditEvent("test-user", "test-type", data) - customAuditEventRepository.add(event) - val persistentAuditEvents = persistenceAuditEventRepository.findAll() - assertThat(persistentAuditEvents).hasSize(1) - <%_ if (databaseType !== 'neo4j') { _%> - val persistentAuditEvent = persistentAuditEvents[0] - assertThat(persistentAuditEvent.data["test-key"]).isNull() - <%_ } _%> - } - - @Test - fun addAuditEventWithAnonymousUser() { - val data = mutableMapOf("test-key" to "test-value") - val event = AuditEvent(ANONYMOUS_USER, "test-type", data) - customAuditEventRepository.add(event) - val persistentAuditEvents = persistenceAuditEventRepository.findAll() - assertThat(persistentAuditEvents).hasSize(0) - } - - @Test - fun addAuditEventWithAuthorizationFailureType() { - val data = mutableMapOf("test-key" to "test-value") - val event = AuditEvent("test-user", "AUTHORIZATION_FAILURE", data) - customAuditEventRepository.add(event) - val persistentAuditEvents = persistenceAuditEventRepository.findAll() - assertThat(persistentAuditEvents).hasSize(0) - } -} diff --git a/generators/server/templates/src/test/kotlin/package/repository/timezone/DateTimeWrapper.kt.ejs b/generators/server/templates/src/test/kotlin/package/repository/timezone/DateTimeWrapper.kt.ejs index 70409074e..832acd89b 100644 --- a/generators/server/templates/src/test/kotlin/package/repository/timezone/DateTimeWrapper.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/repository/timezone/DateTimeWrapper.kt.ejs @@ -18,29 +18,15 @@ -%> package <%= packageName %>.repository.timezone -import javax.persistence.Column -import javax.persistence.Entity -import javax.persistence.GeneratedValue -import javax.persistence.GenerationType -import javax.persistence.Id -<%_ if (!(prodDatabaseType === 'mysql' || prodDatabaseType === 'mariadb')) { _%> -import javax.persistence.SequenceGenerator -<%_ } _%> -import javax.persistence.Table +import javax.persistence.* import java.io.Serializable -import java.time.Instant -import java.time.LocalDate -import java.time.LocalDateTime -import java.time.LocalTime -import java.time.OffsetDateTime -import java.time.OffsetTime -import java.time.ZonedDateTime +import java.time.* @Entity @Table(name = "<%= jhiTablePrefix %>_date_time_wrapper") class DateTimeWrapper( @Id - <%_ if (prodDatabaseType === 'mysql' || prodDatabaseType === 'mariadb') { _%> + <%_ if (prodDatabaseType === 'mysql') { _%> @GeneratedValue(strategy = GenerationType.IDENTITY) <%_ } else { _%> @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") diff --git a/generators/server/templates/src/test/kotlin/package/security/DomainUserDetailsServiceIT.kt.ejs b/generators/server/templates/src/test/kotlin/package/security/DomainUserDetailsServiceIT.kt.ejs index 7b32f3b1e..37a827db9 100644 --- a/generators/server/templates/src/test/kotlin/package/security/DomainUserDetailsServiceIT.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/security/DomainUserDetailsServiceIT.kt.ejs @@ -21,13 +21,7 @@ package <%= packageName %>.security <%_ if (databaseType === 'cassandra') { _%> import <%= packageName %>.AbstractCassandraTest <%_ } _%> -<%_ if (cacheProvider === 'redis') { _%> -import <%= packageName %>.RedisTestContainerExtension -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import <%= packageName %>.AbstractNeo4jIT -<%_ } _%> -import <%= packageName %>.<%= mainClass %> +import <%= packageName %>.IntegrationTest <%_ if (databaseType === 'sql' && reactive) { _%> import <%= packageName %>.config.SYSTEM_ACCOUNT <%_ } _%> @@ -37,14 +31,7 @@ import <%= packageName %>.repository.UserRepository import org.apache.commons.lang3.RandomStringUtils import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test -<%_ if (cacheProvider === 'redis') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest <%_ if (reactive) { _%> import org.springframework.security.core.userdetails.ReactiveUserDetailsService <%_ } _%> @@ -76,19 +63,13 @@ private const val USER_THREE_EMAIL = "test-user-three@localhost" /** * Integration tests for [DomainUserDetailsService]. */ -@SpringBootTest(classes = [<%= mainClass %>::class]) -<%_ if (databaseType === 'neo4j') { _%> -@ExtendWith(AbstractNeo4jIT::class) -<%_ } _%> <%_ if (databaseType === 'sql' && !reactive) { _%> @Transactional <%_ } _%> <%_ if (databaseType === 'couchbase') { _%> @WithMockUser("test-user-one") <%_ } _%> -<%_ if (cacheProvider === 'redis') { _%> -@ExtendWith(RedisTestContainerExtension::class) -<%_ } _%> +@IntegrationTest class DomainUserDetailsServiceIT <% if (databaseType === 'cassandra') { %>: AbstractCassandraTest() <% } %>{ @Autowired diff --git a/generators/server/templates/src/test/kotlin/package/security/OAuth2TokenMockUtil.kt.ejs b/generators/server/templates/src/test/kotlin/package/security/OAuth2TokenMockUtil.kt.ejs deleted file mode 100644 index 8dbbe1c22..000000000 --- a/generators/server/templates/src/test/kotlin/package/security/OAuth2TokenMockUtil.kt.ejs +++ /dev/null @@ -1,80 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.security - -import org.springframework.boot.test.mock.mockito.MockBean -import org.springframework.mock.web.MockHttpServletRequest -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken -import org.springframework.security.core.authority.SimpleGrantedAuthority -import org.springframework.security.core.userdetails.User -import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken -import org.springframework.security.oauth2.provider.OAuth2Authentication -import org.springframework.security.oauth2.provider.OAuth2Request -import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices -import org.springframework.stereotype.Component -import org.springframework.test.web.servlet.request.RequestPostProcessor - -import java.util.UUID - -import org.mockito.BDDMockito.given - -/** - * A bean providing simple mocking of OAuth2 access tokens for security integration tests. - */ -@Component -class OAuth2TokenMockUtil { - - @MockBean - private lateinit var tokenServices: ResourceServerTokenServices - - private fun createAuthentication(username: String, scopes: Set, roles: Set): OAuth2Authentication { - val authorities = roles.map { SimpleGrantedAuthority(it) } - - val principal = User(username, "test", true, true, true, true, authorities) - val authentication = UsernamePasswordAuthenticationToken( - principal, principal.password, principal.authorities - ) - - // Create the authorization request and OAuth2Authentication object - val authRequest = OAuth2Request(null, "testClient", null, true, scopes, null, null, null, null) - return OAuth2Authentication(authRequest, authentication) - } - - @JvmOverloads - fun oauth2Authentication( - username: String, - scopes: Set = emptySet(), - roles: Set = emptySet() - ): RequestPostProcessor { - val uuid = UUID.randomUUID().toString() - - given(tokenServices.loadAuthentication(uuid)) - .willReturn(createAuthentication(username, scopes, roles)) - - given(tokenServices.readAccessToken(uuid)).willReturn(DefaultOAuth2AccessToken(uuid)) - - return OAuth2PostProcessor(uuid) - } - - class OAuth2PostProcessor(private val token: String) : RequestPostProcessor { - - override fun postProcessRequest(mockHttpServletRequest: MockHttpServletRequest) = - mockHttpServletRequest.apply { addHeader("Authorization", "Bearer $token") } - } -} diff --git a/generators/server/templates/src/test/kotlin/package/security/SecurityUtilsUnitTest.kt.ejs b/generators/server/templates/src/test/kotlin/package/security/SecurityUtilsUnitTest.kt.ejs index 48d2a479a..9126a9fa5 100644 --- a/generators/server/templates/src/test/kotlin/package/security/SecurityUtilsUnitTest.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/security/SecurityUtilsUnitTest.kt.ejs @@ -18,6 +18,8 @@ -%> package <%= packageName %>.security +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.springframework.security.authentication.UsernamePasswordAuthenticationToken import org.springframework.security.core.authority.SimpleGrantedAuthority @@ -50,8 +52,13 @@ import org.springframework.security.oauth2.core.oidc.endpoint.OidcParameterNames * Test class for the Security Utility methods. */ class SecurityUtilsUnitTest { + <%_ if (!reactive) { _%> + @BeforeEach + @AfterEach + fun cleanup() { + SecurityContextHolder.clearContext() + } -<%_ if (!reactive) { _%> @Test fun testgetCurrentUserLogin() { val securityContext = SecurityContextHolder.createEmptyContext() @@ -66,15 +73,15 @@ class SecurityUtilsUnitTest { fun testGetCurrentUserLoginForOAuth2() { val securityContext = SecurityContextHolder.createEmptyContext() val claims = mapOf( - "groups" to "ROLE_USER", + "groups" to USER, "sub" to 123, "preferred_username" to "admin" ) val idToken = OidcIdToken(ID_TOKEN, Instant.now(), Instant.now().plusSeconds(60), claims) val authorities = listOf(SimpleGrantedAuthority(USER)) val user = DefaultOidcUser(authorities, idToken) - val bla = OAuth2AuthenticationToken(user, authorities, "oidc") - securityContext.authentication = bla + val auth2AuthenticationToken = OAuth2AuthenticationToken(user, authorities, "oidc") + securityContext.authentication = auth2AuthenticationToken SecurityContextHolder.setContext(securityContext) val login = getCurrentUserLogin() @@ -114,14 +121,14 @@ class SecurityUtilsUnitTest { } @Test - fun testIsCurrentUserInRole() { + fun testHasCurrentUserThisAuthority() { val securityContext = SecurityContextHolder.createEmptyContext() val authorities = listOf(SimpleGrantedAuthority(USER)) securityContext.authentication = UsernamePasswordAuthenticationToken("user", "user", authorities) SecurityContextHolder.setContext(securityContext) - assertThat(isCurrentUserInRole(USER)).isTrue() - assertThat(isCurrentUserInRole(ADMIN)).isFalse() + assertThat(hasCurrentUserThisAuthority(USER)).isTrue() + assertThat(hasCurrentUserThisAuthority(ADMIN)).isFalse() } <%_ } _%> <%_ if (reactive) { _%> @@ -177,20 +184,20 @@ class SecurityUtilsUnitTest { } @Test - fun testIsCurrentUserInRole() { + fun testHasCurrentUserThisAuthority() { val authorities = mutableListOf(SimpleGrantedAuthority(USER)) val context = ReactiveSecurityContextHolder.withAuthentication( UsernamePasswordAuthenticationToken("admin", "admin", authorities) ) - var isCurrentUserInRole = isCurrentUserInRole(USER) + var hasCurrentUserThisAuthority = hasCurrentUserThisAuthority(USER) .subscriberContext(context) .block() - assertThat(isCurrentUserInRole!!).isTrue() + assertThat(hasCurrentUserThisAuthority!!).isTrue() - isCurrentUserInRole = isCurrentUserInRole(ADMIN) + hasCurrentUserThisAuthority = hasCurrentUserThisAuthority(ADMIN) .subscriberContext(context) .block() - assertThat(isCurrentUserInRole!!).isFalse() + assertThat(hasCurrentUserThisAuthority!!).isFalse() } <%_ } _%> } diff --git a/generators/server/templates/src/test/kotlin/package/security/jwt/JWTFilterTest.kt.ejs b/generators/server/templates/src/test/kotlin/package/security/jwt/JWTFilterTest.kt.ejs index d911a206b..fef7c2e7c 100644 --- a/generators/server/templates/src/test/kotlin/package/security/jwt/JWTFilterTest.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/security/jwt/JWTFilterTest.kt.ejs @@ -19,7 +19,7 @@ package <%= packageName %>.security.jwt import <%= packageName %>.security.USER -import io.github.jhipster.config.JHipsterProperties +import tech.jhipster.config.JHipsterProperties import io.jsonwebtoken.io.Decoders import io.jsonwebtoken.security.Keys @@ -59,14 +59,10 @@ class JWTFilterTest { @BeforeEach fun setup() { val jHipsterProperties = JHipsterProperties() + val base64Secret = "fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8" + jHipsterProperties.security.authentication.jwt.base64Secret = base64Secret tokenProvider = TokenProvider(jHipsterProperties) - ReflectionTestUtils.setField( - tokenProvider, "key", - Keys.hmacShaKeyFor( - Decoders.BASE64 - .decode("fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8") - ) - ) + ReflectionTestUtils.setField(tokenProvider, "key", Keys.hmacShaKeyFor(Decoders.BASE64.decode(base64Secret))) ReflectionTestUtils.setField(tokenProvider, "tokenValidityInMilliseconds", 60000) jwtFilter = JWTFilter(tokenProvider) @@ -95,7 +91,7 @@ class JWTFilterTest { jwtFilter.doFilter(request, response, filterChain) assertThat(response.status).isEqualTo(HttpStatus.OK.value()) assertThat(SecurityContextHolder.getContext().authentication.name).isEqualTo("test-user") - assertThat(SecurityContextHolder.getContext().authentication.credentials.toString()).isEqualTo(jwt) + assertThat(SecurityContextHolder.getContext().authentication.credentials.toString()).hasToString(jwt) <%_ } else { _%> val request = MockServerHttpRequest .get("/api/test") @@ -106,7 +102,7 @@ class JWTFilterTest { .flatMap { ReactiveSecurityContextHolder.getContext() } .map(SecurityContext::getAuthentication) .doOnSuccess { auth -> assertThat(auth.name).isEqualTo("test-user") } - .doOnSuccess { auth -> assertThat(auth.credentials.toString()).isEqualTo(jwt) } + .doOnSuccess { auth -> assertThat(auth.credentials.toString()).hasToString(jwt) } .then() }.block() <%_ } _%> diff --git a/generators/server/templates/src/test/kotlin/package/security/jwt/TokenProviderTest.kt.ejs b/generators/server/templates/src/test/kotlin/package/security/jwt/TokenProviderTest.kt.ejs index 75509c903..91853840c 100644 --- a/generators/server/templates/src/test/kotlin/package/security/jwt/TokenProviderTest.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/security/jwt/TokenProviderTest.kt.ejs @@ -31,12 +31,14 @@ import org.springframework.security.core.GrantedAuthority import org.springframework.security.core.authority.SimpleGrantedAuthority import org.springframework.test.util.ReflectionTestUtils -import io.github.jhipster.config.JHipsterProperties +import tech.jhipster.config.JHipsterProperties import io.jsonwebtoken.Jwts import io.jsonwebtoken.SignatureAlgorithm import io.jsonwebtoken.io.Decoders import io.jsonwebtoken.security.Keys +import java.nio.charset.StandardCharsets + import org.assertj.core.api.Assertions.assertThat private const val ONE_MINUTE: Long = 60000 @@ -48,11 +50,11 @@ class TokenProviderTest { @BeforeEach fun setup() { - tokenProvider = TokenProvider(JHipsterProperties()) - key = Keys.hmacShaKeyFor( - Decoders.BASE64 - .decode("fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8") - ) + val jHipsterProperties = JHipsterProperties() + val base64Secret = "fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8" + jHipsterProperties.security.authentication.jwt.base64Secret = base64Secret + tokenProvider = TokenProvider(jHipsterProperties) + key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(base64Secret)) ReflectionTestUtils.setField(tokenProvider, "key", key) ReflectionTestUtils.setField(tokenProvider, "tokenValidityInMilliseconds", ONE_MINUTE) @@ -62,7 +64,7 @@ class TokenProviderTest { fun testReturnFalseWhenJWThasInvalidSignature() { val isTokenValid = tokenProvider.validateToken(createTokenWithDifferentSignature()) - assertThat(isTokenValid).isEqualTo(false) + assertThat(isTokenValid).isFalse() } @Test @@ -72,7 +74,7 @@ class TokenProviderTest { val invalidToken = token.substring(1) val isTokenValid = tokenProvider.validateToken(invalidToken) - assertThat(isTokenValid).isEqualTo(false) + assertThat(isTokenValid).isFalse() } @Test @@ -84,7 +86,7 @@ class TokenProviderTest { val isTokenValid = tokenProvider.validateToken(token) - assertThat(isTokenValid).isEqualTo(false) + assertThat(isTokenValid).isFalse() } @Test @@ -93,16 +95,41 @@ class TokenProviderTest { val isTokenValid = tokenProvider.validateToken(unsupportedToken) - assertThat(isTokenValid).isEqualTo(false) + assertThat(isTokenValid).isFalse() } @Test fun testReturnFalseWhenJWTisInvalid() { val isTokenValid = tokenProvider.validateToken("") - assertThat(isTokenValid).isEqualTo(false) + assertThat(isTokenValid).isFalse() + } + + @Test + fun testKeyIsSetFromSecretWhenSecretIsNotEmpty() { + val secret = "NwskoUmKHZtzGRKJKVjsJF7BtQMMxNWi" + val jHipsterProperties = JHipsterProperties() + jHipsterProperties.security.authentication.jwt.secret = secret + + val tokenProvider = TokenProvider(jHipsterProperties) + + val key = ReflectionTestUtils.getField(tokenProvider, "key") as Key + assertThat(key).isNotNull.isEqualTo(Keys.hmacShaKeyFor(secret.encodeToByteArray())) } + @Test + fun testKeyIsSetFromBase64SecretWhenSecretIsEmpty() { + val base64Secret = "fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8" + val jHipsterProperties = JHipsterProperties() + jHipsterProperties.security.authentication.jwt.base64Secret = base64Secret + + val tokenProvider = TokenProvider(jHipsterProperties) + + val key = ReflectionTestUtils.getField(tokenProvider, "key") as Key + assertThat(key).isNotNull.isEqualTo(Keys.hmacShaKeyFor(Decoders.BASE64.decode(base64Secret))) + } + + private fun createAuthentication(): Authentication { val authorities = mutableListOf(SimpleGrantedAuthority(ANONYMOUS)) return UsernamePasswordAuthenticationToken("anonymous", "anonymous", authorities) diff --git a/generators/server/templates/src/test/kotlin/package/security/oauth2/AuthorizationHeaderUtilTest.kt.ejs b/generators/server/templates/src/test/kotlin/package/security/oauth2/AuthorizationHeaderUtilTest.kt.ejs new file mode 100644 index 000000000..d707add59 --- /dev/null +++ b/generators/server/templates/src/test/kotlin/package/security/oauth2/AuthorizationHeaderUtilTest.kt.ejs @@ -0,0 +1,215 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + +This file is part of the JHipster project, see https://jhipster.github.io/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %>.security.oauth2 + +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.mockito.InjectMocks +import org.mockito.Mock +import org.mockito.MockitoAnnotations +import org.springframework.boot.web.client.RestTemplateBuilder +import org.springframework.http.RequestEntity +import org.springframework.http.ResponseEntity +import org.springframework.http.converter.HttpMessageConverter +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken +import org.springframework.security.core.authority.SimpleGrantedAuthority +import org.springframework.security.core.context.SecurityContext +import org.springframework.security.core.context.SecurityContextHolder +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService +import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken +import org.springframework.security.oauth2.client.registration.ClientRegistration +import org.springframework.security.oauth2.core.* +import org.springframework.security.oauth2.core.oidc.OidcIdToken +import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser +import org.springframework.security.oauth2.jwt.Jwt +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken +import org.springframework.web.client.ResponseErrorHandler +import org.springframework.web.client.RestTemplate + +import java.time.Duration +import java.time.Instant +import java.util.Optional + +import org.mockito.ArgumentMatchers.* +import org.mockito.Mockito.* + +/** + * Test class for the [AuthorizationHeaderUtil] utility class. + */ +class AuthorizationHeaderUtilTest { + + companion object { + const val VALID_REGISTRATION_ID: String = "OIDC" + const val SUB_VALUE: String = "123456" + } + + @Mock private lateinit var clientService: OAuth2AuthorizedClientService + @Mock private lateinit var restTemplateBuilder: RestTemplateBuilder + @Mock private lateinit var securityContext: SecurityContext + @InjectMocks private lateinit var authorizationHeaderUtil: AuthorizationHeaderUtil + + @BeforeEach + fun setup() { + MockitoAnnotations.initMocks(this) + SecurityContextHolder.setContext(securityContext) + + doReturn(restTemplateBuilder).when(restTemplateBuilder).additionalMessageConverters(any(HttpMessageConverter::class)) + doReturn(restTemplateBuilder).when(restTemplateBuilder).errorHandler(any(ResponseErrorHandler::class)) + doReturn(restTemplateBuilder).when(restTemplateBuilder).basicAuthentication(anyString(), anyString()) + } + + @Test + fun getAuthorizationHeader_Authentication() { + val authenticationToken = UsernamePasswordAuthenticationToken("principal", "credentials") + doReturn(authenticationToken).when(securityContext).getAuthentication() + + val header = authorizationHeaderUtil.getAuthorizationHeader() + + Assertions.assertThat(header).isNotNull().isEmpty() + } + + @Test + fun getAuthorizationHeader_JwtAuthentication() { + val jwtToken = JwtAuthenticationToken(Jwt("tokenVal", Instant.now(), + Instant.now().plus(Duration.ofMinutes(3)),hashMapOf("alg" to "HS256"), hashMapOf("sub" to SUB_VALUE))) + doReturn(jwtToken).when(securityContext).getAuthentication() + + val header = authorizationHeaderUtil.getAuthorizationHeader() + + Assertions.assertThat(header).isNotNull().isNotEmpty().get().isEqualTo("Bearer tokenVal") + } + + @Test + fun getAuthorizationHeader_OAuth2Authentication_InvalidClient() { + val oauth2Token = getTestOAuth2AuthenticationToken("INVALID") + val authorizedClient = getTestOAuth2AuthorizedClient() + + doReturn(oauth2Token).when(securityContext).getAuthentication() + doReturn(authorizedClient).when(clientService).loadAuthorizedClient(eq(VALID_REGISTRATION_ID), eq(SUB_VALUE)) + + Assertions.assertThatThrownBy(() -> { + val header = authorizationHeaderUtil.getAuthorizationHeader() + }).isInstanceOf(OAuth2AuthorizationException::class) + .hasMessageContaining("[access_denied] The token is expired") + } + + @Test + fun getAuthorizationHeader_OAuth2Authentication() { + val oauth2Token = getTestOAuth2AuthenticationToken(VALID_REGISTRATION_ID) + val authorizedClient = getTestOAuth2AuthorizedClient() + + doReturn(oauth2Token).when(securityContext).getAuthentication() + doReturn(authorizedClient).when(clientService).loadAuthorizedClient(eq(VALID_REGISTRATION_ID), eq(SUB_VALUE)) + + val header = authorizationHeaderUtil.getAuthorizationHeader() + Assertions.assertThat(header).isNotNull().isNotEmpty().get().isEqualTo("Bearer tokenVal") + } + + @Test + fun getAuthorizationHeader_OAuth2Authentication_RefreshToken() { + val oauth2Token = getTestOAuth2AuthenticationToken(VALID_REGISTRATION_ID) + val authorizedClient = getTestOAuth2AuthorizedClient(true) + + doReturn(oauth2Token).when(securityContext).getAuthentication() + doReturn(authorizedClient).when(clientService).loadAuthorizedClient(eq(VALID_REGISTRATION_ID), eq(SUB_VALUE)) + + val restTemplate = mock(RestTemplate::class) + val refreshResponse = ResponseEntity.of(getTestOAuthIdpTokenResponseDTO(true)) + doReturn(refreshResponse).when(restTemplate).exchange(any(RequestEntity::class), eq(OAuthIdpTokenResponseDTO::class)) + doReturn(restTemplate).when(restTemplateBuilder).build() + + val header = authorizationHeaderUtil.getAuthorizationHeader() + Assertions.assertThat(header).isNotNull().isNotEmpty().get().isEqualTo("Bearer tokenVal") + } + + @Test + fun getAuthorizationHeader_OAuth2Authentication_RefreshToken_NoRefreshToken() { + val oauth2Token = getTestOAuth2AuthenticationToken(VALID_REGISTRATION_ID) + val authorizedClient = getTestOAuth2AuthorizedClient(true) + + doReturn(oauth2Token).when(securityContext).getAuthentication() + doReturn(authorizedClient).when(clientService).loadAuthorizedClient(eq(VALID_REGISTRATION_ID), eq(SUB_VALUE)) + + val restTemplate = mock(RestTemplate::class) + val refreshResponse = ResponseEntity.of(getTestOAuthIdpTokenResponseDTO(false)) + doReturn(refreshResponse).when(restTemplate).exchange(any(RequestEntity::class), eq(OAuthIdpTokenResponseDTO::class)) + doReturn(restTemplate).when(restTemplateBuilder).build() + + val header = authorizationHeaderUtil.getAuthorizationHeader() + Assertions.assertThat(header).isNotNull().isNotEmpty().get().isEqualTo("Bearer tokenVal") + } + + @Test + fun getAuthorizationHeader_OAuth2Authentication_RefreshTokenFails() { + val oauth2Token = getTestOAuth2AuthenticationToken(VALID_REGISTRATION_ID) + val authorizedClient = getTestOAuth2AuthorizedClient(true) + + doReturn(oauth2Token).when(securityContext).getAuthentication() + doReturn(authorizedClient).when(clientService).loadAuthorizedClient(eq(VALID_REGISTRATION_ID), eq(SUB_VALUE)) + + val restTemplate = mock(RestTemplate::class) + doThrow(OAuth2AuthorizationException(OAuth2Error("E"), "error")).when(restTemplate).exchange(any(RequestEntity::class), eq(OAuthIdpTokenResponseDTO::class)) + doReturn(restTemplate).when(restTemplateBuilder).build() + + Assertions.assertThatThrownBy(() -> { + val header = authorizationHeaderUtil.getAuthorizationHeader() + }).isInstanceOf(OAuth2AuthenticationException::class) + .hasMessageContaining("error") + } + + private fun getTestOAuth2AuthorizedClient() = getTestOAuth2AuthorizedClient(false) + + private fun getTestOAuth2AuthorizedClient(accessTokenExpired: boolean):OAuth2AuthorizedClient { + val end = if (accessTokenExpired) Instant.now() else Instant.now().plus(Duration.ofMinutes(3)) + return OAuth2AuthorizedClient( + ClientRegistration.withRegistrationId(VALID_REGISTRATION_ID) + .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) + .clientId("web-app") + .clientSecret("secret") + .redirectUriTemplate("/login/oauth2/code/oidc") + .authorizationUri("http://localhost:8080/auth/realms/master/protocol/openid-connect/auth") + .tokenUri("https://localhost:8080/auth/realms/master/protocol/openid-connect/token") + .build(), + "sub", + OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "tokenVal", Instant.now(), end), + OAuth2RefreshToken("refreshVal", Instant.now())) + } + + private fun getTestOAuth2AuthenticationToken(registrationId" String): OAuth2AuthenticationToken{ + return OAuth2AuthenticationToken( + DefaultOidcUser(listOf(SimpleGrantedAuthority("USER")), + OidcIdToken.withTokenValue("tokenVal").claim("sub", SUB_VALUE).build()), + listOf(SimpleGrantedAuthority("USER")), registrationId) + } + + private fun getTestOAuthIdpTokenResponseDTO(hasRefreshToken: boolean): Optional { + val dto = OAuthIdpTokenResponseDTO() + dto.accessToken = "tokenVal" + dto.idToken = "tokenVal" + dto.notBefore = 0L + dto.refreshExpiresIn = "1800" + dto.sessionState = "ccea4a55" + dto.expiresIn = 300L + dto.refreshToken = if (hasRefreshToken) "tokenVal" else null + dto.scope = "openid email profile offline_access" + return Optional.of(dto) + } +} diff --git a/generators/server/templates/src/test/kotlin/package/security/oauth2/CookieCollectionTest.kt.ejs b/generators/server/templates/src/test/kotlin/package/security/oauth2/CookieCollectionTest.kt.ejs deleted file mode 100644 index b0268b95b..000000000 --- a/generators/server/templates/src/test/kotlin/package/security/oauth2/CookieCollectionTest.kt.ejs +++ /dev/null @@ -1,211 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.security.oauth2 - -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test - -import javax.servlet.http.Cookie - -import org.assertj.core.api.Assertions.assertThat - -private const val COOKIE_NAME = "chocolate" -private const val COOKIE_VALUE = "yummy" -private const val BROWNIE_NAME = "brownie" - -/** - * Test the [CookieCollection]. - */ -class CookieCollectionTest { - private lateinit var cookie: Cookie - private lateinit var cupsCookie: Cookie - private lateinit var brownieCookie: Cookie - - @BeforeEach - fun setUp() { - cookie = Cookie(COOKIE_NAME, COOKIE_VALUE) - cupsCookie = Cookie("cups", "delicious") - brownieCookie = Cookie(BROWNIE_NAME, "mmh") - } - - @Test - fun size() { - val cookies = CookieCollection() - assertThat(cookies).hasSize(0) - cookies.add(cookie) - assertThat(cookies).hasSize(1) - } - - @Test - fun isEmpty() { - val cookies = CookieCollection() - assertThat(cookies).isEmpty() - cookies.add(cookie) - assertThat(cookies).isNotEmpty - } - - @Test - fun contains() { - val cookies = CookieCollection(cookie) - assertThat(cookies.contains(cookie)).isTrue() - assertThat(cookies.contains(COOKIE_NAME)).isTrue() - assertThat(cookies.contains("yuck")).isFalse() - } - - @Test - operator fun iterator() { - val cookies = CookieCollection(cookie) - val it = cookies.iterator() - assertThat(it.hasNext()).isTrue() - assertThat(it.next()).isEqualTo(cookie) - assertThat(it.hasNext()).isFalse() - } - - @Test - fun toArray() { - val cookies = CookieCollection(cookie) - val array = cookies.toArray() - assertThat(array).hasSameSizeAs(cookies) - assertThat(array[0]).isEqualTo(cookie) - } - - @Test - fun toArray1() { - val cookies = CookieCollection(cookie) - val array = cookies.toArray() - assertThat(array).hasSameSizeAs(cookies) - assertThat(array[0]).isEqualTo(cookie) - } - - @Test - fun add() { - val cookies = CookieCollection(cookie) - val newCookie = Cookie(BROWNIE_NAME, "mmh") - cookies.add(newCookie) - assertThat(cookies).hasSize(2) - assertThat(cookies.contains(newCookie)).isTrue() - assertThat(cookies.contains(BROWNIE_NAME)).isTrue() - } - - @Test - fun addAgain() { - val cookies = CookieCollection(cookie, brownieCookie, cupsCookie) - val white = Cookie(COOKIE_NAME, "white") - val modified = cookies.add(white) - assertThat(modified).isTrue() - assertThat(cookies[COOKIE_NAME]).isEqualTo(white) - assertThat(cookies.contains(white)).isTrue() - assertThat(cookies.contains(cookie)).isFalse() - assertThat(cookies.contains(COOKIE_NAME)).isTrue() - } - - @Test - fun get() { - val cookies = CookieCollection(cookie, brownieCookie, cupsCookie) - val c = cookies[COOKIE_NAME] - assertThat(c).isNotNull - assertThat(c).isEqualTo(cookie) - } - - @Test - fun remove() { - val cookies = CookieCollection(cookie, brownieCookie, cupsCookie) - cookies.remove(cookie) - assertThat(cookies).hasSize(2) - assertThat(cookies.contains(cookie)).isFalse() - assertThat(cookies.contains(COOKIE_NAME)).isFalse() - assertThat(cookies.contains(brownieCookie)).isTrue() - assertThat(cookies.contains(BROWNIE_NAME)).isTrue() - } - - @Test - fun containsAll() { - val content = listOf(cookie, brownieCookie) - val cookies = CookieCollection(content) - assertThat(cookies.containsAll(content)).isTrue() - assertThat(cookies.containsAll(listOf(cookie))).isTrue() - assertThat(cookies.containsAll(listOf(cookie, brownieCookie, cupsCookie))).isFalse() - } - - @Test - fun addAll() { - val cookies = CookieCollection() - val content = listOf(cookie, brownieCookie, cupsCookie) - var modified = cookies.addAll(content) - assertThat(modified).isTrue() - assertThat(cookies).hasSize(3) - assertThat(cookies).containsAll(content) - modified = cookies.addAll(listOf()) - assertThat(modified).isFalse() - } - - @Test - fun addAllEmpty() { - val cookies = CookieCollection(cookie, brownieCookie, cupsCookie) - val modified = cookies.addAll(listOf()) - assertThat(modified).isFalse() - assertThat(cookies).contains(cookie, brownieCookie, cupsCookie) - } - - @Test - fun removeAll() { - val cookies = CookieCollection(cookie, brownieCookie, cupsCookie) - val modified = cookies.removeAll(listOf(brownieCookie, cupsCookie)) - assertThat(modified).isTrue() - assertThat(cookies).hasSize(1) - assertThat(cookies).doesNotContain(brownieCookie, cupsCookie) - } - - @Test - fun removeAllEmpty() { - val cookies = CookieCollection(cookie, brownieCookie, cupsCookie) - val modified = cookies.removeAll(listOf()) - assertThat(modified).isFalse() - assertThat(cookies).contains(cookie, brownieCookie, cupsCookie) - } - - @Test - fun removeAllByName() { - val cookies = CookieCollection(cookie, brownieCookie, cupsCookie) - val modified = cookies.removeAll(listOf(COOKIE_NAME, BROWNIE_NAME)) - assertThat(modified).isTrue() - assertThat(cookies).hasSize(1) - assertThat(cookies).doesNotContain(brownieCookie, cookie) - } - - @Test - fun retainAll() { - val cookies = CookieCollection(cookie, brownieCookie, cupsCookie) - val content = listOf(cookie, brownieCookie) - var modified = cookies.retainAll(content) - assertThat(modified).isTrue() - assertThat(cookies).hasSize(2) - assertThat(cookies).containsAll(content) - assertThat(cookies).doesNotContain(cupsCookie) - modified = cookies.retainAll(content) - assertThat(modified).isFalse() - } - - @Test - fun clear() { - val cookies = CookieCollection(cookie) - cookies.clear() - assertThat(cookies).isEmpty() - } -} diff --git a/generators/server/templates/src/test/kotlin/package/security/oauth2/CookieTokenExtractorTest.kt.ejs b/generators/server/templates/src/test/kotlin/package/security/oauth2/CookieTokenExtractorTest.kt.ejs index 12f74531e..3ad8e0031 100644 --- a/generators/server/templates/src/test/kotlin/package/security/oauth2/CookieTokenExtractorTest.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/security/oauth2/CookieTokenExtractorTest.kt.ejs @@ -19,7 +19,6 @@ package <%= packageName %>.security.oauth2 import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.springframework.http.HttpMethod import org.springframework.mock.web.MockHttpServletRequest @@ -31,12 +30,7 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken */ class CookieTokenExtractorTest { - private lateinit var cookieTokenExtractor: CookieTokenExtractor - - @BeforeEach - fun init() { - cookieTokenExtractor = CookieTokenExtractor() - } + private val cookieTokenExtractor: CookieTokenExtractor = CookieTokenExtractor() @Test fun testExtractTokenCookie() { diff --git a/generators/server/templates/src/test/kotlin/package/security/oauth2/CustomClaimConverterIT.kt.ejs b/generators/server/templates/src/test/kotlin/package/security/oauth2/CustomClaimConverterIT.kt.ejs new file mode 100644 index 000000000..85c5c1c88 --- /dev/null +++ b/generators/server/templates/src/test/kotlin/package/security/oauth2/CustomClaimConverterIT.kt.ejs @@ -0,0 +1,117 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + + This file is part of the JHipster project, see https://jhipster.github.io/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %>.security.oauth2 + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.node.ObjectNode +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.assertThatCode +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.mockito.ArgumentMatchers.any +import org.mockito.ArgumentMatchers.eq +import org.mockito.Mockito.`when` +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.mock.mockito.MockBean +import org.springframework.http.HttpEntity +import org.springframework.http.HttpMethod +import org.springframework.http.ResponseEntity +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository +import org.springframework.web.client.RestTemplate +import <%= packageName %>.<%= mainClass %> +import <%= packageName %>.config.TestSecurityConfiguration +import <%= packageName %>.security.ADMIN +import <%= packageName %>.security.USER +import <%= packageName %>.IntegrationTest + +private const val USERNAME = "admin" +private const val NAME = "John" +private const val FAMILY_NAME = "Doe" + +@IntegrationTest +class CustomClaimConverterIT { + + @MockBean + private lateinit var restTemplate: RestTemplate + + @Autowired + private lateinit var clientRegistrationRepository: ClientRegistrationRepository + + private lateinit var customClaimConverter: CustomClaimConverter + + private val mapper = ObjectMapper() + + @BeforeEach + fun initTest() { + customClaimConverter = CustomClaimConverter(clientRegistrationRepository.findByRegistrationId("oidc"), restTemplate) + } + + private fun mockHttpGetUserInfo(userInfo: ObjectNode) { + `when`( + restTemplate.exchange( + eq("https://api.jhipster.org/user"), + eq(HttpMethod.GET), + any(HttpEntity::class.java), + any>() + ) + ) + .thenReturn(ResponseEntity.ok(userInfo)) + } + + @Test + fun testConvert() { + // GIVEN + val claims = hashMapOf() + claims["sub"] = "123" + // AND + val user: ObjectNode = mapper.createObjectNode() + user.put("preferred_username", USERNAME) + user.put("given_name", NAME) + user.put("family_name", FAMILY_NAME) + user.putArray("groups").add(ADMIN).add(USER) + + mockHttpGetUserInfo(user) + + val convertedClaims = customClaimConverter.convert(claims) + + // THEN + assertThat(convertedClaims) + .containsEntry("sub", "123") + .containsEntry("preferred_username", USERNAME) + .containsEntry("given_name", NAME) + .containsEntry("family_name", FAMILY_NAME) + .containsEntry("groups", listOf(ADMIN, USER)) + } + + @Test + fun testConvert_withoutGroups() { + // GIVEN + val claims: MutableMap = HashMap() + claims["sub"] = "123" + // AND + val user = mapper.createObjectNode() + user.put("preferred_username", USERNAME) + user.put("given_name", NAME) + user.put("family_name", FAMILY_NAME) + mockHttpGetUserInfo(user) + + // THEN + assertThatCode { customClaimConverter.convert(claims) }.doesNotThrowAnyException() + } +} \ No newline at end of file diff --git a/generators/server/templates/src/test/kotlin/package/security/oauth2/OAuth2AuthenticationServiceTest.kt.ejs b/generators/server/templates/src/test/kotlin/package/security/oauth2/OAuth2AuthenticationServiceTest.kt.ejs deleted file mode 100644 index fb080d3b0..000000000 --- a/generators/server/templates/src/test/kotlin/package/security/oauth2/OAuth2AuthenticationServiceTest.kt.ejs +++ /dev/null @@ -1,284 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.security.oauth2 - -import <%= packageName %>.config.oauth2.OAuth2Properties -import <%= packageName %>.web.filter.RefreshTokenFilter -import io.github.jhipster.config.JHipsterProperties -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith -import org.mockito.Mock -import org.mockito.junit.MockitoJUnitRunner -import org.springframework.http.HttpEntity -import org.springframework.http.HttpHeaders -import org.springframework.http.HttpMethod -import org.springframework.http.HttpStatus -import org.springframework.http.MediaType -import org.springframework.http.ResponseEntity -import org.springframework.mock.web.MockHttpServletRequest -import org.springframework.mock.web.MockHttpServletResponse -import org.springframework.security.authentication.BadCredentialsException -import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken -import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken -import org.springframework.security.oauth2.common.OAuth2AccessToken -import org.springframework.security.oauth2.common.exceptions.InvalidTokenException -import org.springframework.security.oauth2.provider.token.TokenStore -import org.springframework.test.context.junit.jupiter.SpringExtension -import org.springframework.util.LinkedMultiValueMap -import org.springframework.util.MultiValueMap -import org.springframework.web.client.HttpClientErrorException -import org.springframework.web.client.RestTemplate - -import javax.servlet.http.Cookie -import java.util.Date - -import org.mockito.Mockito.`when` - -private const val CLIENT_AUTHORIZATION = "Basic d2ViX2FwcDpjaGFuZ2VpdA==" -const val ACCESS_TOKEN_VALUE = - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQyNzI4NDQsInVzZXJfbmFtZSI6InVzZXIiLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiNzc1ZTJkYWUtYWYzZi00YTdhLWExOTktNzNiZTU1MmIxZDVkIiwiY2xpZW50X2lkIjoid2ViX2FwcCIsInNjb3BlIjpbIm9wZW5pZCJdfQ.gEK0YcX2IpkpxnkxXXHQ4I0xzTjcy7edqb89ukYE0LPe7xUcZVwkkCJF_nBxsGJh2jtA6NzNLfY5zuL6nP7uoAq3fmvsyrcyR2qPk8JuuNzGtSkICx3kPDRjAT4ST8SZdeh7XCbPVbySJ7ZmPlRWHyedzLA1wXN0NUf8yZYS4ELdUwVBYIXSjkNoKqfWm88cwuNr0g0teypjPtjDqCnXFt1pibwdfIXn479Y1neNAdvSpHcI4Ost-c7APCNxW2gqX-0BItZQearxRgKDdBQ7CGPAIky7dA0gPuKUpp_VCoqowKCXqkE9yKtRQGIISewtj2UkDRZePmzmYrUBXRzfYw" -const val REFRESH_TOKEN_VALUE = - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJ1c2VyIiwic2NvcGUiOlsib3BlbmlkIl0sImF0aSI6Ijc3NWUyZGFlLWFmM2YtNGE3YS1hMTk5LTczYmU1NTJiMWQ1ZCIsImV4cCI6MTQ5Njg2NDc0MywiYXV0aG9yaXRpZXMiOlsiUk9MRV9VU0VSIl0sImp0aSI6IjhmYjI2YTllLTdjYzQtNDFlMi1hNzBjLTk4MDc0N2U2YWFiOSIsImNsaWVudF9pZCI6IndlYl9hcHAifQ.q1-Df9_AFO6TJNiLKV2YwTjRbnd7qcXv52skXYnog5siHYRoR6cPtm6TNQ04iDAoIHljTSTNnD6DS3bHk41mV55gsSVxGReL8VCb_R8ZmhVL4-5yr90sfms0wFp6lgD2bPmZ-TXiS2Oe9wcbNWagy5RsEplZ-sbXu3tjmDao4FN35ojPsXmUs84XnNQH3Y_-PY9GjZG0JEfLQIvE0J5BkXS18Z015GKyA6GBIoLhAGBQQYyG9m10ld_a9fD5SmCyCF72Jad_pfP1u8Z_WyvO-wrlBvm2x-zBthreVrXU5mOb9795wJEP-xaw3dXYGjht_grcW4vKUFtj61JgZk98CQ" -const val EXPIRED_SESSION_TOKEN_VALUE = - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJ1c2VyIiwic2NvcGUiOlsib3BlbmlkIl0sImF0aSI6IjE0NTkwYzdkLTQ5M2YtNDU0NS05MzlmLTg1ODM4ZjRmNzNmNSIsImV4cCI6MTQ5NTU3Mjg5MywiaWF0IjoxNDk1MzIwODkzLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiNzVhYTIxNzEtMzFmNi00MWJmLWExZGUtYWU0YTg1ZjZiMjEyIiwiY2xpZW50X2lkIjoid2ViX2FwcCJ9.gAH-yly7WAslQUeGhyHmjYXwQN3dluvoT84iOJ2mVWYGVlnDRsoxN3_d1ozqtiso9UM7dWpAr80o3gK7AyK-cO1GGBXa3lg0ETsbucFoqHLivgGZA2qVOsFlDq8E7DZENAbOWmywmhFUOogCfZ-BqsuFSi8waMLL-1qlhehBPuK1KzGxIZbjSVUFFFYTxoWPKi2NNTBzYSwwCV0ixj-gHyFC6Gl5ByA4EvYygGUZF2pACxs4tIRkmT90pXWCjWeKS9k9MlxZ7C4UHqyTRW-IYzqAm8OHdwsnXeu0GkFYc08gxoUuPcjMby8ziYLG5uWj0Ua0msmiSjoafzs-5xfH-Q" -const val NEW_ACCESS_TOKEN_VALUE = - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQyNzY2NDEsInVzZXJfbmFtZSI6InVzZXIiLCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiYzIyY2YzMDgtZTIyYi00YzNjLWI5MjctOTYwYzA2YmY1ZmU0IiwiY2xpZW50X2lkIjoid2ViX2FwcCIsInNjb3BlIjpbIm9wZW5pZCJdfQ.IAhE39GCqWRUuXdWy-raOcE9NYXRhGiqkeJH649501LeqNPH5HtRUNWmudVRgwT52Bj7HcbJapMLGetKIMEASqC1-WARfcZ_PR0r7Kfg3OlFALWOH_oVT5kvi2H-QCoSAF9mRYK6abCh_tPk5KryVB5c7YxTMIXDT2nTsSexD8eNQOMBWRCg0RaLHZ9bKfeyVgncQJsu7-vTo1xJyh-keYpdNZ0TA2SjYJgezmB7gwW1Kmc7_83htr8VycG7XA_PuD9--yRNlrN0LtNHEBqNypZsOe6NvpKiNlodFYHlsU1CaumzcF9U7dpVanjIUKJ5VRWVUlSFY6JJ755W29VCTw" -const val NEW_REFRESH_TOKEN_VALUE = - "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJ1c2VyIiwic2NvcGUiOlsib3BlbmlkIl0sImF0aSI6ImMyMmNmMzA4LWUyMmItNGMzYy1iOTI3LTk2MGMwNmJmNWZlNCIsImV4cCI6MTQ5Njg2ODU4MSwiYXV0aG9yaXRpZXMiOlsiUk9MRV9VU0VSIl0sImp0aSI6ImU4YmZhZWJlLWYzMDItNGNjZS1hZGY1LWQ4MzE5OWM1MjBlOSIsImNsaWVudF9pZCI6IndlYl9hcHAifQ.OemWBUfc-2rl4t4VVqolYxul3L527PbSbX2Xvo7oyy3Vy5nmmblqp4hVGdTEjivrlldGVQX03ERbrA-oFkpmfWbBzLvnKS6AUq1MGjut6dXZJeiEqNYmiAABn6jSgK26S0k6b2ADgmf7mxJO8EBypb5sT1DMAbY5cbOe7r4ZG7zMTVSvlvjHTXp_FM8Y9i6nehLD4XDYY57cb_ZA89vAXNzvTAjoopDliExgR0bApG6nvvDEhEYgTS65lccEQocoev6bISJ3RvNYNPJxWcNPftKDp4HrEt2E2WP28K5IivRtQgDQNlQeormf1tp6AG-Oj__NXyAPM7yhAKXNy2zWdQ" - -/** - * Test password and refresh token grants. - * - * @see OAuth2AuthenticationService - */ -@ExtendWith(SpringExtension::class) -class OAuth2AuthenticationServiceTest { - - @Mock - private lateinit var restTemplate: RestTemplate - @Mock - private lateinit var tokenStore: TokenStore - private lateinit var authenticationService: OAuth2AuthenticationService - private lateinit var refreshTokenFilter: RefreshTokenFilter - - @BeforeEach - fun init() { - val oAuth2Properties = OAuth2Properties() - val jHipsterProperties = JHipsterProperties() - jHipsterProperties.security.clientAuthorization.accessTokenUri = "http://uaa/oauth/token" - val cookieHelper = OAuth2CookieHelper(oAuth2Properties) - val accessToken = createAccessToken(ACCESS_TOKEN_VALUE, REFRESH_TOKEN_VALUE) - - mockInvalidPassword() - mockPasswordGrant(accessToken) - mockRefreshGrant() - - val authorizationClient = UaaTokenEndpointClient(restTemplate, jHipsterProperties, oAuth2Properties) - authenticationService = OAuth2AuthenticationService(authorizationClient, cookieHelper) - `when`(tokenStore.readAccessToken(ACCESS_TOKEN_VALUE)).thenReturn(accessToken) - refreshTokenFilter = RefreshTokenFilter(authenticationService, tokenStore) - } - - private fun mockInvalidPassword() { - val reqHeaders = HttpHeaders() - reqHeaders.contentType = MediaType.APPLICATION_FORM_URLENCODED - // take over Authorization header from client request to UAA request - reqHeaders.add("Authorization", CLIENT_AUTHORIZATION) - val formParams = LinkedMultiValueMap().apply { - set("username", "user") - set("password", "user2") - add("grant_type", "password") - } - val entity = HttpEntity>(formParams, reqHeaders) - `when`(restTemplate.postForEntity("http://uaa/oauth/token", entity, OAuth2AccessToken::class.java)) - .thenThrow(HttpClientErrorException(HttpStatus.BAD_REQUEST)) - } - - private fun mockPasswordGrant(accessToken: OAuth2AccessToken) { - val reqHeaders = HttpHeaders() - reqHeaders.contentType = MediaType.APPLICATION_FORM_URLENCODED - // take over Authorization header from client request to UAA request - reqHeaders.add("Authorization", CLIENT_AUTHORIZATION) - val formParams = LinkedMultiValueMap().apply { - set("username", "user") - set("password", "user") - add("grant_type", "password") - } - val entity = HttpEntity>(formParams, reqHeaders) - `when`(restTemplate.postForEntity("http://uaa/oauth/token", entity, OAuth2AccessToken::class.java)) - .thenReturn(ResponseEntity(accessToken, HttpStatus.OK)) - } - - private fun mockRefreshGrant() { - val params = LinkedMultiValueMap().apply { - add("grant_type", "refresh_token") - add("refresh_token", REFRESH_TOKEN_VALUE) - } - //we must authenticate with the UAA server via HTTP basic authentication using the browser's client_id with no client secret - val headers = HttpHeaders() - headers.add("Authorization", CLIENT_AUTHORIZATION) - val entity = HttpEntity>(params, headers) - val newAccessToken = createAccessToken(NEW_ACCESS_TOKEN_VALUE, NEW_REFRESH_TOKEN_VALUE) - `when`(restTemplate.postForEntity("http://uaa/oauth/token", entity, OAuth2AccessToken::class.java)) - .thenReturn(ResponseEntity(newAccessToken, HttpStatus.OK)) - } - - @Test - fun testAuthenticationCookies() { - val request = MockHttpServletRequest().apply { - serverName = "www.test.com" - addHeader("Authorization", CLIENT_AUTHORIZATION) - } - val params = mutableMapOf( - "username" to "user", - "password" to "user", - "rememberMe" to "true" - ) - val response = MockHttpServletResponse() - authenticationService.authenticate(request, response, params) - // check that cookies are set correctly - val accessTokenCookie = response.getCookie(OAuth2CookieHelper.ACCESS_TOKEN_COOKIE) - Assertions.assertEquals(ACCESS_TOKEN_VALUE, accessTokenCookie!!.value) - val refreshTokenCookie = response.getCookie(OAuth2CookieHelper.REFRESH_TOKEN_COOKIE) - Assertions.assertEquals(REFRESH_TOKEN_VALUE, OAuth2CookieHelper.getRefreshTokenValue(refreshTokenCookie!!)) - Assertions.assertTrue(OAuth2CookieHelper.isRememberMe(refreshTokenCookie)) - } - - @Test - fun testAuthenticationNoRememberMe() { - val request = MockHttpServletRequest() - request.serverName = "www.test.com" - val params = mutableMapOf( - "username" to "user", - "password" to "user", - "rememberMe" to "false" - ) - val response = MockHttpServletResponse() - authenticationService.authenticate(request, response, params) - // check that cookies are set correctly - val accessTokenCookie = response.getCookie(OAuth2CookieHelper.ACCESS_TOKEN_COOKIE) - Assertions.assertEquals(ACCESS_TOKEN_VALUE, accessTokenCookie!!.value) - val refreshTokenCookie = response.getCookie(OAuth2CookieHelper.SESSION_TOKEN_COOKIE) - Assertions.assertEquals(REFRESH_TOKEN_VALUE, OAuth2CookieHelper.getRefreshTokenValue(refreshTokenCookie!!)) - Assertions.assertFalse(OAuth2CookieHelper.isRememberMe(refreshTokenCookie)) - } - - @Test - fun testInvalidPassword() { - val request = MockHttpServletRequest() - request.serverName = "www.test.com" - val params = mutableMapOf( - "username" to "user", - "password" to "user2", - "rememberMe" to "false" - ) - val response = MockHttpServletResponse() - Assertions.assertThrows(BadCredentialsException::class.java) { - authenticationService.authenticate(request, response, params) - } - } - - @Test - fun testRefreshGrant() { - val request = createMockHttpServletRequest() - val response = MockHttpServletResponse() - val newRequest = refreshTokenFilter.refreshTokensIfExpiring(request, response) - val newAccessTokenCookie = response.getCookie(OAuth2CookieHelper.ACCESS_TOKEN_COOKIE) - Assertions.assertEquals(NEW_ACCESS_TOKEN_VALUE, newAccessTokenCookie!!.value) - val newRefreshTokenCookie = response.getCookie(OAuth2CookieHelper.REFRESH_TOKEN_COOKIE) - Assertions.assertEquals(NEW_REFRESH_TOKEN_VALUE, newRefreshTokenCookie!!.value) - val requestAccessTokenCookie = OAuth2CookieHelper.getAccessTokenCookie(newRequest) - Assertions.assertEquals(NEW_ACCESS_TOKEN_VALUE, requestAccessTokenCookie?.value) - } - - @Test - fun testSessionExpired() { - val request = MockHttpServletRequest(HttpMethod.GET.name, "http://www.test.com") - val accessTokenCookie = Cookie(OAuth2CookieHelper.ACCESS_TOKEN_COOKIE, ACCESS_TOKEN_VALUE) - val refreshTokenCookie = Cookie(OAuth2CookieHelper.SESSION_TOKEN_COOKIE, EXPIRED_SESSION_TOKEN_VALUE) - request.setCookies(accessTokenCookie, refreshTokenCookie) - val response = MockHttpServletResponse() - val newRequest = refreshTokenFilter.refreshTokensIfExpiring(request, response) - // cookies in response are deleted - val newAccessTokenCookie = response.getCookie(OAuth2CookieHelper.ACCESS_TOKEN_COOKIE) - Assertions.assertEquals(0, newAccessTokenCookie!!.maxAge.toLong()) - val newRefreshTokenCookie = response.getCookie(OAuth2CookieHelper.REFRESH_TOKEN_COOKIE) - Assertions.assertEquals(0, newRefreshTokenCookie!!.maxAge.toLong()) - // request no longer contains cookies - val requestAccessTokenCookie = OAuth2CookieHelper.getAccessTokenCookie(newRequest) - Assertions.assertNull(requestAccessTokenCookie) - val requestRefreshTokenCookie = OAuth2CookieHelper.getRefreshTokenCookie(newRequest) - Assertions.assertNull(requestRefreshTokenCookie) - } - - /** - * If no refresh token is found and the access token has expired, then expect an exception. - */ - @Test - fun testRefreshGrantNoRefreshToken() { - val request = MockHttpServletRequest(HttpMethod.GET.name, "http://www.test.com") - val accessTokenCookie = Cookie(OAuth2CookieHelper.ACCESS_TOKEN_COOKIE, ACCESS_TOKEN_VALUE) - request.setCookies(accessTokenCookie) - val response = MockHttpServletResponse() - Assertions.assertThrows(InvalidTokenException::class.java) { - refreshTokenFilter.refreshTokensIfExpiring(request, response) - } - } - - @Test - fun testLogout() { - val request = MockHttpServletRequest() - val accessTokenCookie = Cookie(OAuth2CookieHelper.ACCESS_TOKEN_COOKIE, ACCESS_TOKEN_VALUE) - val refreshTokenCookie = Cookie(OAuth2CookieHelper.REFRESH_TOKEN_COOKIE, REFRESH_TOKEN_VALUE) - request.setCookies(accessTokenCookie, refreshTokenCookie) - val response = MockHttpServletResponse() - authenticationService.logout(request, response) - val newAccessTokenCookie = response.getCookie(OAuth2CookieHelper.ACCESS_TOKEN_COOKIE) - Assertions.assertEquals(0, newAccessTokenCookie!!.maxAge.toLong()) - val newRefreshTokenCookie = response.getCookie(OAuth2CookieHelper.REFRESH_TOKEN_COOKIE) - Assertions.assertEquals(0, newRefreshTokenCookie!!.maxAge.toLong()) - } - - @Test - fun testStripTokens() { - val request = createMockHttpServletRequest() - val newRequest = authenticationService.stripTokens(request) - val cookies = CookieCollection(*newRequest.cookies) - Assertions.assertFalse(cookies.contains(OAuth2CookieHelper.ACCESS_TOKEN_COOKIE)) - Assertions.assertFalse(cookies.contains(OAuth2CookieHelper.REFRESH_TOKEN_COOKIE)) - } -} - -fun createAccessToken(accessTokenValue: String, refreshTokenValue: String): OAuth2AccessToken { - val accessToken = DefaultOAuth2AccessToken(accessTokenValue) - accessToken.expiration = Date() // token expires now - val refreshToken = DefaultOAuth2RefreshToken(refreshTokenValue) - accessToken.refreshToken = refreshToken - return accessToken -} - -fun createMockHttpServletRequest(): MockHttpServletRequest { - val request = MockHttpServletRequest(HttpMethod.GET.name, "http://www.test.com") - val accessTokenCookie = Cookie(OAuth2CookieHelper.ACCESS_TOKEN_COOKIE, ACCESS_TOKEN_VALUE) - val refreshTokenCookie = Cookie(OAuth2CookieHelper.REFRESH_TOKEN_COOKIE, REFRESH_TOKEN_VALUE) - request.setCookies(accessTokenCookie, refreshTokenCookie) - return request -} diff --git a/generators/server/templates/src/test/kotlin/package/security/oauth2/OAuth2CookieHelperTest.kt.ejs b/generators/server/templates/src/test/kotlin/package/security/oauth2/OAuth2CookieHelperTest.kt.ejs deleted file mode 100644 index 44dcfa63b..000000000 --- a/generators/server/templates/src/test/kotlin/package/security/oauth2/OAuth2CookieHelperTest.kt.ejs +++ /dev/null @@ -1,119 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://jhipster.github.io/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.security.oauth2 - -import <%= packageName %>.config.oauth2.OAuth2Properties -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.springframework.mock.web.MockHttpServletRequest -import org.springframework.test.util.ReflectionTestUtils - -import org.assertj.core.api.Assertions.assertThat - -private const val GET_COOKIE_DOMAIN_METHOD = "getCookieDomain" - -/** - * Tests helper functions around OAuth2 Cookies. - * - * @see OAuth2CookieHelper - */ -class OAuth2CookieHelperTest { - - private lateinit var oAuth2Properties: OAuth2Properties - private lateinit var cookieHelper: OAuth2CookieHelper - - @BeforeEach - @Throws(NoSuchMethodException::class) - fun setUp() { - oAuth2Properties = OAuth2Properties() - cookieHelper = OAuth2CookieHelper(oAuth2Properties) - } - - @Test - fun testLocalhostDomain() { - val request = MockHttpServletRequest() - request.serverName = "localhost" - val name = ReflectionTestUtils.invokeMethod(cookieHelper, GET_COOKIE_DOMAIN_METHOD, request) - assertThat(name).isNull() - } - - @Test - fun testComDomain() { - val request = MockHttpServletRequest() - request.serverName = "test.com" - val name = ReflectionTestUtils.invokeMethod(cookieHelper, GET_COOKIE_DOMAIN_METHOD, request) - assertThat(name).isNull() // already top-level domain - } - - @Test - fun testWwwDomainCom() { - val request = MockHttpServletRequest() - request.serverName = "www.test.com" - val name = ReflectionTestUtils.invokeMethod(cookieHelper, GET_COOKIE_DOMAIN_METHOD, request) - assertThat(name).isNull() - } - - @Test - fun testComSubDomain() { - val request = MockHttpServletRequest() - request.serverName = "abc.test.com" - val name = ReflectionTestUtils.invokeMethod(cookieHelper, GET_COOKIE_DOMAIN_METHOD, request) - assertThat(name).isEqualTo(".test.com") - } - - @Test - fun testWwwSubDomainCom() { - val request = MockHttpServletRequest() - request.serverName = "www.abc.test.com" - val name = ReflectionTestUtils.invokeMethod(cookieHelper, GET_COOKIE_DOMAIN_METHOD, request) - assertThat(name).isEqualTo(".test.com") - } - - @Test - fun testCoUkDomain() { - val request = MockHttpServletRequest() - request.serverName = "test.co.uk" - val name = ReflectionTestUtils.invokeMethod(cookieHelper, GET_COOKIE_DOMAIN_METHOD, request) - assertThat(name).isNull() // already top-level domain - } - - @Test - fun testCoUkSubDomain() { - val request = MockHttpServletRequest() - request.serverName = "abc.test.co.uk" - val name = ReflectionTestUtils.invokeMethod(cookieHelper, GET_COOKIE_DOMAIN_METHOD, request) - assertThat(name).isEqualTo(".test.co.uk") - } - - @Test - fun testNestedDomain() { - val request = MockHttpServletRequest() - request.serverName = "abc.xyu.test.co.uk" - val name = ReflectionTestUtils.invokeMethod(cookieHelper, GET_COOKIE_DOMAIN_METHOD, request) - assertThat(name).isEqualTo(".test.co.uk") - } - - @Test - fun testIpAddress() { - val request = MockHttpServletRequest() - request.serverName = "127.0.0.1" - val name = ReflectionTestUtils.invokeMethod(cookieHelper, GET_COOKIE_DOMAIN_METHOD, request) - assertThat(name).isNull() - } -} diff --git a/generators/server/templates/src/test/kotlin/package/service/AuditEventServiceIT.kt.ejs b/generators/server/templates/src/test/kotlin/package/service/AuditEventServiceIT.kt.ejs deleted file mode 100644 index 05a141a31..000000000 --- a/generators/server/templates/src/test/kotlin/package/service/AuditEventServiceIT.kt.ejs +++ /dev/null @@ -1,132 +0,0 @@ - -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.service - -import <%= packageName %>.domain.PersistentAuditEvent -<%_ if (cacheProvider === 'redis') { _%> -import <%= packageName %>.RedisTestContainerExtension -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import <%= packageName %>.AbstractNeo4jIT -<%_ } _%> -import <%= packageName %>.repository.PersistenceAuditEventRepository -import <%= packageName %>.<%= mainClass %> -import io.github.jhipster.config.JHipsterProperties -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -<%_ if (cacheProvider === 'redis') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest -<%_ if (databaseType === 'sql' && !reactive) { _%> -import org.springframework.transaction.annotation.Transactional -<%_ } _%> -<%_ if (databaseType === 'couchbase') { _%> -import <%= packageName %>.web.rest.mockAuthentication -<%_ } _%> -<%_ if (authenticationType === 'oauth2') { _%> -import <%= packageName %>.config.TestSecurityConfiguration -<%_ } _%> -import java.time.Instant -import java.time.temporal.ChronoUnit - -import org.assertj.core.api.Assertions.assertThat - -/** - * Integration tests for {@link AuditEventService}. - */ -<%_ if (authenticationType === 'oauth2') { _%> -@SpringBootTest(classes = [<%= mainClass %>::class, TestSecurityConfiguration::class]) -<%_ } else { _%> -@SpringBootTest(classes = [<%= mainClass %>::class]) -<%_ } _%> -<%_ if (cacheProvider === 'redis') { _%> -@ExtendWith(RedisTestContainerExtension::class) -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -@ExtendWith(AbstractNeo4jIT::class) -<%_ } _%> -<%_ if (databaseType === 'sql' && !reactive) { _%> -@Transactional -<%_ } _%> -class AuditEventServiceIT { - @Autowired - private lateinit var auditEventService: AuditEventService - - @Autowired - private lateinit var persistenceAuditEventRepository: PersistenceAuditEventRepository - - @Autowired - private lateinit var jHipsterProperties: JHipsterProperties - - private lateinit var auditEventOld: PersistentAuditEvent - - private lateinit var auditEventWithinRetention: PersistentAuditEvent - - private lateinit var auditEventNew: PersistentAuditEvent - - @BeforeEach - fun init() { - <%_ if (databaseType === 'couchbase') { _%> - mockAuthentication() - <%_ } _%> - auditEventOld = PersistentAuditEvent() - auditEventOld.auditEventDate = Instant.now().minus((jHipsterProperties.auditEvents.retentionPeriod + 1).toLong(), ChronoUnit.DAYS) - auditEventOld.principal = "test-user-old" - auditEventOld.auditEventType = "test-type" - - auditEventWithinRetention = PersistentAuditEvent() - auditEventWithinRetention.auditEventDate = Instant.now().minus((jHipsterProperties.auditEvents.retentionPeriod - 1).toLong(), ChronoUnit.DAYS) - auditEventWithinRetention.principal = "test-user-retention" - auditEventWithinRetention.auditEventType = "test-type" - - auditEventNew = PersistentAuditEvent() - auditEventNew.auditEventDate = Instant.now() - auditEventNew.principal = "test-user-new" - auditEventNew.auditEventType = "test-type" - } - - @Test - <%_ if (databaseType === 'sql' && !reactive) { _%> - @Transactional - <%_ } _%> - fun verifyOldAuditEventsAreDeleted() { - persistenceAuditEventRepository.deleteAll()<% if (reactive) { %>.block()<% } %> - persistenceAuditEventRepository.save(auditEventOld)<% if (reactive) { %>.block()<% } %> - persistenceAuditEventRepository.save(auditEventWithinRetention)<% if (reactive) { %>.block()<% } %> - persistenceAuditEventRepository.save(auditEventNew)<% if (reactive) { %>.block()<% } %> - <%_ if (databaseType === 'sql' && !reactive) { _%> - persistenceAuditEventRepository.flush() - <%_ } _%> - auditEventService.removeOldAuditEvents() - <%_ if (databaseType === 'sql' && !reactive) { _%> - persistenceAuditEventRepository.flush() - <%_ } _%> - - assertThat(persistenceAuditEventRepository.findAll()<% if (reactive) { %>.collectList().block()<% } %>.size).isEqualTo(2) - assertThat(persistenceAuditEventRepository.findByPrincipal("test-user-old")<% if (reactive) { %>.collectList().block()<% } %>).isEmpty() - assertThat(persistenceAuditEventRepository.findByPrincipal("test-user-retention")<% if (reactive) { %>.collectList().block()<% } %>).isNotEmpty() - assertThat(persistenceAuditEventRepository.findByPrincipal("test-user-new")<% if (reactive) { %>.collectList().block()<% } %>).isNotEmpty() - } -} diff --git a/generators/server/templates/src/test/kotlin/package/service/MailServiceIT.kt.ejs b/generators/server/templates/src/test/kotlin/package/service/MailServiceIT.kt.ejs index f6b732f98..c7db16f69 100644 --- a/generators/server/templates/src/test/kotlin/package/service/MailServiceIT.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/service/MailServiceIT.kt.ejs @@ -21,23 +21,11 @@ package <%= packageName %>.service import <%= packageName %>.config.DEFAULT_LANGUAGE <% if (databaseType === 'cassandra') { %> import <%= packageName %>.AbstractCassandraTest<% } %> -<%_ if (cacheProvider === 'redis') { _%> -import <%= packageName %>.RedisTestContainerExtension -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import <%= packageName %>.AbstractNeo4jIT -<%_ } _%> -import <%= packageName %>.<%= mainClass %> +import <%= packageName %>.IntegrationTest import <%= packageName %>.domain.<%= asEntity('User') %> -import io.github.jhipster.config.JHipsterProperties +import tech.jhipster.config.JHipsterProperties import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test -<%_ if (cacheProvider === 'redis') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.any import org.mockito.Captor @@ -47,7 +35,6 @@ import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations import org.mockito.Spy import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest import org.springframework.context.MessageSource import org.springframework.mail.MailSendException import org.springframework.mail.javamail.JavaMailSenderImpl @@ -80,13 +67,7 @@ private val PATTERN_LOCALE_2 = Pattern.compile("([a-z]{2})-([a-z]{2})") /** * Integration tests for [MailService]. */ -@SpringBootTest(classes = [<%= mainClass %>::class]) -<%_ if (cacheProvider === 'redis') { _%> -@ExtendWith(RedisTestContainerExtension::class) -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -@ExtendWith(AbstractNeo4jIT::class) -<%_ } _%> +@IntegrationTest class MailServiceIT <% if (databaseType === 'cassandra') { %>: AbstractCassandraTest() <% } %>{ @Autowired @@ -119,10 +100,10 @@ class MailServiceIT <% if (databaseType === 'cassandra') { %>: AbstractCassandra verify(javaMailSender).send(messageCaptor.capture()) val message = messageCaptor.value assertThat(message.subject).isEqualTo("testSubject") - assertThat(message.allRecipients[0].toString()).isEqualTo("john.doe@example.com") - assertThat(message.from[0].toString()).isEqualTo(jHipsterProperties.mail.from) + assertThat(message.allRecipients[0]).hasToString("john.doe@example.com") + assertThat(message.from[0]).hasToString(jHipsterProperties.mail.from) assertThat(message.content).isInstanceOf(String::class.java) - assertThat(message.content.toString()).isEqualTo("testContent") + assertThat(message.content).hasToString("testContent") assertThat(message.dataHandler.contentType).isEqualTo("text/plain; charset=UTF-8") } @@ -132,10 +113,10 @@ class MailServiceIT <% if (databaseType === 'cassandra') { %>: AbstractCassandra verify(javaMailSender).send(messageCaptor.capture()) val message = messageCaptor.value assertThat(message.subject).isEqualTo("testSubject") - assertThat(message.allRecipients[0].toString()).isEqualTo("john.doe@example.com") - assertThat(message.from[0].toString()).isEqualTo(jHipsterProperties.mail.from) + assertThat(message.allRecipients[0]).hasToString("john.doe@example.com") + assertThat(message.from[0]).hasToString(jHipsterProperties.mail.from) assertThat(message.content).isInstanceOf(String::class.java) - assertThat(message.content.toString()).isEqualTo("testContent") + assertThat(message.content).hasToString("testContent") assertThat(message.dataHandler.contentType).isEqualTo("text/html;charset=UTF-8") } @@ -149,10 +130,10 @@ class MailServiceIT <% if (databaseType === 'cassandra') { %>: AbstractCassandra val aos = ByteArrayOutputStream() part.writeTo(aos) assertThat(message.subject).isEqualTo("testSubject") - assertThat(message.allRecipients[0].toString()).isEqualTo("john.doe@example.com") - assertThat(message.from[0].toString()).isEqualTo(jHipsterProperties.mail.from) + assertThat(message.allRecipients[0]).hasToString("john.doe@example.com") + assertThat(message.from[0]).hasToString(jHipsterProperties.mail.from) assertThat(message.content).isInstanceOf(Multipart::class.java) - assertThat(aos.toString()).isEqualTo("\r\ntestContent") + assertThat(aos).hasToString("\r\ntestContent") assertThat(part.dataHandler.contentType).isEqualTo("text/plain; charset=UTF-8") } @@ -166,10 +147,10 @@ class MailServiceIT <% if (databaseType === 'cassandra') { %>: AbstractCassandra val aos = ByteArrayOutputStream() part.writeTo(aos) assertThat(message.subject).isEqualTo("testSubject") - assertThat(message.allRecipients[0].toString()).isEqualTo("john.doe@example.com") - assertThat(message.from[0].toString()).isEqualTo(jHipsterProperties.mail.from) + assertThat(message.allRecipients[0]).hasToString("john.doe@example.com") + assertThat(message.from[0]).hasToString(jHipsterProperties.mail.from) assertThat(message.content).isInstanceOf(Multipart::class.java) - assertThat(aos.toString()).isEqualTo("\r\ntestContent") + assertThat(aos).hasToString("\r\ntestContent") assertThat(part.dataHandler.contentType).isEqualTo("text/html;charset=UTF-8") } @@ -184,8 +165,8 @@ class MailServiceIT <% if (databaseType === 'cassandra') { %>: AbstractCassandra verify(javaMailSender).send(messageCaptor.capture()) val message = messageCaptor.value assertThat(message.subject).isEqualTo("test title") - assertThat(message.allRecipients[0].toString()).isEqualTo(user.email) - assertThat(message.from[0].toString()).isEqualTo(jHipsterProperties.mail.from) + assertThat(message.allRecipients[0]).hasToString(user.email) + assertThat(message.from[0]).hasToString(jHipsterProperties.mail.from) assertThat(message.content.toString()).isEqualToNormalizingNewlines("test title, http://127.0.0.1:8080, john\n") assertThat(message.dataHandler.contentType).isEqualTo("text/html;charset=UTF-8") } @@ -201,8 +182,8 @@ class MailServiceIT <% if (databaseType === 'cassandra') { %>: AbstractCassandra mailService.sendActivationEmail(user) verify(javaMailSender).send(messageCaptor.capture()) val message = messageCaptor.value - assertThat(message.allRecipients[0].toString()).isEqualTo(user.email) - assertThat(message.from[0].toString()).isEqualTo(jHipsterProperties.mail.from) + assertThat(message.allRecipients[0]).hasToString(user.email) + assertThat(message.from[0]).hasToString(jHipsterProperties.mail.from) assertThat(message.content.toString()).isNotEmpty() assertThat(message.dataHandler.contentType).isEqualTo("text/html;charset=UTF-8") } @@ -217,8 +198,8 @@ class MailServiceIT <% if (databaseType === 'cassandra') { %>: AbstractCassandra mailService.sendCreationEmail(user) verify(javaMailSender).send(messageCaptor.capture()) val message = messageCaptor.value - assertThat(message.allRecipients[0].toString()).isEqualTo(user.email) - assertThat(message.from[0].toString()).isEqualTo(jHipsterProperties.mail.from) + assertThat(message.allRecipients[0]).hasToString(user.email) + assertThat(message.from[0]).hasToString(jHipsterProperties.mail.from) assertThat(message.content.toString()).isNotEmpty() assertThat(message.dataHandler.contentType).isEqualTo("text/html;charset=UTF-8") } @@ -233,8 +214,8 @@ class MailServiceIT <% if (databaseType === 'cassandra') { %>: AbstractCassandra mailService.sendPasswordResetMail(user) verify(javaMailSender).send(messageCaptor.capture()) val message = messageCaptor.value - assertThat(message.allRecipients[0].toString()).isEqualTo(user.email) - assertThat(message.from[0].toString()).isEqualTo(jHipsterProperties.mail.from) + assertThat(message.allRecipients[0]).hasToString(user.email) + assertThat(message.from[0]).hasToString(jHipsterProperties.mail.from) assertThat(message.content.toString()).isNotEmpty() assertThat(message.dataHandler.contentType).isEqualTo("text/html;charset=UTF-8") } diff --git a/generators/server/templates/src/test/kotlin/package/service/UserServiceIT.kt.ejs b/generators/server/templates/src/test/kotlin/package/service/UserServiceIT.kt.ejs index eec03eb15..bda504977 100644 --- a/generators/server/templates/src/test/kotlin/package/service/UserServiceIT.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/service/UserServiceIT.kt.ejs @@ -21,21 +21,11 @@ package <%= packageName %>.service <%_ if (databaseType === 'cassandra') { _%> import <%= packageName %>.AbstractCassandraTest <%_ } _%> -<%_ if (cacheProvider === 'redis') { _%> -import <%= packageName %>.RedisTestContainerExtension -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import <%= packageName %>.AbstractNeo4jIT -<%_ } _%> -import <%= packageName %>.<%= mainClass %> +import <%= packageName %>.IntegrationTest <%_ if (databaseType === 'sql' && reactive) { _%> import <%= packageName %>.config.SYSTEM_ACCOUNT <%_ } _%> -import <%= packageName %>.config.ANONYMOUS_USER import <%= packageName %>.config.DEFAULT_LANGUAGE -<%_ if (authenticationType === 'oauth2') { _%> -import <%= packageName %>.config.TestSecurityConfiguration -<%_ } _%> <%_ if ((databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') && authenticationType === 'session' && !reactive) { _%> import <%= packageName %>.domain.PersistentToken <%_ } _%> @@ -55,7 +45,7 @@ import <%= packageName %>.repository.UserRepository import <%= packageName %>.security.ANONYMOUS <%_ } _%> <%_ if (authenticationType !== 'oauth2' && (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase')) { _%> -import io.github.jhipster.security.RandomUtil +import tech.jhipster.security.RandomUtil <%_ } _%> <%_ if (authenticationType !== 'oauth2') { _%> @@ -63,14 +53,7 @@ import org.apache.commons.lang3.RandomStringUtils <%_ } _%> import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test -<%_ if (cacheProvider === 'redis') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest <%_ if (databaseType === 'sql' && !reactive && authenticationType !== 'oauth2') { _%> import org.springframework.boot.test.mock.mockito.MockBean import org.springframework.data.auditing.AuditingHandler @@ -149,17 +132,7 @@ private const val DEFAULT_LANGKEY = "dummy" /** * Integration tests for [UserService]. */ -<%_ if (authenticationType === 'oauth2') { _%> -@SpringBootTest(classes = [<%= mainClass %>::class, TestSecurityConfiguration::class]) -<%_ } else { _%> -@SpringBootTest(classes = [<%= mainClass %>::class]) -<%_ } _%> -<%_ if (cacheProvider === 'redis') { _%> -@ExtendWith(RedisTestContainerExtension::class) -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -@ExtendWith(AbstractNeo4jIT::class) -<%_ } _%> +@IntegrationTest <%_ if (databaseType === 'sql' && !reactive) { _%> @Transactional <%_ } _%> @@ -453,33 +426,6 @@ class UserServiceIT <% if (databaseType === 'cassandra') { %>: AbstractCassandra persistentTokenRepository.save<% if (databaseType === 'sql' && !reactive) { %>AndFlush<% } %>(token) } <%_ } _%> - <%_ if (databaseType !== 'no') { _%> - - @Test - <%_ if (databaseType === 'sql' && !reactive) { _%> - @Transactional - <%_ } else if (databaseType === 'couchbase') { _%> - @WithAnonymousUser - <%_ } _%> - fun assertThatAnonymousUserIsNotGet() { - <%_ if (authenticationType === 'oauth2') { _%> - user.id = ANONYMOUS_USER - <%_ } _%> - user.login = ANONYMOUS_USER - if (!userRepository.findOneByLogin(ANONYMOUS_USER)<% if (reactive) { %>.blockOptional()<% } %>.isPresent) { - userRepository.<% if (databaseType === 'sql' && reactive && authenticationType === 'oauth2') { %>create<% } else { %>save<% } %><% if (databaseType === 'sql' && !reactive) { %>AndFlush<% } %>(user)<% if (reactive) { %>.block()<% } %> - }<% if (databaseType === 'sql' || databaseType === 'neo4j' || databaseType === 'mongodb' || databaseType === 'couchbase') { %> - val pageable = PageRequest.of(0, userRepository.count()<% if (reactive) { %>.block()!!<% } %>.toInt()) - val allManagedUsers = userService.getAllManagedUsers(pageable)<% if (reactive) { %> - .collectList().block()<% } %> - assertNotNull(allManagedUsers) - assertThat(allManagedUsers<% if (!reactive) { %>.content<% } %>.stream()<% } %><% if (databaseType === 'cassandra') { %> - val allManagedUsers = userService.getAllManagedUsers()<% if (reactive) { %>.collectList().block()<% } %> - assertThat(allManagedUsers.stream()<% } %> - .noneMatch { user -> ANONYMOUS_USER == user.login }) - .isTrue() - } - <%_ } _%> <%_ if (authenticationType === 'oauth2') { _%> @Test @@ -559,7 +505,7 @@ class UserServiceIT <% if (databaseType === 'cassandra') { %>: AbstractCassandra private fun createMockOAuth2AuthenticationToken(userDetails: Map): OAuth2AuthenticationToken { val authorities = listOf(SimpleGrantedAuthority(ANONYMOUS)) val usernamePasswordAuthenticationToken = - UsernamePasswordAuthenticationToken(ANONYMOUS_USER, ANONYMOUS_USER, authorities) + UsernamePasswordAuthenticationToken("anonymous", "anonymous", authorities) usernamePasswordAuthenticationToken.details = userDetails val user = DefaultOAuth2User(authorities, userDetails, "sub") diff --git a/generators/server/templates/src/test/kotlin/package/service/mapper/UserMapperTest.kt.ejs b/generators/server/templates/src/test/kotlin/package/service/mapper/UserMapperTest.kt.ejs index 9e80c444f..34f682ae4 100644 --- a/generators/server/templates/src/test/kotlin/package/service/mapper/UserMapperTest.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/service/mapper/UserMapperTest.kt.ejs @@ -19,6 +19,7 @@ package <%= packageName %>.service.mapper import <%= packageName %>.domain.<%= asEntity('User') %> +import <%= packageName %>.service.dto.<%= asDto('AdminUser') %> import <%= packageName %>.service.dto.<%= asDto('User') %> <%_ if (authenticationType !== 'oauth2') { _%> import org.apache.commons.lang3.RandomStringUtils @@ -26,17 +27,19 @@ import org.apache.commons.lang3.RandomStringUtils import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test +<%_ if (user.primaryKey.type === 'UUID') { _%> +import java.util.UUID +<%_ } _%> + import org.assertj.core.api.Assertions.assertThat import kotlin.test.assertNotNull import kotlin.test.assertNull private const val DEFAULT_LOGIN = "johndoe" -<%_ if (databaseType === 'sql' && authenticationType !== 'oauth2') { _%> -private const val DEFAULT_ID = 1L -<%_ } else if (databaseType === 'couchbase'){ _%> +<%_ if (databaseType === 'couchbase'){ _%> private const val DEFAULT_ID = <%= asEntity('User') %>.PREFIX + DEFAULT_LOGIN <%_ } else { _%> -private const val DEFAULT_ID = "id1" +private const val DEFAULT_ID = <%- getPrimaryKeyValue(user.primaryKey.type) %> <%_ } _%> /** @@ -47,7 +50,7 @@ class UserMapperTest { private lateinit var userMapper: UserMapper private lateinit var user: <%= asEntity('User') %> - private lateinit var userDto: <%= asDto('User') %> + private lateinit var userDto: <%= asDto('AdminUser') %> @BeforeEach fun init() { @@ -67,7 +70,7 @@ class UserMapperTest { langKey = "en" ) - userDto = <%= asDto('User') %>(user) + userDto = <%= asDto('AdminUser') %>(user) } @Test @@ -76,8 +79,7 @@ class UserMapperTest { val userDTOS = userMapper.usersToUserDTOs(users) - assertThat(userDTOS).isNotEmpty - assertThat(userDTOS).size().isEqualTo(1) + assertThat(userDTOS).isNotEmpty.size().isEqualTo(1) } @Test @@ -86,20 +88,18 @@ class UserMapperTest { val users = userMapper.userDTOsToUsers(usersDto) - assertThat(users).isNotEmpty - assertThat(users).size().isEqualTo(1) + assertThat(users).isNotEmpty.size().isEqualTo(1) } @Test fun userDTOsToUsersWithAuthoritiesStringShouldMapToUsersWithAuthoritiesDomain() { - userDto.authorities = setOf("ADMIN") + userDto.authorities = mutableSetOf("ADMIN") val usersDto = listOf(userDto) val users = userMapper.userDTOsToUsers(usersDto) - assertThat(users).isNotEmpty - assertThat(users).size().isEqualTo(1) + assertThat(users).isNotEmpty.size().isEqualTo(1) assertThat(users[0].authorities).isNotNull assertThat(users[0].authorities).isNotEmpty <%_ if (databaseType === 'sql' || databaseType === 'mongodb') { _%> @@ -112,21 +112,20 @@ class UserMapperTest { @Test fun userDTOsToUsersMapWithNullAuthoritiesStringShouldReturnUserWithEmptyAuthorities() { - userDto.authorities = null + userDto.authorities = mutableSetOf() val usersDto = listOf(userDto) val users = userMapper.userDTOsToUsers(usersDto) - assertThat(users).isNotEmpty - assertThat(users).size().isEqualTo(1) + assertThat(users).isNotEmpty.size().isEqualTo(1) assertThat(users[0].authorities).isNotNull assertThat(users[0].authorities).isEmpty() } @Test fun userDTOToUserMapWithAuthoritiesStringShouldReturnUserWithAuthorities() { - userDto.authorities = setOf("ADMIN") + userDto.authorities = mutableSetOf("ADMIN") val user = userMapper.userDTOToUser(userDto) @@ -143,7 +142,7 @@ class UserMapperTest { @Test fun userDTOToUserMapWithNullAuthoritiesStringShouldReturnUserWithEmptyAuthorities() { - userDto.authorities = null + userDto.authorities = mutableSetOf() val user = userMapper.userDTOToUser(userDto) diff --git a/generators/server/templates/src/test/kotlin/package/web/filter/ModifyServersOpenApiFilterTest.kt.ejs b/generators/server/templates/src/test/kotlin/package/web/filter/ModifyServersOpenApiFilterTest.kt.ejs new file mode 100644 index 000000000..a84de4bb6 --- /dev/null +++ b/generators/server/templates/src/test/kotlin/package/web/filter/ModifyServersOpenApiFilterTest.kt.ejs @@ -0,0 +1,151 @@ +package <%= packageName %>.web.filter + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Assertions.assertEquals +import org.mockito.Mockito.* + +import java.io.ByteArrayOutputStream +import java.io.IOException +import java.nio.charset.StandardCharsets +import java.util.zip.GZIPOutputStream +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import org.mockito.ArgumentCaptor +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.cloud.gateway.filter.GatewayFilterChain +import org.springframework.core.io.buffer.DataBuffer +import org.springframework.http.HttpHeaders +import org.springframework.mock.http.server.reactive.MockServerHttpRequest +import org.springframework.mock.web.server.MockServerWebExchange +import org.springframework.web.server.ServerWebExchange +import reactor.core.publisher.Flux +import reactor.core.publisher.Mono + +class ModifyServersOpenApiFilterTest { + + private val filterChain: GatewayFilterChain = mock(GatewayFilterChain::class.java) + private val captor: ArgumentCaptor = ArgumentCaptor.forClass(ServerWebExchange::class.java) + + @BeforeEach + fun setup() { + `when`(filterChain.filter(captor.capture())).thenReturn(Mono.empty()) + } + + @Test + fun shouldCallCreateModifyServersOpenApiInterceptorWhenGetOpenApiSpec() { + // dummy api url to filter + val sample_url = "/services/service-test/instance-test/v3/api-docs" + + // create request + val request = MockServerHttpRequest.get(sample_url).build() + val exchange = MockServerWebExchange.from(request) + + // apply the filter to the request + val modifyServersOpenApiFilter = spy(ModifyServersOpenApiFilter()) + modifyServersOpenApiFilter.filter(exchange, filterChain).subscribe() + + verify(modifyServersOpenApiFilter, times(1)) + .createModifyServersOpenApiInterceptor(sample_url, exchange.response, exchange.response.bufferFactory()) + } + + @Test + fun shouldNotCallCreateModifyServersOpenApiInterceptorWhenNotGetOpenApiSpec() { + // dummy api url to filter + val sample_url = "/services/service-test/instance-test/api" + + // create request + val request = MockServerHttpRequest.get(sample_url).build() + val exchange = MockServerWebExchange.from(request) + + // apply the filter to the request + val modifyServersOpenApiFilter = spy(ModifyServersOpenApiFilter()) + modifyServersOpenApiFilter.filter(exchange, filterChain).subscribe() + + verify(modifyServersOpenApiFilter, times(0)) + .createModifyServersOpenApiInterceptor(sample_url, exchange.response, exchange.response.bufferFactory()) + } + + @Test + fun shouldOrderToMinusOne() { + val modifyServersOpenApiFilter = ModifyServersOpenApiFilter() + assertEquals(modifyServersOpenApiFilter.order, -1) + } + + @Nested + class ModifyServersOpenApiInterceptorTest { + + private val log = LoggerFactory.getLogger(javaClass) + + private val path: String = "/services/service-test/instance-test/v3/api-docs" + private val request: MockServerHttpRequest = MockServerHttpRequest.get(path).build() + private val exchange: ServerWebExchange = MockServerWebExchange.from(request) + private val modifyServersOpenApiFilter: ModifyServersOpenApiFilter = ModifyServersOpenApiFilter() + + @Test + fun shouldRewriteBodyWhenBodyIsFluxAndResponseIsNotZipped() { + val interceptor = modifyServersOpenApiFilter.createModifyServersOpenApiInterceptor( + path, + exchange.response, + exchange.response.bufferFactory() + ) + + val bytes = "{}".encodeToByteArray() + val body = exchange.response.bufferFactory().wrap(bytes) + interceptor.writeWith(Flux.just(body)).subscribe() + assertThat( + interceptor + .getRewritedBody() + .contains("\"servers\":[{\"url\":\"/services/service-test/instance-test\",\"description\":\"added by global filter\"}]") + ).isTrue + } + + @Test + fun shouldRewriteBodyWhenBodyIsFluxAndResponseIsZipped() { + exchange.response.getHeaders().set(HttpHeaders.CONTENT_ENCODING, "gzip") + val interceptor = modifyServersOpenApiFilter.createModifyServersOpenApiInterceptor( + path, + exchange.response, + exchange.response.bufferFactory() + ) + + val bytes = zipContent() + val body = exchange.response.bufferFactory().wrap(bytes) + interceptor.writeWith(Flux.just(body)).subscribe() + assertThat( + interceptor + .getRewritedBody() + .contains("\"servers\":[{\"url\":\"/services/service-test/instance-test\",\"description\":\"added by global filter\"}]") + ).isTrue + } + + @Test + fun shouldNotRewriteBodyWhenBodyIsNotFlux() { + val interceptor = modifyServersOpenApiFilter.createModifyServersOpenApiInterceptor( + path, + exchange.response, + exchange.response.bufferFactory() + ) + + val bytes = "{}".encodeToByteArray() + val body = exchange.response.bufferFactory().wrap(bytes) + interceptor.writeWith(Mono.just(body)).subscribe() + assertThat(interceptor.getRewritedBody()).isEmpty() + } + + private fun zipContent(): ByteArray { + try { + val byteArrayOutputStream = ByteArrayOutputStream("{}".length) + val gzipOutputStream = GZIPOutputStream(byteArrayOutputStream) + gzipOutputStream.write("{}".encodeToByteArray()) + gzipOutputStream.flush() + gzipOutputStream.close() + return byteArrayOutputStream.toByteArray() + } catch (e: IOException) { + log.error("Error in test when zip content during modify servers from api-doc of {}: {}", path, e.message) + } + return "{}".encodeToByteArray() + } + } +} diff --git a/generators/server/templates/src/test/kotlin/package/web/rest/AccountResourceIT.kt.ejs b/generators/server/templates/src/test/kotlin/package/web/rest/AccountResourceIT.kt.ejs index 763754cff..c1f25a894 100644 --- a/generators/server/templates/src/test/kotlin/package/web/rest/AccountResourceIT.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/web/rest/AccountResourceIT.kt.ejs @@ -18,283 +18,10 @@ -%> package <%= packageName %>.web.rest -<%_ if (authenticationType === 'oauth2') { _%> <%_ if (databaseType === 'cassandra') { _%> import <%= packageName %>.AbstractCassandraTest <%_ } _%> -<%_ if (cacheProvider === 'redis') { _%> -import <%= packageName %>.RedisTestContainerExtension -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import <%= packageName %>.AbstractNeo4jIT -<%_ } _%> -import <%= packageName %>.config.TestSecurityConfiguration -import <%= packageName %>.<%= mainClass %> -import <%= packageName %>.security.ADMIN -import <%= packageName %>.security.USER -import <%= packageName %>.service.UserService - -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -<%_ if (databaseType === 'neo4j') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> -<%_ if (databaseType === 'neo4j' || cacheProvider === 'redis') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> - -import org.springframework.beans.factory.annotation.Autowired -<%_ if (!reactive) { _%> -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc -<%_ } else { _%> -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient -<%_ } _%> -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.http.MediaType -<%_ if (!reactive) { _%> -import org.springframework.security.core.GrantedAuthority -import org.springframework.security.core.authority.SimpleGrantedAuthority -import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken -import org.springframework.security.oauth2.core.user.DefaultOAuth2User -import org.springframework.security.oauth2.core.user.OAuth2User -import org.springframework.security.test.context.TestSecurityContextHolder -import org.springframework.test.web.servlet.MockMvc -import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder - <%_ if (databaseType === 'sql' && !reactive) { _%> -import org.springframework.transaction.annotation.Transactional - <%_ } _%> -<%_ } else { _%> -import org.springframework.security.oauth2.core.oidc.OidcIdToken -import org.springframework.test.web.reactive.server.WebTestClient -import org.springframework.test.web.reactive.server.WebTestClientConfigurer - <%_ if (searchEngine === 'elasticsearch' && reactive) { _%> -import reactor.core.publisher.Mono - <%_ } _%> - -import java.time.Instant -<%_ } _%> - -<%_ if (reactive && searchEngine === 'elasticsearch') { _%> -import org.mockito.Mockito.* -<%_ } _%> - -import org.springframework.security.test.context.support.WithMockUser -import <%= packageName %>.web.rest.TEST_USER_LOGIN -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get -import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content -import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath -import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status - -<%_ if (reactive) { _%> -import <%= packageName %>.web.rest.ID_TOKEN -import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.* -<%_ } _%> - -/** - * Integration tests for the [AccountResource] REST controller. - */ -<%_ if (!reactive) { _%> -@AutoConfigureMockMvc -<%_ } else { _%> -@AutoConfigureWebTestClient -<%_ } _%> -@WithMockUser(value = TEST_USER_LOGIN) -@SpringBootTest(classes = [<%= mainClass %>::class, TestSecurityConfiguration::class]) -<%_ if (cacheProvider === 'redis') { _%> -@ExtendWith(RedisTestContainerExtension::class) -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -@ExtendWith(AbstractNeo4jIT::class) -<%_ } _%> -class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassandraTest() <% } %> { - - <%_ if (!reactive) { _%> - @Autowired - private lateinit var restAccountMockMvc:MockMvc - <%_ } else { _%> - private lateinit var idToken: OidcIdToken - - @Autowired - private lateinit var webTestClient: WebTestClient - <%_ } _%> - - <%_ if (reactive) { _%> - @BeforeEach - fun setup() { - val claims: MutableMap = hashMapOf() - claims["groups"] = listOf(ADMIN) - claims["sub"] = "jane" - claims["email"] = "jane.doe@jhipster.com" - this.idToken = OidcIdToken(ID_TOKEN, Instant.now(), - Instant.now().plusSeconds(60), claims) - } - <%_ } _%> - -<%# Removed this test case in OAuth + reactive due to https://github.com/spring-projects/spring-security/issues/8142 %> -<%_ if (!reactive) { _%> - @Test<% if (databaseType === 'sql' && !reactive) { %> - @Transactional<% } %> - <% if (!reactive) { %>@Throws(Exception::class)<% } %> - fun testGetExistingAccount() { - <%_ if (!reactive) { _%> - val userDetails = mapOf( - "sub" to TEST_USER_LOGIN, - "email" to "john.doe@jhipster.com" - ) - val authorities = listOf(SimpleGrantedAuthority(ADMIN)) - val user = DefaultOAuth2User(authorities, userDetails, "sub") - val authentication = OAuth2AuthenticationToken(user, authorities, "oidc") - TestSecurityContextHolder.getContext().authentication = authentication - - restAccountMockMvc.perform( - get("/api/account") - .accept(MediaType.APPLICATION_JSON) - ) - .andExpect(status().isOk) - .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) - .andExpect(jsonPath("\$.login").value(TEST_USER_LOGIN)) - .andExpect(jsonPath("\$.email").value("john.doe@jhipster.com")) - .andExpect(jsonPath("\$.authorities").value(ADMIN)) - <%_ } else { _%> - webTestClient - .mutateWith(mockAuthentication(authenticationToken(idToken))) - .mutateWith(csrf()) - .get().uri("/api/account") - .accept(MediaType.APPLICATION_JSON) - .exchange() - .expectStatus().isOk - .expectHeader().contentType(MediaType.APPLICATION_JSON_VALUE) - .expectBody() - .jsonPath("$.login").isEqualTo("jane") - .jsonPath("$.email").isEqualTo("jane.doe@jhipster.com") - .jsonPath("$.authorities").isEqualTo(ADMIN) - <%_ } _%> - } -<%_ } _%> -} -<%_ } else if (skipUserManagement) { _%> -<%_ if (databaseType === 'cassandra') { _%> -import <%= packageName %>.AbstractCassandraTest -<%_ } _%> -<%_ if (reactive && searchEngine === 'elasticsearch') { _%> -import <%= packageName %>.repository.search.UserSearchRepository -<%_ } _%> -<%_ if (cacheProvider === 'redis') { _%> -import <%= packageName %>.RedisTestContainerExtension -<%_ } _%> -import <%= packageName %>.<%= mainClass %> -import <%= packageName %>.security.ADMIN -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -<%_ if (cacheProvider === 'redis') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> -import org.springframework.beans.factory.annotation.Autowired -<%_ if (!reactive) { _%> -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc -<%_ } else { _%> -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient -<%_ } _%> -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.http.MediaType -import org.springframework.security.test.context.support.WithMockUser -<%_ if (!reactive) { _%> -import org.springframework.test.web.servlet.MockMvc -import org.springframework.test.web.servlet.setup.MockMvcBuilders - -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get -import org.springframework.test.web.servlet.result.MockMvcResultMatchers.* -<%_ } else { _%> -import org.springframework.test.web.reactive.server.WebTestClient -<%_ } _%> -<%_ if (reactive && searchEngine === 'elasticsearch') { _%> -import reactor.core.publisher.Mono - -import org.mockito.Mockito.* -<%_ } _%> -import <%= packageName %>.web.rest.TEST_USER_LOGIN - -/** - * Integration tests for the {@link AccountResource} REST controller. - */ - <%_ if (!reactive) { _%> -@AutoConfigureMockMvc -<%_ } else { _%> -@AutoConfigureWebTestClient -<%_ } _%> -@WithMockUser(value = TEST_USER_LOGIN) -@SpringBootTest(classes = [<%= mainClass %>::class]) -<%_ if (cacheProvider === 'redis') { _%> -@ExtendWith(RedisTestContainerExtension::class) -<%_ } _%> -class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassandraTest() <% } %>{ - - @Autowired - <%_ if (!reactive) { _%> - private lateinit var restAccountMockMvc: MockMvc - <%_ } else { _%> - private lateinit var accountWebTestClient: WebTestClient - <%_ } _%> - - <%_ if (searchEngine === 'elasticsearch' && reactive) { _%> - - @Autowired - private lateinit var mockUserSearchRepository: UserSearchRepository - <%_ } _%> - - @Test - <% if (!reactive) { %>@Throws(Exception::class)<% } %> - @WithMockUser(username = TEST_USER_LOGIN, authorities = [ADMIN]) - fun testGetExistingAccount() { - <%_ if (!reactive) { _%> - restAccountMockMvc.perform( - get("/api/account") - .accept(MediaType.APPLICATION_JSON) - ) - .andExpect(status().isOk) - .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) - .andExpect(jsonPath("\$.login").value(TEST_USER_LOGIN)) - .andExpect(jsonPath("\$.authorities").value(ADMIN)) - <%_ } else { _%> - accountWebTestClient.get().uri("/api/account") - .accept(MediaType.APPLICATION_JSON) - .exchange() - .expectStatus().isOk - .expectHeader().contentType(MediaType.APPLICATION_JSON) - .expectBody() - .jsonPath("$.login").isEqualTo(TEST_USER_LOGIN) - .jsonPath("$.authorities").isEqualTo(ADMIN) - <%_ } _%> - } - - @Test - <% if (!reactive) { %>@Throws(Exception::class)<% } %> - fun testGetUnknownAccount() { - <%_ if (!reactive) { _%> - restAccountMockMvc.perform( - get("/api/account") - .accept(MediaType.APPLICATION_PROBLEM_JSON) - ) - .andExpect(status().isInternalServerError) - <%_ } else { _%> - accountWebTestClient.get().uri("/api/account") - .accept(MediaType.APPLICATION_JSON) - .exchange() - .expectStatus().is5xxServerError - <%_ } _%> - } -} -<%_ } else { _%> -<%_ if (databaseType === 'cassandra') { _%> -import <%= packageName %>.AbstractCassandraTest -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import <%= packageName %>.AbstractNeo4jIT -<%_ } _%> -import <%= packageName %>.<%= mainClass %> +import <%= packageName %>.IntegrationTest import <%= packageName %>.config.DEFAULT_LANGUAGE <%_ if (authenticationType === 'session' && !reactive) { _%> import <%= packageName %>.domain.PersistentToken @@ -316,14 +43,13 @@ import <%= packageName %>.security.USER import <%= packageName %>.service.UserService import <%= packageName %>.service.dto.PasswordChangeDTO import <%= packageName %>.service.dto.<%= asDto('User') %> +import <%= packageName %>.service.dto.<%= asDto('AdminUser') %> import <%= packageName %>.web.rest.vm.KeyAndPasswordVM import <%= packageName %>.web.rest.vm.ManagedUserVM import org.apache.commons.lang3.RandomStringUtils -<%_ if (databaseType === 'neo4j') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> - +<%_ if (reactive && testsNeedCsrf || databaseType === 'mongodb' || databaseType === 'neo4j') { _%> import org.junit.jupiter.api.BeforeEach +<%_ } _%> import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired <%_ if (!reactive) { _%> @@ -331,15 +57,11 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMock <%_ } else { _%> import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient <%_ } _%> -import org.springframework.boot.test.context.SpringBootTest <%_ if (reactive) { _%> import org.springframework.test.web.reactive.server.expectBody import org.springframework.http.HttpStatus <%_ } _%> import org.springframework.http.MediaType -<%_ if (!reactive) { _%> -import org.springframework.http.converter.HttpMessageConverter -<%_ } _%> import org.springframework.security.crypto.password.PasswordEncoder import org.springframework.security.test.context.support.WithMockUser <%_ if (reactive) { _%> @@ -372,6 +94,7 @@ import org.assertj.core.api.Assertions.assertThat import org.mockito.Mockito.* <%_ } _%> <%_ if (authenticationType === 'session' && !reactive) { _%> +import org.hamcrest.Matchers.containsString import org.hamcrest.Matchers.hasItem <%_ } _%> import <%= packageName %>.web.rest.TEST_USER_LOGIN @@ -408,10 +131,7 @@ import <%= packageName %>.config.SYSTEM_ACCOUNT @AutoConfigureWebTestClient <%_ } _%> @WithMockUser(value = TEST_USER_LOGIN) -@SpringBootTest(classes = [<%= mainClass %>::class]) -<%_ if (databaseType === 'neo4j') { _%> -@ExtendWith(AbstractNeo4jIT::class) -<%_ } _%> +@IntegrationTest class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassandraTest() <% } %>{ @Autowired @@ -519,7 +239,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa val authorities = mutableSetOf(ADMIN) - val user = <%= asDto('User') %>( + val user = <%= asDto('AdminUser') %>( login = TEST_USER_LOGIN, firstName = "john", lastName = "doe", @@ -603,9 +323,9 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa imageUrl = "http://placehold.it/50x50" <%_ } _%> langKey = DEFAULT_LANGUAGE - authorities = setOf(USER) + authorities = mutableSetOf(USER) } - assertThat(userRepository.findOneByLogin("test-register-valid")<% if (reactive) { %>.blockOptional()<% } %>.isPresent).isFalse() + assertThat(userRepository.findOneByLogin("test-register-valid")<% if (reactive) { %>.blockOptional()<% } %>).isEmpty <%_ if (!reactive) { _%> restAccountMockMvc.perform( @@ -623,7 +343,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa .expectStatus().isCreated <%_ } _%> - assertThat(userRepository.findOneByLogin("test-register-valid")<% if (reactive) { %>.blockOptional()<% } %>.isPresent).isTrue() + assertThat(userRepository.findOneByLogin("test-register-valid")<% if (reactive) { %>.blockOptional()<% } %>).isPresent } @Test<% if (databaseType === 'sql' && !reactive) { %> @@ -641,7 +361,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa imageUrl = "http://placehold.it/50x50" <%_ } _%> langKey = DEFAULT_LANGUAGE - authorities = setOf(USER) + authorities = mutableSetOf(USER) } <%_ if (!reactive) { _%> @@ -661,7 +381,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa <%_ } _%> val user = userRepository.findOneByEmailIgnoreCase("funky@example.com")<% if (reactive) { %>.blockOptional()<% } %> - assertThat(user.isPresent).isFalse() + assertThat(user).isEmpty } @Test<% if (databaseType === 'sql' && !reactive) { %> @@ -679,7 +399,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa imageUrl = "http://placehold.it/50x50" <%_ } _%> langKey = DEFAULT_LANGUAGE - authorities = setOf(USER) + authorities = mutableSetOf(USER) } <%_ if (!reactive) { _%> @@ -699,7 +419,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa <%_ } _%> val user = userRepository.findOneByLogin("bob")<% if (reactive) { %>.blockOptional()<% } %> - assertThat(user.isPresent).isFalse() + assertThat(user).isEmpty } @Test<% if (databaseType === 'sql' && !reactive) { %> @@ -717,7 +437,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa imageUrl = "http://placehold.it/50x50" <%_ } _%> langKey = DEFAULT_LANGUAGE - authorities = setOf(USER) + authorities = mutableSetOf(USER) } <%_ if (!reactive) { _%> @@ -737,7 +457,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa <%_ } _%> val user = userRepository.findOneByLogin("bob")<% if (reactive) { %>.blockOptional()<% } %> - assertThat(user.isPresent).isFalse() + assertThat(user).isEmpty } @Test<% if (databaseType === 'sql' && !reactive) { %> @@ -755,7 +475,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa imageUrl = "http://placehold.it/50x50" <%_ } _%> langKey = DEFAULT_LANGUAGE - authorities = setOf(USER) + authorities = mutableSetOf(USER) } <%_ if (!reactive) { _%> @@ -775,7 +495,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa <%_ } _%> val user = userRepository.findOneByLogin("bob")<% if (reactive) { %>.blockOptional()<% } %> - assertThat(user.isPresent).isFalse() + assertThat(user).isEmpty } @Test<% if (databaseType === 'sql' && !reactive) { %> @@ -799,7 +519,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa imageUrl = "http://placehold.it/50x50" <%_ } _%> langKey = DEFAULT_LANGUAGE - authorities = setOf(USER) + authorities = mutableSetOf(USER) } // Duplicate login, different email @@ -857,7 +577,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa <%_ } _%> val testUser = userRepository.findOneByEmailIgnoreCase("alice2@example.com")<% if (reactive) { %>.blockOptional()<% } %> - assertThat(testUser.isPresent).isTrue() + assertThat(testUser).isPresent testUser.get().activated = true userRepository.save(testUser.get())<% if (reactive) { %>.block()<% } %> @@ -900,7 +620,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa imageUrl = "http://placehold.it/50x50" <%_ } _%> langKey = DEFAULT_LANGUAGE - authorities = setOf(USER) + authorities = mutableSetOf(USER) } // Register first user @@ -921,7 +641,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa <%_ } _%> val testUser1 = userRepository.findOneByLogin("test-register-duplicate-email")<% if (reactive) { %>.blockOptional()<% } %> - assertThat(testUser1.isPresent).isTrue() + assertThat(testUser1).isPresent // Duplicate email, different login val secondUser = ManagedUserVM().apply { @@ -955,10 +675,10 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa <%_ } _%> val testUser2 = userRepository.findOneByLogin("test-register-duplicate-email")<% if (reactive) { %>.blockOptional()<% } %> - assertThat(testUser2.isPresent).isFalse() + assertThat(testUser2).isEmpty val testUser3 = userRepository.findOneByLogin("test-register-duplicate-email-2")<% if (reactive) { %>.blockOptional()<% } %> - assertThat(testUser3.isPresent).isTrue() + assertThat(testUser3).isPresent // Duplicate email - with uppercase email address val userWithUpperCaseEmail = ManagedUserVM().apply { @@ -993,11 +713,11 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa <%_ } _%> val testUser4 = userRepository.findOneByLogin("test-register-duplicate-email-3")<% if (reactive) { %>.blockOptional()<% } %> - assertThat(testUser4.isPresent).isTrue() + assertThat(testUser4).isPresent assertThat(testUser4.get().email).isEqualTo("test-register-duplicate-email@example.com") testUser4.get().activated = true - userService.updateUser((<%= asDto('User') %>(testUser4.get())))<% if (reactive) { %>.block()<% } %> + userService.updateUser((<%= asDto('AdminUser') %>(testUser4.get())))<% if (reactive) { %>.block()<% } %> // Register 4th (already activated) user <%_ if (!reactive) { _%> @@ -1032,7 +752,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa imageUrl = "http://placehold.it/50x50" <%_ } _%> langKey = DEFAULT_LANGUAGE - authorities = setOf(ADMIN) + authorities = mutableSetOf(ADMIN) } <%_ if (searchEngine === 'elasticsearch' && reactive) { _%> @@ -1059,7 +779,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa <%_ } _%> val userDup = userRepository.findOne<% if (databaseType === 'sql') { %>WithAuthorities<% } %>ByLogin("badguy")<% if (reactive) { %>.blockOptional()<% } %> - assertThat(userDup.isPresent).isTrue() + assertThat(userDup).isPresent assertThat(userDup.get().authorities).hasSize(1) .containsExactly(<% if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j') { %>authorityRepository.findById(USER).<% if (reactive) { %>block<% } else { %>get<% } %>()<% } %><% if (databaseType === 'cassandra' || databaseType === 'couchbase') { %>USER<% } %>) } @@ -1147,7 +867,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa <%_ } _%> - val userDTO = <%= asDto('User') %>( + val userDTO = <%= asDto('AdminUser') %>( login = "not-used", firstName = "firstname", lastName = "lastname", @@ -1157,7 +877,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa imageUrl = "http://placehold.it/50x50", <%_ } _%> langKey = DEFAULT_LANGUAGE, - authorities = setOf(ADMIN) + authorities = mutableSetOf(ADMIN) ) <%_ if (!reactive) { _%> @@ -1183,7 +903,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa assertThat(updatedUser?.langKey).isEqualTo(userDTO.langKey) assertThat(updatedUser?.password).isEqualTo(user.password)<% if (['sql', 'mongodb', 'couchbase', 'neo4j'].includes(databaseType)) { %> assertThat(updatedUser?.imageUrl).isEqualTo(userDTO.imageUrl)<% } %> - assertThat(updatedUser?.activated).isEqualTo(true) + assertThat(updatedUser?.activated).isTrue() assertThat(updatedUser?.authorities).isEmpty() } @@ -1209,7 +929,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa userRepository.save<% if (databaseType === 'sql' && !reactive) { %>AndFlush<% } %>(user)<% if (reactive) { %>.block()<% } %> - val userDTO = <%= asDto('User') %>( + val userDTO = <%= asDto('AdminUser') %>( login = "not-used", firstName = "firstname", lastName = "lastname", @@ -1219,7 +939,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa imageUrl = "http://placehold.it/50x50", <%_ } _%> langKey = DEFAULT_LANGUAGE, - authorities = setOf(ADMIN) + authorities = mutableSetOf(ADMIN) ) <%_ if (!reactive) { _%> @@ -1278,7 +998,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa userRepository.save<% if (databaseType === 'sql' && !reactive) { %>AndFlush<% } %>(anotherUser)<% if (reactive) { %>.block()<% } %> - val userDTO = <%= asDto('User') %>( + val userDTO = <%= asDto('AdminUser') %>( login = "not-used", firstName = "firstname", lastName = "lastname", @@ -1288,7 +1008,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa imageUrl = "http://placehold.it/50x50", <%_ } _%> langKey = DEFAULT_LANGUAGE, - authorities = setOf(ADMIN) + authorities = mutableSetOf(ADMIN) ) <%_ if (!reactive) { _%> @@ -1337,7 +1057,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa <%_ } _%> - val userDTO = <%= asDto('User') %>( + val userDTO = <%= asDto('AdminUser') %>( login = "not-used", firstName = "firstname", lastName = "lastname", @@ -1347,7 +1067,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa imageUrl = "http://placehold.it/50x50", <%_ } _%> langKey = DEFAULT_LANGUAGE, - authorities = setOf(ADMIN) + authorities = mutableSetOf(ADMIN) ) // Mark here.... <%_ if (!reactive) { _%> @@ -1607,13 +1327,20 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa userRepository.save<% if (databaseType === 'sql' && !reactive) { %>AndFlush<% } %>(user)<% if (reactive) { %>.block()<% } %> val token = PersistentToken( - series = "current-sessions",<% if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j') { %> - user = user,<% } else { %><% if (databaseType === 'cassandra') { %> - userId = user.id,<% } else { %> - login = user.login,<% } %><% } %> - tokenValue = "current-session-data",<% if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'couchbase' || databaseType === 'neo4j') { %> - tokenDate = LocalDate.of(2017, 3, 23),<% } else { %> - tokenDate = Date(1490714757123L),<% } %> + series = "current-sessions", + <%_ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j') { _%> + user = user, + <%_ } else if (databaseType === 'cassandra') { _%> + userId = user.id, + <%_ } else if (databaseType === 'couchbase') { _%> + login = login, + <%_ } _%> + tokenValue = "current-session-data", + <%_ if (databaseType === 'cassandra') { _%> + tokenDate = Instant.parse("2017-03-28T15:25:57.123Z"), + <%_ } else { _%> + tokenDate = LocalDate.of(2017, 3, 23), + <% } %> ipAddress = "127.0.0.1", userAgent = "Test agent" ) @@ -1625,7 +1352,7 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa .andExpect(jsonPath("\$.[*].series").value(hasItem(token.series))) .andExpect(jsonPath("\$.[*].ipAddress").value(hasItem(token.ipAddress))) .andExpect(jsonPath("\$.[*].userAgent").value(hasItem(token.userAgent))) - .andExpect(jsonPath("\$.[*].tokenDate").value(hasItem(<% if (databaseType === 'cassandra') { %>"2017-03-28T15:25:57.123+0000"<% } else { %>token.tokenDate.toString()<% } %>))) + .andExpect(jsonPath("$.[*].tokenDate").value(hasItem(containsString(<% if (databaseType === 'cassandra') { %>"2017-03-28T15:25:57.123Z"<% } else { %>token.tokenDate.toString()<% } %>)))) } @Test<% if (databaseType === 'sql' && !reactive) { %> @@ -1648,13 +1375,20 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa userRepository.save<% if (databaseType === 'sql' && !reactive) { %>AndFlush<% } %>(user)<% if (reactive) { %>.block()<% } %> val token = PersistentToken( - series = "invalidate-session",<% if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j') { %> - user = user,<% } else { %><% if (databaseType === 'cassandra') { %> - userId = user.id,<% } else { %> - login = user.login,<% } %><% } %> - tokenValue = "invalidate-data",<% if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'couchbase' || databaseType === 'neo4j') { %> - tokenDate = LocalDate.of(2017, 3, 23),<% } else { %> - tokenDate = Date(1490714757123L),<% } %> + series = "invalidate-session", + <%_ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j') { _%> + user = user, + <%_ } else if (databaseType === 'cassandra') { _%> + userId = user.id, + <%_ } else { _%> + login = user.login, + <%_ } _%> + tokenValue = "invalidate-data", + <%_ if (['sql', 'mongodb', 'couchbase', 'neo4j'].includes(databaseType)) { _%> + tokenDate = LocalDate.of(2017, 3, 23), + <%_ } else if (databaseType === 'cassandra') { _%> + tokenDate = Instant.now(), + <%_ } _%> ipAddress = "127.0.0.1", userAgent = "Test agent" ) @@ -1872,4 +1606,3 @@ class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassa <%_ } _%> } } -<%_ } _%> diff --git a/generators/server/templates/src/test/kotlin/package/web/rest/AccountResourceIT_oauth2.kt.ejs b/generators/server/templates/src/test/kotlin/package/web/rest/AccountResourceIT_oauth2.kt.ejs new file mode 100644 index 000000000..5581dba32 --- /dev/null +++ b/generators/server/templates/src/test/kotlin/package/web/rest/AccountResourceIT_oauth2.kt.ejs @@ -0,0 +1,167 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + +This file is part of the JHipster project, see https://jhipster.github.io/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %>.web.rest + +<%_ if (databaseType === 'cassandra') { _%> +import <%= packageName %>.AbstractCassandraTest +<%_ } _%> +import <%= packageName %>.IntegrationTest +import <%= packageName %>.config.TestSecurityConfiguration +import <%= packageName %>.security.AuthoritiesConstants +import <%= packageName %>.service.UserService + +<%_ if (reactive) { _%> +import org.junit.jupiter.api.BeforeEach +<%_ } _%> +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +<%_ if (!reactive) { _%> +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc +<%_ } else { _%> +import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient +<%_ } _%> +import org.springframework.http.MediaType +<%_ if (!reactive) { _%> +import org.springframework.security.core.GrantedAuthority +import org.springframework.security.core.authority.SimpleGrantedAuthority +import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken +import org.springframework.security.oauth2.core.user.DefaultOAuth2User +import org.springframework.security.oauth2.core.user.OAuth2User +import org.springframework.security.test.context.TestSecurityContextHolder +import org.springframework.security.test.context.support.WithMockUser +import org.springframework.test.web.servlet.MockMvc + <%_ if (databaseType === 'sql' && !reactive) { _%> +import org.springframework.transaction.annotation.Transactional + <%_ } _%> + +import java.util.Collection +<%_ } else { _%> +import org.springframework.security.oauth2.core.oidc.OidcIdToken +import org.springframework.test.web.reactive.server.WebTestClient + <%_ if (searchEngine === 'elasticsearch' && reactive) { _%> +import reactor.core.publisher.Mono + <%_ } _%> + +import java.time.Instant +<%_ } _%> +import java.util.Collections +import java.util.HashMap +import java.util.Map + +<%_ if (reactive && searchEngine === 'elasticsearch') { _%> +import org.mockito.Mockito.* +<%_ } _%> +import <%= packageName %>.security.ADMIN +import <%= packageName %>.web.rest.TEST_USER_LOGIN +import org.springframework.security.test.context.support.WithMockUser +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.* +<%_ if (reactive) { _%> +import <%= packageName %>.web.rest.ID_TOKEN +import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.* +<%_ } _%> + +/** + * Integration tests for the {@link AccountResource} REST controller. + */ +<%_ if (!reactive) { _%> +@AutoConfigureMockMvc +<%_ } else { _%> +@AutoConfigureWebTestClient +<%_ } _%> +@WithMockUser(value = TEST_USER_LOGIN) +@IntegrationTest +class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassandraTest() <% } %>{ + + <%_ if (!reactive) { _%> + @Autowired + private lateinit var restAccountMockMvc: MockMvc + <%_ } else { _%> + private lateinit var idToken: OidcIdToken + + @Autowired + private lateinit var webTestClient: WebTestClient + <%_ } _%> + + <%_ if (reactive) { _%> + @BeforeEach + fun setup() { + val claims: MutableMap = hashMapOf() + claims["groups"] = listOf(ADMIN) + claims["sub"] = "jane" + claims["email"] = "jane.doe@jhipster.com" + this.idToken = OidcIdToken(ID_TOKEN, Instant.now(), + Instant.now().plusSeconds(60), claims) + } + + <%_ } _%> + @Test<% if (databaseType === 'sql' && !reactive) { %> + @Transactional<% } %> + <% if (!reactive) { %>@Throws(Exception::class)<% } %> + fun testGetExistingAccount() { + <%_ if (!reactive) { _%> + val userDetails = mapOf( + "sub" to TEST_USER_LOGIN, + "email" to "john.doe@jhipster.com" + ) + val authorities = listOf(SimpleGrantedAuthority(ADMIN)) + val user = DefaultOAuth2User(authorities, userDetails, "sub") + val authentication = OAuth2AuthenticationToken(user, authorities, "oidc") + TestSecurityContextHolder.getContext().authentication = authentication + + restAccountMockMvc.perform( + get("/api/account") + .accept(MediaType.APPLICATION_JSON) + ) + .andExpect(status().isOk) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("\$.login").value(TEST_USER_LOGIN)) + .andExpect(jsonPath("\$.email").value("john.doe@jhipster.com")) + .andExpect(jsonPath("\$.authorities").value(ADMIN)) + <%_ } else { _%> + webTestClient + .mutateWith(mockAuthentication(authenticationToken(idToken))) + .mutateWith(csrf()) + .get().uri("/api/account") + .accept(MediaType.APPLICATION_JSON) + .exchange() + .expectStatus().isOk + .expectHeader().contentType(MediaType.APPLICATION_JSON_VALUE) + .expectBody() + .jsonPath("$.login").isEqualTo("jane") + .jsonPath("$.email").isEqualTo("jane.doe@jhipster.com") + .jsonPath("$.authorities").isEqualTo(ADMIN) + <%_ } _%> + } + + @Test + <% if (!reactive) { %>@Throws(Exception::class)<% } %> + fun testGetUnknownAccount() { + <%_ if (!reactive) { _%> + restAccountMockMvc.perform(get("/api/account") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isInternalServerError()) + <%_ } else { _%> + webTestClient.get().uri("/api/account") + .accept(MediaType.APPLICATION_JSON) + .exchange() + .expectStatus().is5xxServerError() + <%_ } _%> + } +} diff --git a/generators/server/templates/src/test/kotlin/package/web/rest/AccountResourceIT_skipUserManagement.kt.ejs b/generators/server/templates/src/test/kotlin/package/web/rest/AccountResourceIT_skipUserManagement.kt.ejs new file mode 100644 index 000000000..f55f48fa7 --- /dev/null +++ b/generators/server/templates/src/test/kotlin/package/web/rest/AccountResourceIT_skipUserManagement.kt.ejs @@ -0,0 +1,104 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + +This file is part of the JHipster project, see https://jhipster.github.io/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %>.web.rest + +<%_ if (databaseType === 'cassandra') { _%> +import <%= packageName %>.AbstractCassandraTest +<%_ } _%> +import <%= packageName %>.IntegrationTest +<%_ if (reactive && searchEngine === 'elasticsearch') { _%> +import <%= packageName %>.repository.search.UserSearchRepository +<%_ } _%> +import <%= packageName %>.security.AuthoritiesConstants +import org.junit.jupiter.api.Test +<%_ if (reactiveSqlTestContainers) { _%> +import <%= packageName %>.ReactiveSqlTestContainerExtension +<%_ } _%> +import org.springframework.beans.factory.annotation.Autowired +<%_ if (!reactive) { _%> +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc +<%_ } else { _%> +import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient +<%_ } _%> +import org.springframework.http.MediaType +import org.springframework.security.test.context.support.WithMockUser +<%_ if (!reactive) { _%> +import org.springframework.test.web.servlet.MockMvc + +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.* +<%_ } else { _%> +import org.springframework.test.web.reactive.server.WebTestClient +<%_ } _%> +<%_ if (reactive && searchEngine === 'elasticsearch') { _%> +import reactor.core.publisher.Mono + +import org.mockito.Mockito.* +<%_ } _%> +import <%= packageName %>.web.rest.TEST_USER_LOGIN + +/** + * Integration tests for the {@link AccountResource} REST controller. + */ +<%_ if (!reactive) { _%> +@AutoConfigureMockMvc +<%_ } else { _%> +@AutoConfigureWebTestClient +<%_ } _%> +@WithMockUser(value = TEST_USER_LOGIN) +@IntegrationTest +class AccountResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassandraTest() <% } %>{ + + @Autowired + <%_ if (!reactive) { _%> + private lateinit var restAccountMockMvc: MockMvc + <%_ } else { _%> + private lateinit var accountWebTestClient: WebTestClient + <%_ } _%> + <%_ if (searchEngine === 'elasticsearch' && reactive) { _%> + + @Autowired + private lateinit var mockUserSearchRepository: UserSearchRepository + <%_ } _%> + + @Test + <% if (!reactive) { %>@Throws(Exception::class)<% } %> + @WithMockUser(username = TEST_USER_LOGIN, authorities = [ADMIN]) + fun testGetExistingAccount() { + <%_ if (!reactive) { _%> + restAccountMockMvc.perform( + get("/api/account") + .accept(MediaType.APPLICATION_JSON) + ) + .andExpect(status().isOk) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("\$.login").value(TEST_USER_LOGIN)) + .andExpect(jsonPath("\$.authorities").value(ADMIN)) + <%_ } else { _%> + accountWebTestClient.get().uri("/api/account") + .accept(MediaType.APPLICATION_JSON) + .exchange() + .expectStatus().isOk + .expectHeader().contentType(MediaType.APPLICATION_JSON) + .expectBody() + .jsonPath("$.login").isEqualTo(TEST_USER_LOGIN) + .jsonPath("$.authorities").isEqualTo(ADMIN) + <%_ } _%> + } +} diff --git a/generators/server/templates/src/test/kotlin/package/web/rest/AuditResourceIT.kt.ejs b/generators/server/templates/src/test/kotlin/package/web/rest/AuditResourceIT.kt.ejs deleted file mode 100644 index d0938f54c..000000000 --- a/generators/server/templates/src/test/kotlin/package/web/rest/AuditResourceIT.kt.ejs +++ /dev/null @@ -1,250 +0,0 @@ -<%# - Copyright 2013-2020 the original author or authors from the JHipster project. - - This file is part of the JHipster project, see https://www.jhipster.tech/ - for more information. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. --%> -package <%= packageName %>.web.rest - -import <%= packageName %>.<%= mainClass %> -<%_ if (cacheProvider === 'redis') { _%> -import <%= packageName %>.RedisTestContainerExtension -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import <%= packageName %>.AbstractNeo4jIT -<%_ } _%> -<%_ if (authenticationType === 'oauth2') { _%> -import <%= packageName %>.config.TestSecurityConfiguration -<%_ } _%> -import <%= packageName %>.domain.PersistentAuditEvent -import <%= packageName %>.repository.PersistenceAuditEventRepository -import <%= packageName %>.security.ADMIN - -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -<%_ if (cacheProvider === 'redis') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> -import org.springframework.beans.factory.annotation.Autowired -<%_ if (!reactive) { _%> -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc -<%_ } else { _%> -import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient -<%_ } _%> -import org.springframework.boot.test.context.SpringBootTest -<%_ if (!reactive) { _%> -import org.springframework.data.web.PageableHandlerMethodArgumentResolver -<%_ } _%> -import org.springframework.http.MediaType -import org.springframework.security.test.context.support.WithMockUser -<%_ if (!reactive) { _%> -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter -import org.springframework.test.context.junit4.SpringRunner -import org.springframework.test.web.servlet.MockMvc -import org.springframework.test.web.servlet.setup.MockMvcBuilders -<%_ } _%> -<%_ if (reactive) { _%> -import org.springframework.test.web.reactive.server.WebTestClient -<%_ } _%> -<%_ if (databaseType === 'sql' && !reactive) { _%> -import org.springframework.transaction.annotation.Transactional -<%_ } _%> - -import java.time.Instant - -import org.assertj.core.api.AssertionsForClassTypes.assertThat -import org.hamcrest.Matchers.hasItem -<%_ if (!reactive) { _%> -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get -import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content -import org.springframework.test.web.servlet.result.MockMvcResultMatchers.header -import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath -import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status -<%_ } _%> - -private const val SAMPLE_PRINCIPAL = "SAMPLE_PRINCIPAL" -private const val SAMPLE_TYPE = "SAMPLE_TYPE" -private val SAMPLE_TIMESTAMP = Instant.parse("2015-08-04T10:11:30Z") -private const val SECONDS_PER_DAY = (60 * 60 * 24).toLong() - -/** - * Integration tests for the [AuditResource] REST controller. - */ -<%_ if (!reactive) { _%> -@AutoConfigureMockMvc -<%_ } else { _%> -@AutoConfigureWebTestClient -<%_ } _%> -@WithMockUser(authorities = [ADMIN]) -<%_ if (authenticationType === 'oauth2') { _%> -@SpringBootTest(classes = [<%= mainClass %>::class, TestSecurityConfiguration::class]) -<%_ } else { _%> -@SpringBootTest(classes = [<%= mainClass %>::class]) -<%_ } _%> -<%_ if (databaseType === 'sql' && !reactive) { _%> -@Transactional -<%_ } _%> -<%_ if (cacheProvider === 'redis') { _%> -@ExtendWith(RedisTestContainerExtension::class) -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -@ExtendWith(AbstractNeo4jIT::class) -<%_ } _%> -class AuditResourceIT { - - @Autowired - private lateinit var auditEventRepository: PersistenceAuditEventRepository - - private lateinit var auditEvent: PersistentAuditEvent - - @Autowired - <%_ if (!reactive) { _%> - private lateinit var restAuditMockMvc: MockMvc - <%_ } else { _%> - private lateinit var webTestClient: WebTestClient - <%_ } _%> - - @BeforeEach - fun initTest() { - auditEventRepository.deleteAll()<% if (reactive) { %>.block()<% } %> - auditEvent = PersistentAuditEvent( - auditEventType = SAMPLE_TYPE, - principal = SAMPLE_PRINCIPAL, - auditEventDate = SAMPLE_TIMESTAMP - ) - } - - @Test - <% if (!reactive) { %>@Throws(Exception::class)<% } %> - fun getAllAudits() { - // Initialize the database - auditEventRepository.save(auditEvent)<% if (reactive) { %>.block()<% } %> - - // Get all the audits - <%_ if (!reactive) { _%> - restAuditMockMvc.perform(get("/management/audits")) - .andExpect(status().isOk) - .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) - .andExpect(jsonPath("\$.[*].principal").value(hasItem(SAMPLE_PRINCIPAL))) - <%_ } else { _%> - webTestClient.get().uri("/management/audits") - .exchange() - .expectStatus().isOk() - .expectHeader().contentType(MediaType.APPLICATION_JSON) - .expectBody().jsonPath("$.[*].principal").value(hasItem(SAMPLE_PRINCIPAL)) - <%_ } _%> - } - - @Test - <% if (!reactive) { %>@Throws(Exception::class)<% } %> - fun getAudit() { - // Initialize the database - auditEventRepository.save(auditEvent)<% if (reactive) { %>.block()<% } %> - - // Get the audit - <%_ if (!reactive) { _%> - restAuditMockMvc.perform(get("/management/audits/{id}", auditEvent.id)) - .andExpect(status().isOk) - .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) - .andExpect(jsonPath("\$.principal").value(SAMPLE_PRINCIPAL)) - <%_ } else { _%> - webTestClient.get().uri("/management/audits/{id}", auditEvent.id) - .exchange() - .expectStatus().isOk() - .expectHeader().contentType(MediaType.APPLICATION_JSON) - .expectBody().jsonPath("$.principal").isEqualTo(SAMPLE_PRINCIPAL) - <%_ } _%> - } - - @Test - <% if (!reactive) { %>@Throws(Exception::class)<% } %> - fun getAuditsByDate() { - // Initialize the database - auditEventRepository.save(auditEvent)<% if (reactive) { %>.block()<% } %> - - // Generate dates for selecting audits by date, making sure the period will contain the audit - val fromDate = SAMPLE_TIMESTAMP.minusSeconds(SECONDS_PER_DAY).toString().substring(0, 10) - val toDate = SAMPLE_TIMESTAMP.plusSeconds(SECONDS_PER_DAY).toString().substring(0, 10) - - // Get the audit - <%_ if (!reactive) { _%> - restAuditMockMvc.perform(get("/management/audits?fromDate=$fromDate&toDate=$toDate")) - .andExpect(status().isOk) - .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) - .andExpect(jsonPath("\$.[*].principal").value(hasItem(SAMPLE_PRINCIPAL))) - <%_ } else { _%> - webTestClient.get().uri("/management/audits?fromDate="+fromDate+"&toDate="+toDate) - .exchange() - .expectStatus().isOk() - .expectHeader().contentType(MediaType.APPLICATION_JSON) - .expectBody().jsonPath("$.[*].principal").value(hasItem(SAMPLE_PRINCIPAL)) - <%_ } _%> - } - - @Test - <% if (!reactive) { %>@Throws(Exception::class)<% } %> - fun getNonExistingAuditsByDate() { - // Initialize the database - auditEventRepository.save(auditEvent)<% if (reactive) { %>.block()<% } %> - - // Generate dates for selecting audits by date, making sure the period will not contain the sample audit - val fromDate = SAMPLE_TIMESTAMP.minusSeconds(2 * SECONDS_PER_DAY).toString().substring(0, 10) - val toDate = SAMPLE_TIMESTAMP.minusSeconds(SECONDS_PER_DAY).toString().substring(0, 10) - - // Query audits but expect no results - <%_ if (!reactive) { _%> - restAuditMockMvc.perform(get("/management/audits?fromDate=$fromDate&toDate=$toDate")) - .andExpect(status().isOk) - .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) - .andExpect(header().string("X-Total-Count", "0")) - <%_ } else { _%> - webTestClient.get().uri("/management/audits?fromDate="+fromDate+"&toDate="+toDate) - .exchange() - .expectStatus().isOk() - .expectHeader().contentType(MediaType.APPLICATION_JSON) - .expectHeader().valueEquals("X-Total-Count", "0") - <%_ } _%> - } - - @Test - <% if (!reactive) { %>@Throws(Exception::class)<% } %> - fun getNonExistingAudit() { - // Get the audit - <%_ if (!reactive) { _%> - restAuditMockMvc.perform(get("/management/audits/{id}", java.lang.Long.MAX_VALUE)) - .andExpect(status().isNotFound) - <%_ } else { _%> - webTestClient.get().uri("/management/audits/{id}", Long.MAX_VALUE) - .exchange() - .expectStatus().isNotFound() - <%_ } _%> - } - - @Test - <% if (!reactive) { %>@Throws(Exception::class)<% } %> - fun testPersistentAuditEventEquals() { - equalsVerifier(PersistentAuditEvent::class) - val auditEvent1 = PersistentAuditEvent(id = <% if (databaseType === 'sql') { %>1L<% } else { %>"id1"<% } %>) - val auditEvent2 = PersistentAuditEvent(id = auditEvent1.id) - assertThat(auditEvent1).isEqualTo(auditEvent2) - auditEvent2.id = <% if (databaseType === 'sql') { %>2L<% } else { %>"id2"<% } %> - assertThat(auditEvent1).isNotEqualTo(auditEvent2) - auditEvent1.id = null - assertThat(auditEvent1).isNotEqualTo(auditEvent2) - } -} diff --git a/generators/server/templates/src/test/kotlin/package/web/rest/KafkaResourceIT.kt.ejs b/generators/server/templates/src/test/kotlin/package/web/rest/KafkaResourceIT.kt.ejs index a682c50b1..260d4f4c9 100644 --- a/generators/server/templates/src/test/kotlin/package/web/rest/KafkaResourceIT.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/web/rest/KafkaResourceIT.kt.ejs @@ -108,12 +108,12 @@ class <%= upperFirstCamelCase(baseName) %>KafkaResourceIT { fun producesMessages() { <%_ if (!reactive) { _%> restMockMvc.perform(post("/api/<%= dasherizedBaseName %>-kafka/publish/topic-produce?message=value-produce")) - .andExpect(status().isOk()) + .andExpect(status().isOk) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) <%_ } else { _%> client.post().uri("/api/jhipster-kafka/publish/topic-produce?message=value-produce") .exchange() - .expectStatus().isOk() + .expectStatus().isOk .expectHeader().contentType(MediaType.APPLICATION_JSON) <%_ } _%> @@ -139,7 +139,7 @@ class <%= upperFirstCamelCase(baseName) %>KafkaResourceIT { <%_ if (!reactive) { _%> val mvcResult = restMockMvc.perform(get("/api/<%= dasherizedBaseName %>-kafka/consume?topic=topic-consume")) - .andExpect(status().isOk()) + .andExpect(status().isOk) .andExpect(request().asyncStarted()) .andReturn() @@ -155,7 +155,7 @@ class <%= upperFirstCamelCase(baseName) %>KafkaResourceIT { val value = client.get().uri("/api/jhipster-kafka/consume?topic=topic-consume") .accept(MediaType.TEXT_EVENT_STREAM) .exchange() - .expectStatus().isOk() + .expectStatus().isOk .expectHeader().contentTypeCompatibleWith(MediaType.TEXT_EVENT_STREAM) .returnResult(String::class) .getResponseBody().blockFirst(Duration.ofSeconds(10)) diff --git a/generators/server/templates/src/test/kotlin/package/web/rest/LogoutResourceIT.kt.ejs b/generators/server/templates/src/test/kotlin/package/web/rest/LogoutResourceIT.kt.ejs index 5e05c553e..67a1585ee 100644 --- a/generators/server/templates/src/test/kotlin/package/web/rest/LogoutResourceIT.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/web/rest/LogoutResourceIT.kt.ejs @@ -18,25 +18,12 @@ -%> package <%= packageName %>.web.rest -import <%= packageName %>.<%= mainClass %> -<%_ if (cacheProvider === 'redis') { _%> -import <%= packageName %>.RedisTestContainerExtension -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import <%= packageName %>.AbstractNeo4jIT -<%_ } _%> +import <%= packageName %>.IntegrationTest; import <%= packageName %>.config.TestSecurityConfiguration import <%= packageName %>.security.USER import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test -<%_ if (cacheProvider === 'redis') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest <%_ if (reactive) { _%> import org.springframework.context.ApplicationContext <%_ } _%> @@ -67,13 +54,7 @@ import org.springframework.security.test.web.reactive.server.SecurityMockServerC /** * Integration tests for the [LogoutResource] REST controller. */ -@SpringBootTest(classes = [<%= mainClass %>::class, TestSecurityConfiguration::class]) -<%_ if (cacheProvider === 'redis') { _%> -@ExtendWith(RedisTestContainerExtension::class) -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -@ExtendWith(AbstractNeo4jIT::class) -<%_ } _%> +@IntegrationTest class LogoutResourceIT { @Autowired @@ -94,7 +75,7 @@ class LogoutResourceIT { <% if (!reactive) { %>@Throws(Exception::class)<% } %> fun before() { val claims = mapOf( - "groups" to listOf("ROLE_USER"), + "groups" to listOf(USER), "sub" to 123 ) val idToken = OidcIdToken(ID_TOKEN, Instant.now(), Instant.now().plusSeconds(60), claims) @@ -131,9 +112,9 @@ class LogoutResourceIT { .block() this.webTestClient.mutateWith(csrf()) - .mutateWith(mockAuthentication(TestUtil.authenticationToken(idToken))) + .mutateWith(mockAuthentication(authenticationToken(idToken))) .post().uri("/api/logout").exchange() - .expectStatus().isOk() + .expectStatus().isOk .expectHeader().contentType(MediaType.APPLICATION_JSON_VALUE) .expectBody() .jsonPath("$.logoutUrl").isEqualTo(logoutUrl.toString()) diff --git a/generators/server/templates/src/test/kotlin/package/web/rest/PublicUserResourceIT.kt.ejs b/generators/server/templates/src/test/kotlin/package/web/rest/PublicUserResourceIT.kt.ejs new file mode 100644 index 000000000..e4287fb8c --- /dev/null +++ b/generators/server/templates/src/test/kotlin/package/web/rest/PublicUserResourceIT.kt.ejs @@ -0,0 +1,267 @@ +<%# + Copyright 2013-2020 the original author or authors from the JHipster project. + +This file is part of the JHipster project, see https://jhipster.github.io/ + for more information. + + Licensed under the Apache License, Version 2.0 (the "License") + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +-%> +package <%= packageName %>.web.rest + +<%_ if (databaseType === 'cassandra') { _%> +import <%= packageName %>.AbstractCassandraTest +<%_ } _%> +import <%= packageName %>.IntegrationTest +import <%= packageName %>.security.ADMIN +import <%= packageName %>.security.USER +<%_ if (authenticationType === 'oauth2') { _%> +import <%= packageName %>.config.TestSecurityConfiguration +<%_ } _%> +import <%= packageName %>.domain.<%= asEntity('User') %> +import <%= packageName %>.repository.UserRepository +<%_ if (searchEngine === 'elasticsearch') { _%> +import <%= packageName %>.repository.search.UserSearchRepository +<%_ } _%> +<%_ if (databaseType === 'sql' && reactive) { _%> +import <%= packageName %>.service.EntityManager +<%_ } _%> +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +<%_ if (!reactive) { _%> +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc +<%_ } else { _%> +import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient +<%_ } _%> +<%_ if (cacheManagerIsAvailable === true) { _%> +import org.springframework.cache.CacheManager +<%_ } _%> +<%_ if (cacheProvider === 'memcached' ) { _%> +import org.springframework.cache.support.NoOpCacheManager +<%_ } _%> +import org.springframework.http.MediaType +<%_ if (databaseType === 'couchbase') { _%> +import org.springframework.security.core.context.SecurityContextHolder +import org.springframework.security.test.context.TestSecurityContextHolder +<%_ } _%> +import org.springframework.security.test.context.support.WithMockUser +<%_ if (reactive) { _%> +import <%= packageName %>.service.dto.<%= asDto('User') %> +import org.springframework.test.web.reactive.server.WebTestClient +<%_ } _%> +<%_ if (!reactive) { _%> +import org.springframework.test.web.servlet.MockMvc +<%_ } _%> +<%_ if (databaseType === 'sql' && !reactive) { _%> +import org.springframework.transaction.annotation.Transactional +<%_ } _%> +<%_ if (reactive && searchEngine === 'elasticsearch') { _%> +import reactor.core.publisher.Mono +<%_ } _%> + +<%_ if (databaseType === 'sql' && !reactive) { _%> +import javax.persistence.EntityManager +<%_ } _%> +<%_ if (databaseType === 'cassandra' || databaseType === 'couchbase') { _%> +import java.util.stream.Collectors +import java.util.stream.Stream +<%_ } _%> +<%_ if (databaseType === 'cassandra') { _%> +import java.util.UUID +<%_ } _%> + +<%_ if (reactive) { _%> +import org.assertj.core.api.Assertions.assertThat +<%_ } _%> +<%_ if (reactive && searchEngine === 'elasticsearch') { _%> +import org.mockito.Mockito.* +<%_ } _%> +<%_ if (!reactive) { _%> + <%_ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') { _%> +import org.hamcrest.Matchers.hasItems + <%_ } _%> +import org.hamcrest.Matchers.hasItem +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.* +import org.springframework.test.web.servlet.result.MockMvcResultMatchers.* +<%_ } else if (testsNeedCsrf) { _%> +import org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.csrf +<%_ } _%> + +/** + * Integration tests for the {@link UserResource} REST controller. + */ +<%_ if (!reactive) { _%> +@AutoConfigureMockMvc +<%_ } else { _%> +@AutoConfigureWebTestClient +<%_ } _%> +@WithMockUser(authorities = [ADMIN]) +@IntegrationTest +class PublicUserResourceIT <% if (databaseType === 'cassandra') { %>: AbstractCassandraTest() <% } %>{ + + private val DEFAULT_LOGIN = "johndoe" + + <%_ const DEFAULT_USER = {firstName: 'john', lastName: 'doe'}; _%> + <%_ for (field of user.fields.filter(field => !field.builtIn && field.relatedByOtherEntity)) { _%> + private val DEFAULT_<%= field.fieldName.toUpperCase() %> = "<%= DEFAULT_USER [field.fieldName] %>" + <%_ } _%> + + @Autowired + private lateinit var userRepository: UserRepository + <%_ if (searchEngine === 'elasticsearch') { _%> + + /** + * This repository is mocked in the <%= packageName %>.repository.search test package. + * + * @see <%= packageName %>.repository.search.UserSearchRepositoryMockConfiguration + */ + @Autowired + private lateinit var mockUserSearchRepository: UserSearchRepository + <%_ } _%> + <%_ if (databaseType === 'sql') { _%> + + @Autowired + private lateinit var em: EntityManager + <%_ } _%> + <%_ if (cacheManagerIsAvailable === true) { _%> + + @Autowired + private lateinit var cacheManager: CacheManager + <%_ } _%> + + @Autowired + <%_ if (reactive) { _%> + private lateinit var webTestClient: WebTestClient + <%_ } else { _%> + private lateinit var restUserMockMvc: MockMvc + <%_ } _%> + + private lateinit var user: <%= asEntity('User') %> + + <%_ if (cacheManagerIsAvailable === true) { _%> + @BeforeEach + fun setup() { + cacheManager.getCache(UserRepository.USERS_BY_LOGIN_CACHE).clear() + cacheManager.getCache(UserRepository.USERS_BY_EMAIL_CACHE).clear() + } + + <%_ } _%> + <%_ if (reactive && testsNeedCsrf) { _%> + @BeforeEach + fun setupCsrf() { + webTestClient = webTestClient.mutateWith(csrf()) + } + + <%_ } _%> + @BeforeEach + fun initTest() { + user = UserResourceIT.initTestUser(userRepository<% if (databaseType === 'sql') { %>, em<% } %>) + } + + @Test + <%_ if (databaseType === 'sql' && !reactive) { _%> + @Transactional + <%_ } _%> + <%_ if (!reactive) { _%> + @Throws(Exception::class) + <%_ } _%> + fun getAllPublicUsers() { + // Initialize the database + userRepository.<% if (databaseType === 'sql' && reactive && authenticationType === 'oauth2') { %>create<% } else { %>save<% } %><% if (databaseType === 'sql' && !reactive) { %>AndFlush<% } %>(user)<% if (reactive) { %>.block()<% } %> + + // Get all the users + <%_ if (!reactive) { _%> + restUserMockMvc.perform(get("/api/users<% if (databaseType === 'sql') { %>?sort=id,desc<% } %>") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("$.[*].login").value(hasItem(DEFAULT_LOGIN))) + <%_ for (field of user.fields.filter(field => !field.builtIn && field.relatedByOtherEntity)) { _%> + .andExpect(jsonPath("$.[*].<%= field.fieldName %>").value(hasItem(DEFAULT_<%= field.fieldName.toUpperCase() %>))) + <%_ } _%> + .andExpect(jsonPath("$.[*].email").doesNotExist()) + <%_ if (databaseType !== 'cassandra') { _%> + .andExpect(jsonPath("$.[*].imageUrl").doesNotExist()) + <%_ } _%> + .andExpect(jsonPath("$.[*].langKey").doesNotExist()) + <%_ } else { _%> + val foundUser = webTestClient.get().uri("/api/users?sort=id,DESC") + .accept(MediaType.APPLICATION_JSON) + .exchange() + .expectStatus().isOk + .expectHeader().contentType(MediaType.APPLICATION_JSON) + .returnResult(<%= asDto('User') %>::class.java).responseBody.blockFirst() + + assertThat(foundUser.login).isEqualTo(DEFAULT_LOGIN) + <%_ for (field of user.fields.filter(field => !field.builtIn && field.relatedByOtherEntity)) { _%> + assertThat(foundUser.<%= field.fieldName %>).isEqualTo(DEFAULT_<%= field.fieldName.toUpperCase() %>) + <%_ } _%> + <% } _%> + } + + <%_ if ((databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') + && (!(authenticationType === 'oauth2' && applicationType === 'microservice'))) { _%> + @Test + <%_ if (databaseType === 'sql' && !reactive) { _%> + @Transactional + <%_ } _%> + <%_ if (!reactive) { _%> + @Throws(Exception::class) + <%_ } _%> + fun getAllAuthorities() { + <%_ if (!reactive) { _%> + restUserMockMvc.perform(get("/api/authorities") + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk) + .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("$").isArray()) + .andExpect(jsonPath("$").value(hasItems(USER, ADMIN))) + <%_ } else { _%> + webTestClient.get().uri("/api/authorities") + .accept(MediaType.APPLICATION_JSON) + .exchange() + .expectStatus().isOk + .expectHeader().contentType(MediaType.APPLICATION_JSON_VALUE) + .expectBody() + .jsonPath("$").isArray() + .jsonPath("$[?(@=='$ADMIN')]").hasJsonPath() + .jsonPath("$[?(@=='$USER')]").hasJsonPath() + <%_ } _%> + } + <%_ } _%> + + <%_ if (databaseType === 'sql' && authenticationType !== 'oauth2') { _%> + @Test + <%_ if (!reactive) { _%> + @Transactional + <%_ } _%> + @Throws(Exception::class) + fun getAllUsersSortedByParameters() { + // Initialize the database + userRepository.<% if (reactive) { %>save<% } else { %>saveAndFlush<% } %>(user)<% if (reactive) { %>.block()<% } %> + + <%_ if (!reactive) { _%> + restUserMockMvc.perform(get("/api/users?sort=resetKey,desc").accept(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest) + restUserMockMvc.perform(get("/api/users?sort=password,desc").accept(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest) + restUserMockMvc.perform(get("/api/users?sort=resetKey,id,desc").accept(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest) + restUserMockMvc.perform(get("/api/users?sort=id,desc").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk) + <%_ } else { _%> + webTestClient.get().uri("/api/users?sort=resetKey,DESC").accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isBadRequest + webTestClient.get().uri("/api/users?sort=password,DESC").accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isBadRequest + webTestClient.get().uri("/api/users?sort=resetKey,id,DESC").accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isBadRequest + webTestClient.get().uri("/api/users?sort=id,DESC").accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk + <%_ } _%> + } + <%_ } _%> +} diff --git a/generators/server/templates/src/test/kotlin/package/web/rest/TestUtil.kt.ejs b/generators/server/templates/src/test/kotlin/package/web/rest/TestUtil.kt.ejs index 148479492..1bb149d2b 100644 --- a/generators/server/templates/src/test/kotlin/package/web/rest/TestUtil.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/web/rest/TestUtil.kt.ejs @@ -33,6 +33,7 @@ import <%= packageName %>.security.extractAuthorityFromClaims <%_ } _%> import org.hamcrest.Description import org.hamcrest.TypeSafeDiagnosingMatcher +import org.hamcrest.TypeSafeMatcher <%_ if (!reactive) { _%> import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar import org.springframework.format.support.DefaultFormattingConversionService @@ -65,6 +66,7 @@ import java.util.concurrent.TimeUnit <%_ } _%> import java.io.IOException +import java.math.BigDecimal import java.time.ZonedDateTime import java.time.format.DateTimeParseException @@ -140,6 +142,42 @@ class ZonedDateTimeMatcher(private val date: ZonedDateTime) : TypeSafeDiagnosing */ fun sameInstant(date: ZonedDateTime) = ZonedDateTimeMatcher(date) +/** +* A matcher that tests that the examined number represents the same value - it can be Long, Double, etc - as the reference BigDecimal. +*/ +class NumberMatcher(private val value: BigDecimal):TypeSafeMatcher() { + override fun describeTo(description: Description) { + description.appendText("a numeric value is ").appendValue(value) + } + + override fun matchesSafely(item: Number): Boolean { + val bigDecimal = asDecimal(item) + return value.compareTo(bigDecimal) == 0 + } + + fun asDecimal(item: Number?): BigDecimal? { + if (item == null) { + return null + } + + return when (item) { + is BigDecimal -> item + is Long -> item.toBigDecimal() + is Int -> item.toLong().toBigDecimal() + is Float -> item.toBigDecimal() + is Double -> item.toBigDecimal() + else -> item.toDouble().toBigDecimal() + } + } +} + +/** +* Creates a matcher that matches when the examined number represents the same value as the reference BigDecimal. +* +* @param number the reference BigDecimal against which the examined number is checked. +*/ +fun sameNumber(number: BigDecimal): NumberMatcher = NumberMatcher(number) + /** * Verifies the equals/hashcode contract on the domain object. */ @@ -147,7 +185,7 @@ fun equalsVerifier(clazz: KClass) { val domainObject1 = clazz.createInstance() assertThat(domainObject1.toString()).isNotNull() assertThat(domainObject1).isEqualTo(domainObject1) - assertThat(domainObject1.hashCode()).isEqualTo(domainObject1.hashCode()) + assertThat(domainObject1).hasSameHashCodeAs(domainObject1) // Test with an instance of another class val testOtherObject = Any() assertThat(domainObject1).isNotEqualTo(testOtherObject) @@ -157,7 +195,7 @@ fun equalsVerifier(clazz: KClass) { assertThat(domainObject1).isNotEqualTo(domainObject2) <%_ if (databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'couchbase') { _%> // HashCodes are equals because the objects are not persisted yet - assertThat(domainObject1.hashCode()).isEqualTo(domainObject2.hashCode()) + assertThat(domainObject1).hasSameHashCodeAs(domainObject2) <%_ } _%> } <%_ if (!reactive) { _%> diff --git a/generators/server/templates/src/test/kotlin/package/web/rest/UserJWTControllerIT.kt.ejs b/generators/server/templates/src/test/kotlin/package/web/rest/UserJWTControllerIT.kt.ejs index 5b08ce2ed..7ed560890 100644 --- a/generators/server/templates/src/test/kotlin/package/web/rest/UserJWTControllerIT.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/web/rest/UserJWTControllerIT.kt.ejs @@ -21,16 +21,10 @@ package <%= packageName %>.web.rest <%_ if (databaseType === 'cassandra') { _%> import <%= packageName %>.AbstractCassandraTest <%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import <%= packageName %>.AbstractNeo4jIT -<%_ } _%> -<%_ if (cacheProvider === 'redis') { _%> -import <%= packageName %>.RedisTestContainerExtension -<%_ } _%> +import <%= packageName %>.IntegrationTest <%_ if (databaseType === 'sql' && reactive) { _%> import <%= packageName %>.config.SYSTEM_ACCOUNT <%_ } _%> -import <%= packageName %>.<%= mainClass %> <%_ if (!skipUserManagement) { _%> <%_ if (databaseType === 'sql' && reactive) { _%> import <%= packageName %>.config.Constants @@ -40,19 +34,12 @@ import <%= packageName %>.repository.UserRepository <%_ } _%> import <%= packageName %>.web.rest.vm.LoginVM import org.junit.jupiter.api.Test -<%_ if (cacheProvider === 'redis') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> import org.springframework.beans.factory.annotation.Autowired <%_ if (!reactive) { _%> import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc <%_ } else { _%> import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient <%_ } _%> -import org.springframework.boot.test.context.SpringBootTest import org.springframework.http.MediaType <%_ if (!skipUserManagement) { _%> import org.springframework.security.crypto.password.PasswordEncoder @@ -62,7 +49,6 @@ import org.springframework.test.web.reactive.server.WebTestClient <%_ } _%> <%_ if (!reactive) { _%> import org.springframework.test.web.servlet.MockMvc -import org.springframework.test.web.servlet.setup.MockMvcBuilders <%_ if (databaseType === 'sql') { _%> import org.springframework.transaction.annotation.Transactional <%_ } _%> @@ -88,13 +74,7 @@ import org.hamcrest.Matchers.* <%_ } else { _%> @AutoConfigureWebTestClient <%_ } _%> -@SpringBootTest(classes = [<%= mainClass %>::class]) -<%_ if (cacheProvider === 'redis') { _%> -@ExtendWith(RedisTestContainerExtension::class) -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -@ExtendWith(AbstractNeo4jIT::class) -<%_ } _%> +@IntegrationTest class UserJWTControllerIT <% if (databaseType === 'cassandra') { %>: AbstractCassandraTest() <% } %>{ <%_ if (!skipUserManagement) { _%> diff --git a/generators/server/templates/src/test/kotlin/package/web/rest/UserResourceIT.kt.ejs b/generators/server/templates/src/test/kotlin/package/web/rest/UserResourceIT.kt.ejs index 26517ef49..d4fceeb72 100644 --- a/generators/server/templates/src/test/kotlin/package/web/rest/UserResourceIT.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/web/rest/UserResourceIT.kt.ejs @@ -21,19 +21,10 @@ package <%= packageName %>.web.rest <%_ if (databaseType === 'cassandra') { _%> import <%= packageName %>.AbstractCassandraTest <%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import <%= packageName %>.AbstractNeo4jIT -<%_ } _%> -<%_ if (cacheProvider === 'redis') { _%> -import <%= packageName %>.RedisTestContainerExtension -<%_ } _%> -import <%= packageName %>.<%= mainClass %> +import <%= packageName %>.IntegrationTest <%_ if (databaseType === 'sql' && reactive) { _%> import <%= packageName %>.config.SYSTEM_ACCOUNT <%_ } _%> -<%_ if (authenticationType === 'oauth2') { _%> -import <%= packageName %>.config.TestSecurityConfiguration -<%_ } _%> <%_ if (databaseType !== 'cassandra' && databaseType !== 'couchbase') { _%> import <%= packageName %>.domain.Authority <%_ } _%> @@ -44,7 +35,11 @@ import <%= packageName %>.repository.search.UserSearchRepository <%_ } _%> import <%= packageName %>.security.ADMIN import <%= packageName %>.security.USER +import <%= packageName %>.service.dto.<%= asDto('AdminUser') %> import <%= packageName %>.service.dto.<%= asDto('User') %> +<%_ if (databaseType === 'sql' && reactive) { _%> +import <%= packageName %>.service.EntityManager +<%_ } _%> import <%= packageName %>.service.mapper.UserMapper <%_ if (authenticationType !== 'oauth2') { _%> import <%= packageName %>.web.rest.vm.ManagedUserVM @@ -52,19 +47,12 @@ import <%= packageName %>.web.rest.vm.ManagedUserVM import org.apache.commons.lang3.RandomStringUtils import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test -<%_ if (cacheProvider === 'redis') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> import org.springframework.beans.factory.annotation.Autowired <%_ if (!reactive) { _%> import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc <%_ } else { _%> import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient <%_ } _%> -import org.springframework.boot.test.context.SpringBootTest <%_ if (cacheManagerIsAvailable === true) { _%> import org.springframework.cache.CacheManager <%_ } _%> @@ -96,10 +84,8 @@ import javax.persistence.EntityManager <%_ if (databaseType !== 'cassandra') { _%> import java.time.Instant <%_ } _%> -import java.util.function.Consumer -<%_ if (databaseType === 'cassandra' || (authenticationType === 'oauth2' && databaseType !== 'couchbase')) { _%> import java.util.UUID -<%_ } _%> +import java.util.function.Consumer import org.assertj.core.api.Assertions.assertThat <%_ if (reactive && searchEngine === 'elasticsearch') { _%> @@ -137,17 +123,7 @@ import kotlin.test.assertNull @AutoConfigureWebTestClient <%_ } _%> @WithMockUser(authorities = [ADMIN]) -<%_ if (authenticationType === 'oauth2') { _%> -@SpringBootTest(classes = [<%= mainClass %>::class, TestSecurityConfiguration::class]) -<%_ } else { _%> -@SpringBootTest(classes = [<%= mainClass %>::class]) -<%_ } _%> -<%_ if (cacheProvider === 'redis') { _%> -@ExtendWith(RedisTestContainerExtension::class) -<%_ } _%> -<%_ if (databaseType === 'neo4j') { _%> -@ExtendWith(AbstractNeo4jIT::class) -<%_ } _%> +@IntegrationTest class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandraTest() <% } %>{ @Autowired @@ -166,7 +142,7 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra @Autowired private lateinit var userMapper: UserMapper - <%_ if (databaseType === 'sql' && !reactive) { _%> + <%_ if (databaseType === 'sql') { _%> @Autowired private lateinit var em: EntityManager @@ -203,21 +179,7 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra @BeforeEach fun initTest() { - <%_ if (databaseType === 'sql' && reactive) { _%> - userRepository.deleteAllUserAuthorities().block() - <%_ } _%> - <%_ if (databaseType !== 'sql' || reactive) { _%> - userRepository.deleteAll()<% if (reactive) { %>.block()<% } %> - user = createEntity() - <%_ } else { _%> - user = createEntity(em) - <%_ } _%> - <%_ if (databaseType === 'sql') { _%> - user.apply { - login = DEFAULT_LOGIN - email = DEFAULT_EMAIL - } - <%_ } _%> + user = initTestUser(userRepository<% if (databaseType === 'sql' ) { %>, em<% } _%>) } <%_ if (authenticationType !== 'oauth2') { _%> @@ -247,19 +209,19 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra imageUrl = DEFAULT_IMAGEURL <%_ } _%> langKey = DEFAULT_LANGKEY - authorities = setOf(USER) + authorities = mutableSetOf(USER) } <%_ if (!reactive) { _%> restUserMockMvc.perform( - post("/api/users") + post("/api/admin/users") .contentType(MediaType.APPLICATION_JSON) .content(convertObjectToJsonBytes(managedUserVM))<% if (testsNeedCsrf) { %> .with(csrf())<% } %> ) .andExpect(status().isCreated) <%_ } else { _%> - webTestClient.post().uri("/api/users") + webTestClient.post().uri("/api/admin/users") .contentType(MediaType.APPLICATION_JSON) .bodyValue(convertObjectToJsonBytes(managedUserVM)) .exchange() @@ -296,7 +258,7 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra <%_ } else if (databaseType === 'mongodb' || databaseType === 'neo4j' || databaseType === 'couchbase') { _%> id = "1L" <%_ } else { _%> - id = 1L + id = DEFAULT_ID <%_ } _%> login = DEFAULT_LOGIN password = DEFAULT_PASSWORD @@ -308,20 +270,20 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra imageUrl = DEFAULT_IMAGEURL <%_ } _%> langKey = DEFAULT_LANGKEY - authorities = setOf(USER) + authorities = mutableSetOf(USER) } // An entity with an existing ID cannot be created, so this API call must fail <%_ if (!reactive) { _%> restUserMockMvc.perform( - post("/api/users") + post("/api/admin/users") .contentType(MediaType.APPLICATION_JSON) .content(convertObjectToJsonBytes(managedUserVM))<% if (testsNeedCsrf) { %> .with(csrf())<% } %> ) .andExpect(status().isBadRequest) <%_ } else { _%> - webTestClient.post().uri("/api/users") + webTestClient.post().uri("/api/admin/users") .contentType(MediaType.APPLICATION_JSON) .bodyValue(convertObjectToJsonBytes(managedUserVM)) .exchange() @@ -359,20 +321,20 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra imageUrl = DEFAULT_IMAGEURL <%_ } _%> langKey = DEFAULT_LANGKEY - authorities = setOf(USER) + authorities = mutableSetOf(USER) } // Create the User <%_ if (!reactive) { _%> restUserMockMvc.perform( - post("/api/users") + post("/api/admin/users") .contentType(MediaType.APPLICATION_JSON) .content(convertObjectToJsonBytes(managedUserVM))<% if (testsNeedCsrf) { %> .with(csrf())<% } %> ) .andExpect(status().isBadRequest) <%_ } else { _%> - webTestClient.post().uri("/api/users") + webTestClient.post().uri("/api/admin/users") .contentType(MediaType.APPLICATION_JSON) .bodyValue(convertObjectToJsonBytes(managedUserVM)) .exchange() @@ -407,20 +369,20 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra imageUrl = DEFAULT_IMAGEURL <%_ } _%> langKey = DEFAULT_LANGKEY - authorities = setOf(USER) + authorities = mutableSetOf(USER) } // Create the User <%_ if (!reactive) { _%> restUserMockMvc.perform( - post("/api/users") + post("/api/admin/users") .contentType(MediaType.APPLICATION_JSON) .content(convertObjectToJsonBytes(managedUserVM))<% if (testsNeedCsrf) { %> .with(csrf())<% } %> ) .andExpect(status().isBadRequest) <%_ } else { _%> - webTestClient.post().uri("/api/users") + webTestClient.post().uri("/api/admin/users") .contentType(MediaType.APPLICATION_JSON) .bodyValue(convertObjectToJsonBytes(managedUserVM)) .exchange() @@ -445,7 +407,7 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra // Get all the users <%_ if (!reactive) { _%> restUserMockMvc.perform( - get("/api/users<% if (databaseType === 'sql') { %>?sort=id,desc<% } %>") + get("/api/admin/users<% if (databaseType === 'sql') { %>?sort=id,desc<% } %>") .accept(MediaType.APPLICATION_JSON) ) .andExpect(status().isOk) @@ -459,12 +421,12 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra <%_ } _%> .andExpect(jsonPath("\$.[*].langKey").value(hasItem(DEFAULT_LANGKEY))) <%_ } else { _%> - val foundUser = webTestClient.get().uri("/api/users?sort=id,DESC") + val foundUser = webTestClient.get().uri("/api/admin/users?sort=id,DESC") .accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isOk .expectHeader().contentType(MediaType.APPLICATION_JSON) - .returnResult(<%= asDto('User') %>::class.java).responseBody.blockFirst() + .returnResult(<%= asDto('AdminUser') %>::class.java).responseBody.blockFirst() assertNotNull(foundUser) assertThat(foundUser.login).isEqualTo(DEFAULT_LOGIN) @@ -478,32 +440,6 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra <%_ } _%> } - <%_ if (databaseType === 'sql' && authenticationType !== 'oauth2') { _%> - @Test - <%_ if (!reactive) { _%> - @Transactional - <%_ } _%> - <%_ if (!reactive) { _%> - @Throws(Exception::class) - <%_ } _%> - fun getAllUsersSortedByParameters() { - // Initialize the database - userRepository.<% if (reactive) { %>save<% } else { %>saveAndFlush<% } %>(user)<% if (reactive) { %>.block()<% } %> - - <%_ if (!reactive) { _%> - restUserMockMvc.perform(get("/api/users?sort=resetKey,desc").accept(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest) - restUserMockMvc.perform(get("/api/users?sort=password,desc").accept(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest) - restUserMockMvc.perform(get("/api/users?sort=resetKey,id,desc").accept(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest) - restUserMockMvc.perform(get("/api/users?sort=id,desc").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk) - <%_ } else { _%> - webTestClient.get().uri("/api/users?sort=resetKey,DESC").accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isBadRequest - webTestClient.get().uri("/api/users?sort=password,DESC").accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isBadRequest - webTestClient.get().uri("/api/users?sort=resetKey,id,DESC").accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isBadRequest - webTestClient.get().uri("/api/users?sort=id,DESC").accept(MediaType.APPLICATION_JSON).exchange().expectStatus().isOk - <%_ } _%> - } - <%_ } _%> - @Test <%_ if (databaseType === 'sql' && !reactive) { _%> @Transactional @@ -524,7 +460,7 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra // Get the user <%_ if (!reactive) { _%> - restUserMockMvc.perform(get("/api/users/{login}", user.login)) + restUserMockMvc.perform(get("/api/admin/users/{login}", user.login)) .andExpect(status().isOk) .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) .andExpect(jsonPath("\$.login").value(user.login!!)) @@ -536,7 +472,7 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra <%_ } _%> .andExpect(jsonPath("\$.langKey").value(DEFAULT_LANGKEY)) <%_ } else { _%> - webTestClient.get().uri("/api/users/{login}", user.login) + webTestClient.get().uri("/api/admin/users/{login}", user.login) .exchange() .expectStatus().isOk .expectHeader().contentType(MediaType.APPLICATION_JSON) @@ -569,10 +505,10 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra <%_ } _%> fun getNonExistingUser() { <%_ if (!reactive) { _%> - restUserMockMvc.perform(get("/api/users/unknown")) + restUserMockMvc.perform(get("/api/admin/users/unknown")) .andExpect(status().isNotFound) <%_ } else { _%> - webTestClient.get().uri("/api/users/unknown") + webTestClient.get().uri("/api/admin/users/unknown") .exchange() .expectStatus().isNotFound <%_ } _%> @@ -617,19 +553,19 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra lastModifiedBy = updatedUser.lastModifiedBy lastModifiedDate = updatedUser.lastModifiedDate <%_ } _%> - authorities = setOf(USER) + authorities = mutableSetOf(USER) } <%_ if (!reactive) { _%> restUserMockMvc.perform( - put("/api/users") + put("/api/admin/users") .contentType(MediaType.APPLICATION_JSON) .content(convertObjectToJsonBytes(managedUserVM))<% if (testsNeedCsrf) { %> .with(csrf())<% } %> ) .andExpect(status().isOk) <%_ } else { _%> - webTestClient.put().uri("/api/users") + webTestClient.put().uri("/api/admin/users") .contentType(MediaType.APPLICATION_JSON) .bodyValue(convertObjectToJsonBytes(managedUserVM)) .exchange() @@ -687,19 +623,19 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra lastModifiedBy = updatedUser.lastModifiedBy lastModifiedDate = updatedUser.lastModifiedDate <%_ } _%> - authorities = setOf(USER) + authorities = mutableSetOf(USER) } <%_ if (!reactive) { _%> restUserMockMvc.perform( - put("/api/users") + put("/api/admin/users") .contentType(MediaType.APPLICATION_JSON) .content(convertObjectToJsonBytes(managedUserVM))<% if (testsNeedCsrf) { %> .with(csrf())<% } %> ) .andExpect(status().isOk) <%_ } else { _%> - webTestClient.put().uri("/api/users") + webTestClient.put().uri("/api/admin/users") .contentType(MediaType.APPLICATION_JSON) .bodyValue(convertObjectToJsonBytes(managedUserVM)) .exchange() @@ -777,19 +713,19 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra lastModifiedBy = updatedUser.lastModifiedBy lastModifiedDate = updatedUser.lastModifiedDate <%_ } _%> - authorities = setOf(USER) + authorities = mutableSetOf(USER) } <%_ if (!reactive) { _%> restUserMockMvc.perform( - put("/api/users") + put("/api/admin/users") .contentType(MediaType.APPLICATION_JSON) .content(convertObjectToJsonBytes(managedUserVM))<% if (testsNeedCsrf) { %> .with(csrf())<% } %> ) .andExpect(status().isBadRequest) <%_ } else { _%> - webTestClient.put().uri("/api/users") + webTestClient.put().uri("/api/admin/users") .contentType(MediaType.APPLICATION_JSON) .bodyValue(convertObjectToJsonBytes(managedUserVM)) .exchange() @@ -854,19 +790,19 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra lastModifiedBy = updatedUser.lastModifiedBy lastModifiedDate = updatedUser.lastModifiedDate <%_ } _%> - authorities = setOf(USER) + authorities = mutableSetOf(USER) } <%_ if (!reactive) { _%> restUserMockMvc.perform( - put("/api/users") + put("/api/admin/users") .contentType(MediaType.APPLICATION_JSON) .content(convertObjectToJsonBytes(managedUserVM))<% if (testsNeedCsrf) { %> .with(csrf())<% } %> ) .andExpect(status().isBadRequest) <%_ } else { _%> - webTestClient.put().uri("/api/users") + webTestClient.put().uri("/api/admin/users") .contentType(MediaType.APPLICATION_JSON) .bodyValue(convertObjectToJsonBytes(managedUserVM)) .exchange() @@ -897,13 +833,13 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra // Delete the user <%_ if (!reactive) { _%> restUserMockMvc.perform( - delete("/api/users/{login}", user.login) + delete("/api/admin/users/{login}", user.login) .accept(MediaType.APPLICATION_JSON)<% if (testsNeedCsrf) { %> .with(csrf())<% } %> ) .andExpect(status().isNoContent) <%_ } else { _%> - webTestClient.delete().uri("/api/users/{login}", user.login) + webTestClient.delete().uri("/api/admin/users/{login}", user.login) .accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isNoContent @@ -917,49 +853,15 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra } <%_ } _%> - <%_ if ((databaseType === 'sql' || databaseType === 'mongodb' || databaseType === 'couchbase') - && (!(authenticationType === 'oauth2' && applicationType === 'microservice'))) { _%> - - @Test - <%_ if (databaseType === 'sql' && !reactive) { _%> - @Transactional - <%_ } _%> - <%_ if (!reactive) { _%> - @Throws(Exception::class) - <%_ } _%> - fun getAllAuthorities() { - <%_ if (!reactive) { _%> - restUserMockMvc.perform( - get("/api/users/authorities") - .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - ) - .andExpect(status().isOk) - .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) - .andExpect(jsonPath("\$").isArray) - .andExpect(jsonPath("\$").value(hasItems(USER, ADMIN))) - <%_ } else { _%> - webTestClient.get().uri("/api/users/authorities") - .accept(MediaType.APPLICATION_JSON) - .exchange() - .expectStatus().isOk - .expectHeader().contentType(MediaType.APPLICATION_JSON_VALUE) - .expectBody() - .jsonPath("\$").isArray - .jsonPath("\$[?(@=='" + ADMIN + "')]").hasJsonPath() - .jsonPath("\$[?(@=='" + USER + "')]").hasJsonPath() - <%_ } _%> - } - <%_ } _%> @Test @Throws(Exception::class) fun testUserEquals() { equalsVerifier(<%= asEntity('User') %>::class) - val user1 = <%= asEntity('User') %>(id = <% if (databaseType === 'sql' && authenticationType !== 'oauth2') { %>1L<% } else { %>"id1"<% } %>) + val user1 = <%= asEntity('User') %>(id = DEFAULT_ID) val user2 = <%= asEntity('User') %>(id = user1.id) assertThat(user1).isEqualTo(user2) - user2.id = <% if (databaseType === 'sql' && authenticationType !== 'oauth2') { %>2L<% } else { %>"id2"<% } %> + user2.id = <%- getPrimaryKeyValue(user.primaryKey.type, databaseType, 2) %> assertThat(user1).isNotEqualTo(user2) user1.id = null assertThat(user1).isNotEqualTo(user2) @@ -967,7 +869,7 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra @Test fun testUserDTOtoUser() { - val userDTO = <%= asDto('User') %>( + val userDTO = <%= asDto('AdminUser') %>( id = DEFAULT_ID, login = DEFAULT_LOGIN, firstName = DEFAULT_FIRSTNAME, @@ -982,7 +884,7 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra createdBy = DEFAULT_LOGIN, lastModifiedBy = DEFAULT_LOGIN, <%_ } _%> - authorities = setOf(USER) + authorities = mutableSetOf(USER) ) val user = userMapper.userDTOToUser(userDTO) @@ -992,7 +894,7 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra assertThat(user.firstName).isEqualTo(DEFAULT_FIRSTNAME) assertThat(user.lastName).isEqualTo(DEFAULT_LASTNAME) assertThat(user.email).isEqualTo(DEFAULT_EMAIL) - assertThat(user.activated).isEqualTo(true) + assertThat(user.activated).isTrue() <%_ if (databaseType !== 'cassandra') { _%> assertThat(user.imageUrl).isEqualTo(DEFAULT_IMAGEURL) <%_ } _%> @@ -1021,14 +923,14 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra user.authorities = mutableSetOf(USER) <%_ } _%> - val userDTO = userMapper.userToUserDTO(user) + val userDTO = userMapper.userToAdminUserDTO(user) assertThat(userDTO.id).isEqualTo(DEFAULT_ID) assertThat(userDTO.login).isEqualTo(DEFAULT_LOGIN) assertThat(userDTO.firstName).isEqualTo(DEFAULT_FIRSTNAME) assertThat(userDTO.lastName).isEqualTo(DEFAULT_LASTNAME) assertThat(userDTO.email).isEqualTo(DEFAULT_EMAIL) - assertThat(userDTO.isActivated()).isEqualTo(true) + assertThat(userDTO.activated).isTrue() <%_ if (databaseType !== 'cassandra') { _%> assertThat(userDTO.imageUrl).isEqualTo(DEFAULT_IMAGEURL) <%_ } _%> @@ -1047,9 +949,9 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra @Test fun testAuthorityEquals() { val authorityA = Authority() - assertThat(authorityA).isEqualTo(authorityA) - assertThat(authorityA).isNotEqualTo(null) - assertThat(authorityA).isNotEqualTo(Any()) + assertThat(authorityA) + .isNotEqualTo(null) + .isNotEqualTo(Any()) assertThat(authorityA.hashCode()).isEqualTo(31) assertThat(authorityA.toString()).isNotNull() @@ -1063,8 +965,9 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra assertThat(authorityA).isNotEqualTo(authorityB) authorityB.name = USER - assertThat(authorityA).isEqualTo(authorityB) - assertThat(authorityA.hashCode()).isEqualTo(authorityB.hashCode()) + assertThat(authorityA) + .isEqualTo(authorityB) + .hasSameHashCodeAs(authorityB) } <%_ } _%> @@ -1075,12 +978,10 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra private const val UPDATED_LOGIN = "jhipster" <%_ } _%> - <%_ if (databaseType === 'sql' && authenticationType !== 'oauth2') { _%> - private const val DEFAULT_ID = 1L - <%_ } else if (databaseType === 'couchbase'){ _%> + <%_ if (databaseType === 'couchbase'){ _%> private const val DEFAULT_ID = <%= asEntity('User') %>.PREFIX + DEFAULT_LOGIN <%_ } else { _%> - private const val DEFAULT_ID = "id1" + private const val DEFAULT_ID = <%- getPrimaryKeyValue(user.primaryKey.type) %> <%_ } _%> <%_ if (authenticationType !== 'oauth2') { _%> @@ -1122,7 +1023,7 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra * if they test an entity which has a required relationship to the User entity. */ @JvmStatic - fun createEntity(<% if (databaseType === 'sql' && !reactive) { %>em: EntityManager?<% } %>): <%= asEntity('User') %> { + fun createEntity(<% if (databaseType === 'sql') { %>em: EntityManager?<% } %>): <%= asEntity('User') %> { return <%= asEntity('User') %>( <%_ if (databaseType === 'cassandra' || (authenticationType === 'oauth2' && databaseType !== 'couchbase')) { _%> id = UUID.randomUUID().toString(), @@ -1144,6 +1045,41 @@ class UserResourceIT<% if (databaseType === 'cassandra') { %>: AbstractCassandra langKey = DEFAULT_LANGKEY ) } + + <%_ if (databaseType === 'sql' && reactive) { _%> + + /** + * Delete all the users from the database. + */ + @JvmStatic + fun deleteEntities(em: EntityManager) { + try { + em.deleteAll("<%= jhiTablePrefix %>_user_authority").block() + em.deleteAll(User::class.java).block() + } catch (e: Exception) { + // It can fail, if other entities are still referring this - it will be removed later. + } + } + <%_ } _%> + + /** + * Setups the database with one user. + */ + @JvmStatic + fun initTestUser(userRepository: UserRepository<% if (databaseType === 'sql' ) { %>, em: EntityManager<% } _%>): <%= asEntity('User') %> { + <%_ if (databaseType === 'sql' && reactive) { _%> + userRepository.deleteAllUserAuthorities().block() + <%_ } _%> + <%_ if (databaseType !== 'sql' || reactive) { _%> + userRepository.deleteAll()<% if (reactive) { %>.block()<% } %> + <%_ } _%> + val user = createEntity(<% if (databaseType === 'sql' ) { %>em<% } _%>); + <%_ if (databaseType === 'sql') { _%> + user.login = DEFAULT_LOGIN + user.email = DEFAULT_EMAIL + <%_ } _%> + return user + } } fun assertPersistedUsers(userAssertion: (List<<%= asEntity('User') %>>) -> Unit) { diff --git a/generators/server/templates/src/test/kotlin/package/web/rest/errors/ExceptionTranslatorIT.kt.ejs b/generators/server/templates/src/test/kotlin/package/web/rest/errors/ExceptionTranslatorIT.kt.ejs index 7c4a074bb..7009027fb 100644 --- a/generators/server/templates/src/test/kotlin/package/web/rest/errors/ExceptionTranslatorIT.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/web/rest/errors/ExceptionTranslatorIT.kt.ejs @@ -21,20 +21,8 @@ package <%= packageName %>.web.rest.errors <%_ if (databaseType === 'cassandra') { _%> import <%= packageName %>.AbstractCassandraTest <%_ } _%> -<%_ if (cacheProvider === 'redis') { _%> -import <%= packageName %>.RedisTestContainerExtension -<%_ } _%> -import <%= packageName %>.<%= mainClass %> -<%_ if (authenticationType === 'uaa') { _%> -import <%= packageName %>.config.SecurityBeanOverrideConfiguration -<%_ } _%> -<%_ if (authenticationType === 'oauth2') { _%> -import <%= packageName %>.config.TestSecurityConfiguration -<%_ } _%> +import <%= packageName %>.IntegrationTest import org.junit.jupiter.api.Test -<%_ if (cacheProvider === 'redis') { _%> -import org.junit.jupiter.api.extension.ExtendWith -<%_ } _%> import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.security.test.context.support.WithMockUser @@ -57,16 +45,7 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status */ @WithMockUser @AutoConfigureMockMvc -<%_ if (authenticationType === 'uaa' && applicationType !== 'uaa') { _%> -@SpringBootTest(classes = [SecurityBeanOverrideConfiguration::class, <%= mainClass %>::class]) -<%_ } else if (authenticationType === 'oauth2') { _%> -@SpringBootTest(classes = [<%= mainClass %>::class, TestSecurityConfiguration::class]) -<%_ } else { _%> -@SpringBootTest(classes = [<%= mainClass %>::class]) -<%_ } _%> -<%_ if (cacheProvider === 'redis') { _%> -@ExtendWith(RedisTestContainerExtension::class) -<%_ } _%> +@IntegrationTest class ExceptionTranslatorIT <% if (databaseType === 'cassandra') { %>: AbstractCassandraTest() <% } %>{ @Autowired @@ -93,7 +72,7 @@ class ExceptionTranslatorIT <% if (databaseType === 'cassandra') { %>: AbstractC .andExpect(jsonPath("\$.message").value(ERR_VALIDATION)) .andExpect(jsonPath("\$.fieldErrors.[0].objectName").value("test")) .andExpect(jsonPath("\$.fieldErrors.[0].field").value("test")) - .andExpect(jsonPath("\$.fieldErrors.[0].message").value("NotNull")) + .andExpect(jsonPath("\$.fieldErrors.[0].message").value("must not be null")) } @Test @@ -183,11 +162,7 @@ import org.springframework.security.test.web.reactive.server.SecurityMockServerC */ @WithMockUser @AutoConfigureWebTestClient -<%_ if (authenticationType === 'oauth2') { _%> -@SpringBootTest(classes = [<%= mainClass %>::class, TestSecurityConfiguration::class]) -<%_ } else { _%> -@SpringBootTest(classes = [<%= mainClass %>::class]) -<%_ } _%> +@IntegrationTest class ExceptionTranslatorIT { @Autowired @@ -224,7 +199,7 @@ class ExceptionTranslatorIT { .jsonPath("\$.message").isEqualTo(ERR_VALIDATION) .jsonPath("\$.fieldErrors.[0].objectName").isEqualTo("test") .jsonPath("\$.fieldErrors.[0].field").isEqualTo("test") - .jsonPath("\$.fieldErrors.[0].message").isEqualTo("NotNull") + .jsonPath("\$.fieldErrors.[0].message").isEqualTo("must not be null") } @Test diff --git a/generators/server/templates/src/test/kotlin/package/web/rest/errors/ExceptionTranslatorTestController.kt.ejs b/generators/server/templates/src/test/kotlin/package/web/rest/errors/ExceptionTranslatorTestController.kt.ejs index 89e736494..521e43bbf 100644 --- a/generators/server/templates/src/test/kotlin/package/web/rest/errors/ExceptionTranslatorTestController.kt.ejs +++ b/generators/server/templates/src/test/kotlin/package/web/rest/errors/ExceptionTranslatorTestController.kt.ejs @@ -67,7 +67,7 @@ class ExceptionTranslatorTestController { fun internalServerError(): Unit = throw RuntimeException() class Test<%= dtoSuffix %> { - @field:NotNull + @field:NotNull<% if (reactive) { %>(message = "must not be null")<% } %> var test: String? = null } diff --git a/generators/spring-controller/index.js b/generators/spring-controller/index.js index d53f2b3ec..bc2767d95 100644 --- a/generators/spring-controller/index.js +++ b/generators/spring-controller/index.js @@ -56,7 +56,7 @@ module.exports = class extends BaseGenerator { initializing() { this.log(`The spring-controller ${this.name} is being created.`); - const configuration = this.getAllJhipsterConfig(this, true); + const configuration = this.config; this.baseName = configuration.get('baseName'); this.packageName = configuration.get('packageName'); this.packageFolder = configuration.get('packageFolder'); diff --git a/generators/spring-controller/prompts.js b/generators/spring-controller/prompts.js index 487591d3d..561aeb442 100644 --- a/generators/spring-controller/prompts.js +++ b/generators/spring-controller/prompts.js @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -const jhiCore = require('jhipster-core'); +const { isReservedFieldName } = require('generator-jhipster/jdl/jhipster/reserved-keywords'); module.exports = { askForControllerActions, @@ -45,7 +45,7 @@ function askForControllerActions() { if (input.charAt(0) === input.charAt(0).toUpperCase()) { return 'Your action name cannot start with an upper case letter'; } - if (jhiCore.isReservedFieldName(input)) { + if (isReservedFieldName(input)) { return 'Your action name cannot contain a Java, Angular or React reserved keyword'; } diff --git a/generators/spring-service/index.js b/generators/spring-service/index.js index 64522d799..2cf203feb 100644 --- a/generators/spring-service/index.js +++ b/generators/spring-service/index.js @@ -51,7 +51,7 @@ module.exports = class extends BaseGenerator { initializing() { this.log(`The service ${this.name} is being created.`); - const configuration = this.getAllJhipsterConfig(this, true); + const configuration = this.config; this.baseName = configuration.get('baseName'); this.packageName = configuration.get('packageName'); this.packageFolder = configuration.get('packageFolder'); diff --git a/package-lock.json b/package-lock.json index 47b797d28..15420cbba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,493 +1,966 @@ { "name": "generator-jhipster-kotlin", - "version": "1.11.0", - "lockfileVersion": 1, + "version": "1.10.0", + "lockfileVersion": 2, "requires": true, - "dependencies": { - "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", - "requires": { - "@babel/highlight": "^7.8.3" + "packages": { + "": { + "name": "generator-jhipster-kotlin", + "version": "1.10.0", + "license": "Apache-2.0", + "dependencies": { + "chalk": "4.1.0", + "cheerio": "1.0.0-rc.5", + "generator-jhipster": "7.0.0", + "glob": "7.1.6", + "lodash": "4.17.21", + "prettier": "2.2.1", + "semver": "7.3.4", + "shelljs": "0.8.4", + "yeoman-environment": "3.2.0", + "yeoman-generator": "5.2.0" + }, + "bin": { + "khipster": "cli/khipster.js" + }, + "devDependencies": { + "chai": "4.3.4", + "ejs-lint": "1.1.0", + "eslint": "7.22.0", + "eslint-config-airbnb-base": "14.2.1", + "eslint-config-prettier": "8.1.0", + "eslint-plugin-import": "2.22.1", + "eslint-plugin-prettier": "3.3.1", + "fs-extra": "9.1.0", + "mocha": "8.3.2", + "yeoman-assert": "3.1.1", + "yeoman-test": "5.1.0" + }, + "engines": { + "node": ">=12.12.0", + "npm": ">=6.14.4" } }, - "@babel/helper-validator-identifier": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", - "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==" + "node_modules/@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dependencies": { + "@babel/highlight": "^7.10.4" + } }, - "@babel/highlight": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", - "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==", - "requires": { - "@babel/helper-validator-identifier": "^7.9.0", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==" + }, + "node_modules/@babel/highlight": { + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", + "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.12.11", "chalk": "^2.0.0", "js-tokens": "^4.0.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" } }, - "@mrmlnc/readdir-enhanced": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", - "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", - "requires": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" } }, - "@nodelib/fs.scandir": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", - "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.3", - "run-parallel": "^1.1.9" + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", + "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", "dependencies": { - "@nodelib/fs.stat": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", - "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", - "dev": true - } + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" } }, - "@nodelib/fs.stat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", - "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==" + "node_modules/@eslint/eslintrc": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", + "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } }, - "@nodelib/fs.walk": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", - "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.3", + "dependencies": { + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", + "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "dependencies": { + "@nodelib/fs.stat": "2.0.4", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", + "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.4", "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" } }, - "@sinonjs/commons": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.0.tgz", - "integrity": "sha512-wEj54PfsZ5jGSwMX68G8ZXFawcSglQSXqCftWX3ec8MDUzQdHgcKvw97awHbY0efQEL5iKUOAmmVtoYgmrSG4Q==", + "node_modules/@npmcli/arborist": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-2.2.9.tgz", + "integrity": "sha512-ddC/CCAEHh28XYtgSAOudchdphNXcgErdYxwsEiykc2YbRA9Z+4XjI0BdBdXvv22DvkpO7zotUSxlVTcJmdURw==", + "dependencies": { + "@npmcli/installed-package-contents": "^1.0.7", + "@npmcli/map-workspaces": "^1.0.2", + "@npmcli/metavuln-calculator": "^1.1.0", + "@npmcli/move-file": "^1.1.0", + "@npmcli/name-from-folder": "^1.0.1", + "@npmcli/node-gyp": "^1.0.1", + "@npmcli/run-script": "^1.8.2", + "bin-links": "^2.2.1", + "cacache": "^15.0.3", + "common-ancestor-path": "^1.0.1", + "json-parse-even-better-errors": "^2.3.1", + "json-stringify-nice": "^1.1.1", + "mkdirp-infer-owner": "^2.0.0", + "npm-install-checks": "^4.0.0", + "npm-package-arg": "^8.1.0", + "npm-pick-manifest": "^6.1.0", + "npm-registry-fetch": "^9.0.0", + "pacote": "^11.2.6", + "parse-conflict-json": "^1.1.1", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^1.0.1", + "read-package-json-fast": "^2.0.2", + "readdir-scoped-modules": "^1.1.0", + "semver": "^7.3.5", + "tar": "^6.1.0", + "treeverse": "^1.0.4", + "walk-up-path": "^1.0.0" + }, + "bin": { + "arborist": "bin/index.js" + } + }, + "node_modules/@npmcli/arborist/node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/ci-detect": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@npmcli/ci-detect/-/ci-detect-1.3.0.tgz", + "integrity": "sha512-oN3y7FAROHhrAt7Rr7PnTSwrHrZVRTS2ZbyxeQwSSYD0ifwM3YNgQqbaRmjcWoPyq77MjchusjJDspbzMmip1Q==" + }, + "node_modules/@npmcli/git": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-2.0.6.tgz", + "integrity": "sha512-a1MnTfeRPBaKbFY07fd+6HugY1WAkKJzdiJvlRub/9o5xz2F/JtPacZZapx5zRJUQFIzSL677vmTSxEcDMrDbg==", + "dependencies": { + "@npmcli/promise-spawn": "^1.1.0", + "lru-cache": "^6.0.0", + "mkdirp": "^1.0.3", + "npm-pick-manifest": "^6.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.2", + "unique-filename": "^1.1.1", + "which": "^2.0.2" + } + }, + "node_modules/@npmcli/installed-package-contents": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz", + "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==", + "dependencies": { + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + }, + "bin": { + "installed-package-contents": "index.js" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@npmcli/map-workspaces": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-1.0.3.tgz", + "integrity": "sha512-SdlRlOoQw4WKD4vtb/n5gUkobEABYBEOo8fRE4L8CtBkyWDSvIrReTfKvQ/Jc/LQqDaaZ5iv1iMSQzKCUr1n1A==", + "dependencies": { + "@npmcli/name-from-folder": "^1.0.1", + "glob": "^7.1.6", + "minimatch": "^3.0.4", + "read-package-json-fast": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/metavuln-calculator": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-1.1.1.tgz", + "integrity": "sha512-9xe+ZZ1iGVaUovBVFI9h3qW+UuECUzhvZPxK9RaEA2mjU26o5D0JloGYWwLYvQELJNmBdQB6rrpuN8jni6LwzQ==", + "dependencies": { + "cacache": "^15.0.5", + "pacote": "^11.1.11", + "semver": "^7.3.2" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/name-from-folder": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-1.0.1.tgz", + "integrity": "sha512-qq3oEfcLFwNfEYOQ8HLimRGKlD8WSeGEdtUa7hmzpR8Sa7haL1KVQrvgO6wqMjhWFFVjgtrh1gIxDz+P8sjUaA==" + }, + "node_modules/@npmcli/node-gyp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.2.tgz", + "integrity": "sha512-yrJUe6reVMpktcvagumoqD9r08fH1iRo01gn1u0zoCApa9lnZGEigVKUd2hzsCId4gdtkZZIVscLhNxMECKgRg==" + }, + "node_modules/@npmcli/promise-spawn": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz", + "integrity": "sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg==", + "dependencies": { + "infer-owner": "^1.0.4" + } + }, + "node_modules/@npmcli/run-script": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-1.8.4.tgz", + "integrity": "sha512-Yd9HXTtF1JGDXZw0+SOn+mWLYS0e7bHBHVC/2C8yqs4wUrs/k8rwBSinD7rfk+3WG/MFGRZKxjyoD34Pch2E/A==", + "dependencies": { + "@npmcli/node-gyp": "^1.0.2", + "@npmcli/promise-spawn": "^1.3.2", + "infer-owner": "^1.0.4", + "node-gyp": "^7.1.0", + "read-package-json-fast": "^2.0.1" + } + }, + "node_modules/@octokit/auth-token": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.5.tgz", + "integrity": "sha512-BpGYsPgJt05M7/L/5FoE1PiAbdxXFZkX/3kDYcsvd1v6UhlnE5e96dTDr0ezX/EFwciQxf3cNV0loipsURU+WA==", + "dependencies": { + "@octokit/types": "^6.0.3" + } + }, + "node_modules/@octokit/core": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.3.1.tgz", + "integrity": "sha512-Dc5NNQOYjgZU5S1goN6A/E500yXOfDUFRGQB8/2Tl16AcfvS3H9PudyOe3ZNE/MaVyHPIfC0htReHMJb1tMrvw==", + "dependencies": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.4.12", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/endpoint": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.11.tgz", + "integrity": "sha512-fUIPpx+pZyoLW4GCs3yMnlj2LfoXTWDUVPTC4V3MUEKZm48W+XYpeWSZCv+vYF1ZABUm2CqnDVf1sFtIYrj7KQ==", + "dependencies": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/endpoint/node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@octokit/graphql": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.6.1.tgz", + "integrity": "sha512-2lYlvf4YTDgZCTXTW4+OX+9WTLFtEUc6hGm4qM1nlZjzxj+arizM4aHWzBVBCxY9glh7GIs0WEuiSgbVzv8cmA==", + "dependencies": { + "@octokit/request": "^5.3.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-6.0.0.tgz", + "integrity": "sha512-CnDdK7ivHkBtJYzWzZm7gEkanA7gKH6a09Eguz7flHw//GacPJLmkHA3f3N++MJmlxD1Fl+mB7B32EEpSCwztQ==" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.13.3.tgz", + "integrity": "sha512-46lptzM9lTeSmIBt/sVP/FLSTPGx6DCzAdSX3PfeJ3mTf4h9sGC26WpaQzMEq/Z44cOcmx8VsOhO+uEgE3cjYg==", + "dependencies": { + "@octokit/types": "^6.11.0" + }, + "peerDependencies": { + "@octokit/core": ">=2" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.3.tgz", + "integrity": "sha512-4RFU4li238jMJAzLgAwkBAw+4Loile5haQMQr+uhFq27BmyJXcXSKvoQKqh0agsZEiUlW6iSv3FAgvmGkur7OQ==", + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.0.0.tgz", + "integrity": "sha512-Jc7CLNUueIshXT+HWt6T+M0sySPjF32mSFQAK7UfAg8qGeRI6OM1GSBxDLwbXjkqy2NVdnqCedJcP1nC785JYg==", + "dependencies": { + "@octokit/types": "^6.13.0", + "deprecation": "^2.3.1" + }, + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/request": { + "version": "5.4.14", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.4.14.tgz", + "integrity": "sha512-VkmtacOIQp9daSnBmDI92xNIeLuSRDOIuplp/CJomkvzt7M18NXgG044Cx/LFKLgjKt9T2tZR6AtJayba9GTSA==", + "dependencies": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.0.0", + "@octokit/types": "^6.7.1", + "deprecation": "^2.0.0", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.1", + "once": "^1.4.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/request-error": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.5.tgz", + "integrity": "sha512-T/2wcCFyM7SkXzNoyVNWjyVlUwBvW3igM3Btr/eKYiPmucXTtkxt2RBsf6gn3LTzaLSLTQtNmvg+dGsOxQrjZg==", + "dependencies": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "node_modules/@octokit/request/node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@octokit/rest": { + "version": "18.5.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.5.2.tgz", + "integrity": "sha512-Kz03XYfKS0yYdi61BkL9/aJ0pP2A/WK5vF/syhu9/kY30J8He3P68hv9GRpn8bULFx2K0A9MEErn4v3QEdbZcw==", + "dependencies": { + "@octokit/core": "^3.2.3", + "@octokit/plugin-paginate-rest": "^2.6.2", + "@octokit/plugin-request-log": "^1.0.2", + "@octokit/plugin-rest-endpoint-methods": "5.0.0" + } + }, + "node_modules/@octokit/types": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.13.0.tgz", + "integrity": "sha512-W2J9qlVIU11jMwKHUp5/rbVUeErqelCsO5vW5PKNb7wAXQVUz87Rc+imjlEvpvbH8yUb+KHmv8NEjVZdsdpyxA==", + "dependencies": { + "@octokit/openapi-types": "^6.0.0" + } + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.2.tgz", + "integrity": "sha512-sruwd86RJHdsVf/AtBoijDmUqJp3B6hF/DGC23C+JaegnDHaZyewCjoVGTdg3J0uz3Zs7NnIT05OBOmML72lQw==", "dev": true, - "requires": { + "dependencies": { "type-detect": "4.0.8" } }, - "@sinonjs/fake-timers": { + "node_modules/@sinonjs/fake-timers": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", "dev": true, - "requires": { + "dependencies": { "@sinonjs/commons": "^1.7.0" } }, - "@sinonjs/formatio": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-5.0.1.tgz", - "integrity": "sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^5.0.2" - } - }, - "@sinonjs/samsam": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.0.3.tgz", - "integrity": "sha512-QucHkc2uMJ0pFGjJUDP3F9dq5dx8QIaqISl9QgwLOh6P9yv877uONPGXh/OH/0zmM3tW1JjuJltAZV2l7zU+uQ==", + "node_modules/@sinonjs/samsam": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", + "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", "dev": true, - "requires": { + "dependencies": { "@sinonjs/commons": "^1.6.0", "lodash.get": "^4.4.2", "type-detect": "^4.0.8" } }, - "@sinonjs/text-encoding": { + "node_modules/@sinonjs/text-encoding": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "engines": { + "node": ">= 6" + } }, - "@types/concat-stream": { + "node_modules/@types/concat-stream": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.0.tgz", "integrity": "sha1-OU2+C7X+5Gs42JZzXoto7yOQ0A0=", - "requires": { + "dependencies": { "@types/node": "*" } }, - "@types/events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" - }, - "@types/form-data": { + "node_modules/@types/form-data": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz", "integrity": "sha1-yayFsqX9GENbjIXZ7LUObWyJP/g=", - "requires": { + "dependencies": { "@types/node": "*" } }, - "@types/glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", - "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", - "requires": { - "@types/events": "*", + "node_modules/@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "dependencies": { "@types/minimatch": "*", "@types/node": "*" } }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==" + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true }, - "@types/minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=" + "node_modules/@types/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==" }, - "@types/node": { - "version": "13.9.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.9.1.tgz", - "integrity": "sha512-E6M6N0blf/jiZx8Q3nb0vNaswQeEyn0XlupO+xN6DtJ6r6IT4nXrTry7zhIfYvFCl3/8Cu6WIysmUBKiqV0bqQ==" + "node_modules/@types/node": { + "version": "8.10.66", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", + "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==" }, - "@types/normalize-package-data": { + "node_modules/@types/normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==" }, - "@types/qs": { - "version": "6.9.5", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz", - "integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==" - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } + "node_modules/@types/qs": { + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.6.tgz", + "integrity": "sha512-0/HnwIfW4ki2D8L8c9GVcG5I72s9jP5GSLVF0VIXDW00kmIpA6O33G7a8n59Tmh7Nz0WUC3rSb7PTY/sdW2JzA==" }, - "acorn": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.2.0.tgz", - "integrity": "sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==", + "node_modules/@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true }, - "acorn-jsx": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", - "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", - "dev": true + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, - "acorn-node": { + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-node": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", "dev": true, - "requires": { + "dependencies": { "acorn": "^7.0.0", "acorn-walk": "^7.0.0", "xtend": "^4.0.2" } }, - "acorn-walk": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.1.1.tgz", - "integrity": "sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ==", - "dev": true + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } }, - "ajv": { - "version": "6.12.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", - "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", - "requires": { + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.1.4.tgz", + "integrity": "sha512-+V/rGa3EuU74H6wR04plBb7Ks10FbtUQgRj/FQOG7uUIEuaINI+AiqJR1k6t3SVNs7o7ZjIdus6706qqzVq8jQ==", + "dependencies": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "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" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "ansi": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.1.tgz", - "integrity": "sha1-DELU+xcWDVqa8eSEus4cZpIsGyE=" - }, - "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } }, - "ansi-escapes": { + "node_modules/ansi-escapes": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" - }, - "ansi-font": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/ansi-font/-/ansi-font-0.0.2.tgz", - "integrity": "sha1-iQMBvVhBRi/TnAt3Ca/R9SUUMzE=" + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "engines": { + "node": ">=4" + } }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + "node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "engines": { + "node": ">=8" + } }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "requires": { - "@types/color-name": "^1.1.1", + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "ansi-wrap": { + "node_modules/ansi-wrap": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "engines": { + "node": ">=0.10.0" + } }, - "anymatch": { + "node_modules/anymatch": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", "dev": true, - "requires": { + "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" } }, - "are-we-there-yet": { + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "requires": { + "dependencies": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" - }, + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "argparse": { + "node_modules/are-we-there-yet/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/are-we-there-yet/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "requires": { + "dependencies": { "sprintf-js": "~1.0.2" } }, - "arr-diff": { + "node_modules/arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "engines": { + "node": ">=0.10.0" + } }, - "arr-union": { + "node_modules/arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "engines": { + "node": ">=0.10.0" + } }, - "array-differ": { + "node_modules/array-differ": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", - "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==" + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "engines": { + "node": ">=8" + } }, - "array-includes": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz", - "integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==", + "node_modules/array-includes": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", + "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", "dev": true, - "requires": { + "dependencies": { + "call-bind": "^1.0.2", "define-properties": "^1.1.3", - "es-abstract": "^1.17.0", + "es-abstract": "^1.18.0-next.2", + "get-intrinsic": "^1.1.1", "is-string": "^1.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "array-union": { + "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "engines": { + "node": ">=8" + } }, - "array.prototype.flat": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", - "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "node_modules/array.prototype.flat": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", + "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", "dev": true, - "requires": { + "dependencies": { + "call-bind": "^1.0.0", "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" + "es-abstract": "^1.18.0-next.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "arrify": { + "node_modules/arrify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "engines": { + "node": ">=8" + } }, - "asap": { + "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" }, - "asn1": { + "node_modules/asn1": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { + "dependencies": { "safer-buffer": "~2.1.0" } }, - "assert-plus": { + "node_modules/assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "engines": { + "node": ">=0.8" + } }, - "assertion-error": { + "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true + "dev": true, + "engines": { + "node": "*" + } }, - "assign-symbols": { + "node_modules/assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "engines": { + "node": ">=0.10.0" + } }, - "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } }, - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" + "node_modules/async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dependencies": { + "lodash": "^4.17.14" + } }, - "asynckit": { + "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, - "at-least-node": { + "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true + "dev": true, + "engines": { + "node": ">= 4.0.0" + } }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + "node_modules/atomically": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz", + "integrity": "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==", + "engines": { + "node": ">=10.12.0" + } }, - "aws-sdk": { - "version": "2.706.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.706.0.tgz", - "integrity": "sha512-7GT+yrB5Wb/zOReRdv/Pzkb2Qt+hz6B/8FGMVaoysX3NryHvQUdz7EQWi5yhg9CxOjKxdw5lFwYSs69YlSp1KA==", - "requires": { + "node_modules/aws-sdk": { + "version": "2.863.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.863.0.tgz", + "integrity": "sha512-krr0047EOl9qpRdhPoyYxI7+viVUpX+t+Vjbf+alXdOE172DC+hFi8y6egIM1xVV4KkMFm0y0EykBWgA93XNNA==", + "dependencies": { "buffer": "4.9.2", "events": "1.1.1", "ieee754": "1.1.13", @@ -498,1037 +971,1129 @@ "uuid": "3.3.2", "xml2js": "0.4.19" }, - "dependencies": { - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" - } + "engines": { + "node": ">= 0.8.0" } }, - "aws-sign2": { + "node_modules/aws-sdk/node_modules/uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "engines": { + "node": "*" + } }, - "aws4": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", - "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" + "node_modules/aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, - "axios": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", - "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", - "requires": { - "follow-redirects": "1.5.10" + "node_modules/axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "dependencies": { + "follow-redirects": "^1.10.0" } }, - "balanced-match": { + "node_modules/balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "requires": { - "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" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } - } - }, - "base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + ] }, - "bcrypt-pbkdf": { + "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { + "dependencies": { "tweetnacl": "^0.14.3" } }, - "binary-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", - "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", - "dev": true + "node_modules/before-after-hook": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.0.tgz", + "integrity": "sha512-jH6rKQIfroBbhEXVmI7XmXe3ix5S/PgJqpzdDPnR8JGLHWNYLsYZ6tK5iWOF/Ra3oqEX0NobXGlzbiylIzVphQ==" }, - "binaryextensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.3.0.tgz", - "integrity": "sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg==" + "node_modules/bin-links": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-2.2.1.tgz", + "integrity": "sha512-wFzVTqavpgCCYAh8SVBdnZdiQMxTkGR+T3b14CNpBXIBe2neJWaMGAZ55XWWHELJJ89dscuq0VCBqcVaIOgCMg==", + "dependencies": { + "cmd-shim": "^4.0.1", + "mkdirp": "^1.0.3", + "npm-normalize-package-bin": "^1.0.0", + "read-cmd-shim": "^2.0.0", + "rimraf": "^3.0.0", + "write-file-atomic": "^3.0.3" + }, + "engines": { + "node": ">=10" + } }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } }, - "brace-expansion": { + "node_modules/binaryextensions": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-4.15.0.tgz", + "integrity": "sha512-MkUl3szxXolQ2scI1PM14WOT951KnaTNJ0eMKg7WzOI4kvSxyNo/Cygx4LOBNhwyINhAuSQpJW1rYD9aBSxGaw==", + "engines": { + "node": ">=0.8" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, + "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { + "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "requires": { - "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" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - } + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" } }, - "browser-stdout": { + "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "buffer": { + "node_modules/buffer": { "version": "4.9.2", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "requires": { + "dependencies": { "base64-js": "^1.0.2", "ieee754": "^1.1.4", "isarray": "^1.0.0" } }, - "buffer-from": { + "node_modules/buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "requires": { - "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" + "node_modules/builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=" + }, + "node_modules/cacache": { + "version": "15.0.6", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.6.tgz", + "integrity": "sha512-g1WYDMct/jzW+JdWEyjaX2zoBkZ6ZT9VpOyp2I/VMtDsNLffNat3kqPFfi1eDRSK9/SuKGyORDHcQMcPF8sQ/w==", + "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": "^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", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" } }, - "call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "callsites": { + "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" - }, - "camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "requires": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" + "dev": true, + "engines": { + "node": ">=6" } }, - "capture-stack-trace": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", - "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==" + "node_modules/camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "caseless": { + "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, - "chai": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "node_modules/chai": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", "dev": true, - "requires": { + "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", "deep-eql": "^3.0.1", "get-func-name": "^2.0.0", - "pathval": "^1.1.0", + "pathval": "^1.1.1", "type-detect": "^4.0.5" + }, + "engines": { + "node": ">=4" } }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "requires": { + "node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "chardet": { + "node_modules/chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" }, - "check-error": { + "node_modules/check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true + "dev": true, + "engines": { + "node": "*" + } }, - "cheerio": { - "version": "1.0.0-rc.2", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", - "integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=", - "requires": { - "css-select": "~1.2.0", - "dom-serializer": "~0.1.0", - "entities": "~1.1.1", - "htmlparser2": "^3.9.1", - "lodash": "^4.15.0", - "parse5": "^3.0.1" + "node_modules/cheerio": { + "version": "1.0.0-rc.5", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.5.tgz", + "integrity": "sha512-yoqps/VCaZgN4pfXtenwHROTp8NG6/Hlt4Jpz2FEP0ZJQ+ZUkVDd0hAPDNKhj3nakpfPt/CNs57yEtxD1bXQiw==", + "dependencies": { + "cheerio-select-tmp": "^0.1.0", + "dom-serializer": "~1.2.0", + "domhandler": "^4.0.0", + "entities": "~2.1.0", + "htmlparser2": "^6.0.0", + "parse5": "^6.0.0", + "parse5-htmlparser2-tree-adapter": "^6.0.0" + }, + "engines": { + "node": ">= 0.12" } }, - "chevrotain": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-7.0.1.tgz", - "integrity": "sha512-B/44jrdw5GAzy483LEeVSgXSX0qOYM8lUd3l5+yf6Vl6OQjEUCm2BUiYbHRCIK6xCEvCLAFe1kj8uyV6+zdaVw==", - "requires": { + "node_modules/cheerio-select-tmp": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/cheerio-select-tmp/-/cheerio-select-tmp-0.1.1.tgz", + "integrity": "sha512-YYs5JvbpU19VYJyj+F7oYrIE2BOll1/hRU7rEy/5+v9BzkSo3bK81iAeeQEMI92vRIxz677m72UmJUiVwwgjfQ==", + "deprecated": "Use cheerio-select instead", + "dependencies": { + "css-select": "^3.1.2", + "css-what": "^4.0.0", + "domelementtype": "^2.1.0", + "domhandler": "^4.0.0", + "domutils": "^2.4.4" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chevrotain": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-8.0.1.tgz", + "integrity": "sha512-nE//TMrGF7Kb7mwrGbpTspMqcVMwcUKZ7/3AEbmDPW3kD0aBVUaqWjbHDgZDEuxCG8CaSos9hMN7EKJn1TgHqw==", + "dependencies": { "regexp-to-ast": "0.5.0" } }, - "chokidar": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", - "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "node_modules/chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", "dev": true, - "requires": { + "dependencies": { "anymatch": "~3.1.1", "braces": "~3.0.2", - "fsevents": "~2.1.1", "glob-parent": "~5.1.0", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.2.0" + "readdirp": "~3.5.0" }, - "dependencies": { - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - } + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.1" } }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - } + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" } }, - "cli-cursor": { + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "requires": { + "dependencies": { "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" } }, - "cli-spinners": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.5.0.tgz", - "integrity": "sha512-PC+AmIuK04E6aeSs/pUccSujsTzBhu4HzC2dL+CfJB/Jcc2qTRbEwZQDfIUpt2Xl8BodYBEq8w4fc0kU2I9DjQ==" + "node_modules/cli-spinners": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.0.tgz", + "integrity": "sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "cli-table": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", - "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", - "requires": { + "node_modules/cli-table": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.6.tgz", + "integrity": "sha512-ZkNZbnZjKERTY5NwC2SeMeLeifSPq/pubeRoTpdr3WchLlnZg6hEgvHkK5zL7KNFdd9PmHN8lxrENUwI3cE8vQ==", + "dependencies": { "colors": "1.0.3" }, - "dependencies": { - "colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" - } + "engines": { + "node": ">= 0.2.0" } }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" + "node_modules/cli-table/node_modules/colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "engines": { + "node": ">=0.1.90" + } }, - "cliui": { + "node_modules/cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==" + }, + "node_modules/cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, - "requires": { + "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^6.2.0" - }, + } + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - } + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" } }, - "clone": { + "node_modules/clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "engines": { + "node": ">=0.8" + } }, - "clone-buffer": { + "node_modules/clone-buffer": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=" - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "engines": { + "node": ">= 0.10" } }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" + "node_modules/clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" }, - "cloneable-readable": { + "node_modules/cloneable-readable": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", - "requires": { + "dependencies": { "inherits": "^2.0.1", "process-nextick-args": "^2.0.0", "readable-stream": "^2.3.5" - }, + } + }, + "node_modules/cloneable-readable/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "code-point-at": { + "node_modules/cloneable-readable/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/cloneable-readable/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/cmd-shim": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-4.1.0.tgz", + "integrity": "sha512-lb9L7EM4I/ZRVuljLPEtUJOP+xiQVknZ4ZMpMgEp4JzNldPb27HU03hi6K1/6CoIuit/Zm/LQXySErFeXxDprw==", + "dependencies": { + "mkdirp-infer-owner": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "engines": { + "node": ">=0.10.0" } }, - "color": { + "node_modules/color": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", - "requires": { + "dependencies": { "color-convert": "^1.9.1", "color-string": "^1.5.2" - }, - "dependencies": { - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - } } }, - "color-convert": { + "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { + "dependencies": { "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "color-name": { + "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "color-string": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", - "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", - "requires": { + "node_modules/color-string": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz", + "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==", + "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, - "colornames": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz", - "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=" + "node_modules/color/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } }, - "colors": { + "node_modules/color/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "engines": { + "node": ">=0.1.90" + } }, - "colorspace": { + "node_modules/colorspace": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", - "requires": { + "dependencies": { "color": "3.0.x", "text-hex": "1.0.x" } }, - "combined-stream": { + "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { + "dependencies": { "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==" + "node_modules/commander": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.1.0.tgz", + "integrity": "sha512-pRxBna3MJe6HKnBGsDyMv8ETbptw3axEdYHoqNh7gu5oDcew8fs0xnivZGm06Ogk8zGAJ9VX+OPEr2GXEQK4dg==", + "engines": { + "node": ">= 10" + } }, - "commondir": { + "node_modules/common-ancestor-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", + "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==" + }, + "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, - "concat-map": { + "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, - "concat-stream": { + "node_modules/concat-stream": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "requires": { + "engines": [ + "node >= 0.8" + ], + "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^2.2.2", "typedarray": "^0.0.6" - }, + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "conf": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/conf/-/conf-6.2.4.tgz", - "integrity": "sha512-GjgyPRLo1qK1LR9RWAdUagqo+DP18f5HWCFk4va7GS+wpxQTOzfuKTwKOvGW2c01/YXNicAyyoyuSddmdkBzZQ==", - "requires": { - "ajv": "^6.10.2", - "debounce-fn": "^3.0.1", - "dot-prop": "^5.0.0", + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/conf": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/conf/-/conf-9.0.2.tgz", + "integrity": "sha512-rLSiilO85qHgaTBIIHQpsv8z+NnVfZq3cKuYNCXN1AOqPzced0GWZEe/A517VldRLyQYXUMyV+vszavE2jSAqw==", + "dependencies": { + "ajv": "^7.0.3", + "ajv-formats": "^1.5.1", + "atomically": "^1.7.0", + "debounce-fn": "^4.0.0", + "dot-prop": "^6.0.1", "env-paths": "^2.2.0", - "json-schema-typed": "^7.0.1", - "make-dir": "^3.0.0", - "onetime": "^5.1.0", - "pkg-up": "^3.0.1", - "semver": "^6.2.0", - "write-file-atomic": "^3.0.0" + "json-schema-typed": "^7.0.3", + "make-dir": "^3.1.0", + "onetime": "^5.1.2", + "pkg-up": "^3.1.0", + "semver": "^7.3.4" }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/conf/node_modules/ajv": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.2.4.tgz", + "integrity": "sha512-nBeQgg/ZZA3u3SYxyaDvpvDtgZ/EZPF547ARgZBrG9Bhu1vKDwAIjtIf+sDtJUKa2zOcEbmRLBRSyMraS/Oy1A==", "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "confusing-browser-globals": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz", - "integrity": "sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw==", + "node_modules/conf/node_modules/ajv-formats": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-1.6.0.tgz", + "integrity": "sha512-iio2lsjYkuTq49avg+/coyM5D3qdjyW1dkiy+I79XG3DAQFAOcGltC6eXsw6dX10OtH2S9Kyez7OkFtY0bJBBA==", + "peerDependencies": { + "ajv": "^7.0.0" + } + }, + "node_modules/conf/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz", + "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==", "dev": true }, - "contains-path": { + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "node_modules/contains-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "core-util-is": { + "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, - "create-error-class": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", - "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", - "requires": { - "capture-stack-trace": "^1.0.0" + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" } }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, + "node_modules/css-select": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-3.1.2.tgz", + "integrity": "sha512-qmss1EihSuBNWNNhHjxzxSfJoFBM/lERB/Q4EnsJQQC62R2evJDW481091oAdOr9uh46/0n4nrg0It5cAnj1RA==", "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } + "boolbase": "^1.0.0", + "css-what": "^4.0.0", + "domhandler": "^4.0.0", + "domutils": "^2.4.3", + "nth-check": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "css-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", - "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", - "requires": { - "boolbase": "~1.0.0", - "css-what": "2.1", - "domutils": "1.5.1", - "nth-check": "~1.0.1" + "node_modules/css-what": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-4.0.0.tgz", + "integrity": "sha512-teijzG7kwYfNVsUh2H/YN62xW3KK9YhXEgSlbxMlcyjPNvdKJqFx5lrwlJgoFP1ZHlB89iGDlo/JyshKeRhv5A==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "css-what": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", - "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" + "node_modules/cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" }, - "dargs": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-6.1.0.tgz", - "integrity": "sha512-5dVBvpBLBnPwSsYXqfybFyehMmC/EenKEcf23AhCTgTf48JFBbmJKqoZBsERDnjL0FyiVTYWdFsRfTLHxLyKdQ==" + "node_modules/dargs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "engines": { + "node": ">=8" + } }, - "dashdash": { + "node_modules/dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { + "dependencies": { "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" } }, - "dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==" - }, - "debounce-fn": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/debounce-fn/-/debounce-fn-3.0.1.tgz", - "integrity": "sha512-aBoJh5AhpqlRoHZjHmOzZlRx+wz2xVwGL9rjs+Kj0EWUrL4/h4K7OD176thl2Tdoqui/AaA4xhHrNArGLAaI3Q==", - "requires": { - "mimic-fn": "^2.1.0" + "node_modules/dateformat": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.5.1.tgz", + "integrity": "sha512-OD0TZ+B7yP7ZgpJf5K2DIbj3FZvFvxgFUuaqA/V5zTjAtAAXZ1E8bktHxmAGs4x5b7PflqA9LeQ84Og7wYtF7Q==", + "engines": { + "node": "*" } }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" + "node_modules/debounce-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/debounce-fn/-/debounce-fn-4.0.0.tgz", + "integrity": "sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==", + "dependencies": { + "mimic-fn": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "decamelize-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", - "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", - "requires": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, + "node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dependencies": { - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true } } }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + "node_modules/debuglog": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", + "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=", + "engines": { + "node": "*" + } }, - "deep-eql": { + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", "dev": true, - "requires": { + "dependencies": { "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=0.12" } }, - "deep-extend": { + "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } }, - "deep-is": { + "node_modules/deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "defaults": { + "node_modules/defaults": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "requires": { + "dependencies": { "clone": "^1.0.2" } }, - "define-properties": { + "node_modules/define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "dev": true, - "requires": { + "dependencies": { "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "engines": { + "node": ">= 0.4" } }, - "delayed-stream": { + "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } }, - "delegates": { + "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, - "diagnostics": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", - "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", - "requires": { - "colorspace": "1.1.x", - "enabled": "1.0.x", - "kuler": "1.0.x" + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" } }, - "didyoumean": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.1.tgz", - "integrity": "sha1-6S7f2tplN9SE1zwBcv0eugxJdv8=" + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" + "node_modules/detect-indent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.0.0.tgz", + "integrity": "sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==", + "engines": { + "node": ">=8" + } }, - "dir-glob": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", - "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", - "requires": { - "arrify": "^1.0.1", - "path-type": "^3.0.0" - }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/dezalgo": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", + "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", "dependencies": { - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" - } + "asap": "^2.0.0", + "wrappy": "1" } }, - "doctrine": { - "version": "3.0.0", + "node_modules/didyoumean": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.1.tgz", + "integrity": "sha1-6S7f2tplN9SE1zwBcv0eugxJdv8=" + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, - "requires": { + "dependencies": { "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" } }, - "dom-serializer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", - "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", - "requires": { - "domelementtype": "^1.3.0", - "entities": "^1.1.1" + "node_modules/dom-serializer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.2.0.tgz", + "integrity": "sha512-n6kZFH/KlCrqs/1GHMOd5i2fd/beQHuehKdWvNNffbGHTr/almdhuVvTVFb3V7fglz+nC50fFusu3lY33h12pA==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + "node_modules/domelementtype": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz", + "integrity": "sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] }, - "domhandler": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", - "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", - "requires": { - "domelementtype": "1" + "node_modules/domhandler": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.0.0.tgz", + "integrity": "sha512-KPTbnGQ1JeEMQyO1iYXoagsI6so/C96HZiFyByU3T6iAzpXn8EGEvct6unm1ZGoed8ByO2oirxgwxBmqKF9haA==", + "dependencies": { + "domelementtype": "^2.1.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "domutils": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", - "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", - "requires": { - "dom-serializer": "0", - "domelementtype": "1" + "node_modules/domutils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.5.0.tgz", + "integrity": "sha512-Ho16rzNMOFk2fPwChGh3D2D9OEHAfG19HgmRR2l+WLSsIstNsAYBzePH412bL0y5T44ejABIVfTHQ8nqi/tBCg==", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "requires": { + "node_modules/dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "dependencies": { "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "download-stats": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/download-stats/-/download-stats-0.3.4.tgz", - "integrity": "sha512-ic2BigbyUWx7/CBbsfGjf71zUNZB4edBGC3oRliSzsoNmvyVx3Ycfp1w3vp2Y78Ee0eIIkjIEO5KzW0zThDGaA==", - "requires": { - "JSONStream": "^1.2.1", - "lazy-cache": "^2.0.1", - "moment": "^2.15.1" - } - }, - "drange": { + "node_modules/drange": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/drange/-/drange-1.1.1.tgz", - "integrity": "sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA==" - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + "integrity": "sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA==", + "engines": { + "node": ">=4" + } }, - "ecc-jsbn": { + "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { + "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" } }, - "editions": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/editions/-/editions-2.3.1.tgz", - "integrity": "sha512-ptGvkwTvGdGfC0hfhKg0MT+TRLRKGtUiWGBInxOm5pz7ssADezahjCUaYuZ8Dr+C05FW0AECIIPt4WBxVINEhA==", - "requires": { - "errlop": "^2.0.0", - "semver": "^6.3.0" - }, + "node_modules/editions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/editions/-/editions-6.1.0.tgz", + "integrity": "sha512-h6nWEyIocfgho9J3sTSuhU/WoFOu1hTX75rPBebNrbF38Y9QFDjCDizYXdikHTySW7Y3mSxli8bpDz9RAtc7rA==", "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } + "errlop": "^4.0.0", + "version-range": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" } }, - "ejs": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.2.tgz", - "integrity": "sha512-zFuywxrAWtX5Mk2KAuoJNkXXbfezpNA0v7i+YC971QORguPekpjpAgeOv99YWSdKXwj7JxI2QAWDeDkE8fWtXw==", - "requires": { - "jake": "^10.6.1" + "node_modules/ejs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.0.1.tgz", + "integrity": "sha512-cuIMtJwxvzumSAkqaaoGY/L6Fc/t6YvoP9/VIaK0V/CyqKLEQ8sqODmYfy/cjXEdZ9+OOL8TecbJu+1RsofGDw==", + "dev": true, + "hasInstallScript": true, + "engines": { + "node": ">=0.10.0" } }, - "ejs-include-regex": { + "node_modules/ejs-include-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/ejs-include-regex/-/ejs-include-regex-1.0.0.tgz", "integrity": "sha1-4vcVdcv9VRrIALJHTB9io45wCTo=", "dev": true }, - "ejs-lint": { + "node_modules/ejs-lint": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/ejs-lint/-/ejs-lint-1.1.0.tgz", "integrity": "sha512-SnOxzUtJug5C92wtFTZ+Zyb+eoqOlN+WyqDk6HDSXgY5FseDgm8MhZ/r70nkzrh0AMPpifzebep3gGILzAlQNg==", "dev": true, - "requires": { + "dependencies": { "chalk": "^4.0.0", "ejs": "3.0.1", "ejs-include-regex": "^1.0.0", @@ -1538,1371 +2103,8624 @@ "syntax-error": "^1.1.6", "yargs": "^15.0.0" }, - "dependencies": { - "@nodelib/fs.stat": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", - "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", - "dev": true - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "ejs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.0.1.tgz", - "integrity": "sha512-cuIMtJwxvzumSAkqaaoGY/L6Fc/t6YvoP9/VIaK0V/CyqKLEQ8sqODmYfy/cjXEdZ9+OOL8TecbJu+1RsofGDw==", - "dev": true - }, - "fast-glob": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.2.tgz", - "integrity": "sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A==", - "dev": true, - "requires": { - "@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" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "globby": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.0.tgz", - "integrity": "sha512-iuehFnR3xu5wBBtm4xi0dMe92Ob87ufyu/dHwpDYfbcpYpIbrO5OnS8M1vWvrBhSGEJ3/Ecj7gnX76P8YxpPEg==", - "dev": true, - "requires": { - "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" - } - }, - "ignore": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.6.tgz", - "integrity": "sha512-cgXgkypZBcCnOgSihyeqbo6gjIaIyDqPQB7Ra4vhE9m6kigdGoQDMHjviFhRZo3IMlRy6yElosoviMs5YxZXUA==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - } + "bin": { + "ejslint": "cli.js" } }, - "emoji-regex": { + "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, - "enabled": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", - "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", - "requires": { - "env-variable": "0.0.x" + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" } }, - "end-of-stream": { + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "requires": { + "dependencies": { "once": "^1.4.0" } }, - "entities": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", - "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } }, - "env-paths": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", - "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==" + "node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } }, - "env-variable": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.6.tgz", - "integrity": "sha512-bHz59NlBbtS0NhftmR8+ExBEekE7br0e01jw+kk0NDro7TtZzBYZ5ScGPs3OmwnpyfHTHOtr1Y6uedCdrIldtg==" + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "engines": { + "node": ">=6" + } }, - "errlop": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/errlop/-/errlop-2.2.0.tgz", - "integrity": "sha512-e64Qj9+4aZzjzzFpZC7p5kmm/ccCrbLhAJplhsDXQFs87XTsXwOpH4s1Io2s90Tau/8r2j9f4l/thhDevRjzxw==" + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" }, - "error": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/error/-/error-7.2.1.tgz", - "integrity": "sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==", - "requires": { - "string-template": "~0.2.1" + "node_modules/errlop": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/errlop/-/errlop-4.1.0.tgz", + "integrity": "sha512-vul6gGBuVt0M2TPi1/WrcL86+Hb3Q2Tpu3TME3sbVhZrYf7J1ZMHCodI25RQKCVurh56qTfvgM0p3w5cT4reSQ==", + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" } }, - "error-ex": { + "node_modules/error": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/error/-/error-10.4.0.tgz", + "integrity": "sha512-YxIFEJuhgcICugOUvRx5th0UM+ActZ9sjY0QJmeVwsQdvosZ7kYzc9QqS0Da3R5iUmgU5meGIxh0xBeZpMVeLw==" + }, + "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "requires": { - "is-arrayish": "^0.2.1" - }, "dependencies": { - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" - } + "is-arrayish": "^0.2.1" } }, - "es-abstract": { - "version": "1.17.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", - "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "node_modules/es-abstract": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", + "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", "dev": true, - "requires": { + "dependencies": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.2", + "is-string": "^1.0.5", + "object-inspect": "^1.9.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "es-to-primitive": { + "node_modules/es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, - "requires": { + "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "escape-string-regexp": { + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "engines": { + "node": ">=0.8.0" + } }, - "eslint": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", - "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "node_modules/eslint": { + "version": "7.22.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.22.0.tgz", + "integrity": "sha512-3VawOtjSJUQiiqac8MQc+w457iGLfuNGLFn8JmF051tTKbh5/x/0vlcEj8OgDCaw7Ysa2Jn8paGshV7x2abKXg==", "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", + "dependencies": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.0", "ajv": "^6.10.0", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", "debug": "^4.0.1", "doctrine": "^3.0.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^1.4.3", - "eslint-visitor-keys": "^1.1.0", - "espree": "^6.1.2", - "esquery": "^1.0.1", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", + "file-entry-cache": "^6.0.1", "functional-red-black-tree": "^1.0.1", "glob-parent": "^5.0.0", - "globals": "^12.1.0", + "globals": "^13.6.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^7.0.0", "is-glob": "^4.0.0", "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.14", + "levn": "^0.4.1", + "lodash": "^4.17.21", "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", - "optionator": "^0.8.3", + "optionator": "^0.9.1", "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^6.1.2", - "strip-ansi": "^5.2.0", - "strip-json-comments": "^3.0.1", - "table": "^5.2.3", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.4", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-airbnb-base": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz", + "integrity": "sha512-GOrQyDtVEc1Xy20U7vsB2yAoB4nBlfH5HZJeatRXHleO+OS5Ot+MWij4Dpltw4/DyIkqUfqz1epfhVR5XWWQPA==", + "dev": true, "dependencies": { - "ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", - "dev": true, - "requires": { - "type-fest": "^0.11.0" - } - }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "inquirer": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", - "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^3.0.0", - "cli-cursor": "^3.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.15", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.5.3", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - } - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", - "dev": true - } + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.2" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "eslint": "^5.16.0 || ^6.8.0 || ^7.2.0", + "eslint-plugin-import": "^2.22.1" } }, - "eslint-config-airbnb-base": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.1.0.tgz", - "integrity": "sha512-+XCcfGyCnbzOnktDVhwsCAx+9DmrzEmuwxyHUJpw+kqBVT744OUBrB09khgFKlK1lshVww6qXGsYPZpavoNjJw==", + "node_modules/eslint-config-prettier": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.1.0.tgz", + "integrity": "sha512-oKMhGv3ihGbCIimCAjqkdzx2Q+jthoqnXSP+d86M9tptwugycmTFdVR4IpLgq2c4SHifbwO90z2fQ8/Aio73yw==", "dev": true, - "requires": { - "confusing-browser-globals": "^1.0.9", - "object.assign": "^4.1.0", - "object.entries": "^1.1.1" + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" } }, - "eslint-config-prettier": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz", - "integrity": "sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA==", + "node_modules/eslint-import-resolver-node": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", "dev": true, - "requires": { - "get-stdin": "^6.0.0" + "dependencies": { + "debug": "^2.6.9", + "resolve": "^1.13.1" } }, - "eslint-import-resolver-node": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz", - "integrity": "sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==", + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, - "requires": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - }, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } + "ms": "2.0.0" } }, - "eslint-module-utils": { + "node_modules/eslint-import-resolver-node/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/eslint-module-utils": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", "dev": true, - "requires": { + "dependencies": { "debug": "^2.6.9", "pkg-dir": "^2.0.0" }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } + "ms": "2.0.0" } }, - "eslint-plugin-import": { - "version": "2.20.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.2.tgz", - "integrity": "sha512-FObidqpXrR8OnCh4iNsxy+WACztJLXAHBO5hK79T1Hc77PgQZkyDGA5Ag9xAvRpglvLNxhH/zSmZ70/pZ31dHg==", + "node_modules/eslint-module-utils/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/eslint-plugin-import": { + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", + "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", "dev": true, - "requires": { - "array-includes": "^3.0.3", - "array.prototype.flat": "^1.2.1", + "dependencies": { + "array-includes": "^3.1.1", + "array.prototype.flat": "^1.2.3", "contains-path": "^0.1.0", "debug": "^2.6.9", "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.2", - "eslint-module-utils": "^2.4.1", + "eslint-import-resolver-node": "^0.3.4", + "eslint-module-utils": "^2.6.0", "has": "^1.0.3", "minimatch": "^3.0.4", - "object.values": "^1.1.0", + "object.values": "^1.1.1", "read-pkg-up": "^2.0.0", - "resolve": "^1.12.0" + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" + }, + "engines": { + "node": ">=4" }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } - } + "ms": "2.0.0" } }, - "eslint-plugin-prettier": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.3.tgz", - "integrity": "sha512-+HG5jmu/dN3ZV3T6eCD7a4BlAySdN7mLIbJYo0z1cFQuI+r2DiTJEFeF68ots93PsnrMxbzIZ2S/ieX+mkrBeQ==", + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", "dev": true, - "requires": { + "dependencies": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/eslint-plugin-prettier": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz", + "integrity": "sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ==", + "dev": true, + "dependencies": { "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "eslint": ">=5.0.0", + "prettier": ">=1.13.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } } }, - "eslint-scope": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", - "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, - "requires": { - "esrecurse": "^4.1.0", + "dependencies": { + "esrecurse": "^4.3.0", "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" } }, - "eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "node_modules/eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "dev": true, - "requires": { + "dependencies": { "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" } }, - "eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", - "dev": true + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } }, - "espree": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", - "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", + "node_modules/eslint-visitor-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", "dev": true, - "requires": { - "acorn": "^7.1.1", - "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.1.0" + "engines": { + "node": ">=10" } }, - "esprima": { + "node_modules/espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } }, - "esquery": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", - "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", "dev": true, - "requires": { + "dependencies": { "estraverse": "^5.1.0" }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, "dependencies": { - "estraverse": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz", - "integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==", - "dev": true - } + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" } }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", "dev": true, - "requires": { - "estraverse": "^4.1.0" + "engines": { + "node": ">=4.0" } }, - "estraverse": { + "node_modules/estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true + "dev": true, + "engines": { + "node": ">=4.0" + } }, - "esutils": { + "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "events": { + "node_modules/events": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.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" + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "engines": { + "node": ">=0.4.x" } }, - "exit-hook": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=" - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "requires": { - "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" - }, + "node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - } + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "extend": { + "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, - "extend-shallow": { + "node_modules/extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "requires": { + "dependencies": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "external-editor": { + "node_modules/external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "requires": { + "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", "tmp": "^0.0.33" - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "requires": { - "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" }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - } + "engines": { + "node": ">=4" } }, - "extsprintf": { + "node_modules/extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "engines": [ + "node >=0.6.0" + ] }, - "faker": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/faker/-/faker-4.1.0.tgz", - "integrity": "sha1-HkW7vsxndLPBlfrSg1EJxtdIzD8=" + "node_modules/faker": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/faker/-/faker-5.4.0.tgz", + "integrity": "sha512-Y9n/Ky/xZx/Bj8DePvXspUYRtHl/rGQytoIT5LaxmNwSe3wWyOeOXb3lT6Dpipq240PVpeFaGKzScz/5fvff2g==" }, - "fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, - "fast-diff": { + "node_modules/fast-diff": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", "dev": true }, - "fast-glob": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", - "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", - "requires": { - "@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" + "node_modules/fast-glob": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", + "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "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" + }, + "engines": { + "node": ">=8" } }, - "fast-json-stable-stringify": { + "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, - "fast-levenshtein": { + "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, - "fast-safe-stringify": { + "node_modules/fast-safe-stringify": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" }, - "fastq": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.8.0.tgz", - "integrity": "sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q==", - "dev": true, - "requires": { + "node_modules/fastq": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", + "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", + "dependencies": { "reusify": "^1.0.4" } }, - "fecha": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", - "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==" + "node_modules/fecha": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz", + "integrity": "sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg==" }, - "figures": { + "node_modules/figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "requires": { + "dependencies": { "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" } }, - "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, - "requires": { - "flat-cache": "^2.0.1" + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" } }, - "filelist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz", - "integrity": "sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ==", - "requires": { + "node_modules/filelist": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz", + "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==", + "dependencies": { "minimatch": "^3.0.4" } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - } + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "requires": { - "locate-path": "^3.0.0" + "node_modules/find-yarn-workspace-root2": { + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root2/-/find-yarn-workspace-root2-1.2.16.tgz", + "integrity": "sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==", + "dependencies": { + "micromatch": "^4.0.2", + "pkg-dir": "^4.2.0" } }, - "first-chunk-stream": { + "node_modules/find-yarn-workspace-root2/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-yarn-workspace-root2/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-yarn-workspace-root2/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-yarn-workspace-root2/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-yarn-workspace-root2/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/first-chunk-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", - "requires": { + "dependencies": { "readable-stream": "^2.0.2" }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/first-chunk-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - } + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "flat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", - "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" - }, + "node_modules/first-chunk-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/first-chunk-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dependencies": { - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", - "dev": true - } + "safe-buffer": "~5.1.0" } }, - "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dev": true, - "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - }, "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" } }, - "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "node_modules/flatted": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", + "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", "dev": true }, - "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "requires": { - "debug": "=3.1.0" + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, + "node_modules/follow-redirects": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz", + "integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } } }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" - }, - "forever-agent": { + "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "engines": { + "node": "*" + } }, - "form-data": { + "node_modules/form-data": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { + "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" } }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "requires": { - "map-cache": "^0.2.2" - } - }, - "fs-extra": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz", - "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==", + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, - "requires": { + "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", - "universalify": "^1.0.0" + "universalify": "^2.0.0" }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dependencies": { - "jsonfile": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", - "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^1.0.0" - } - }, - "universalify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", - "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==", - "dev": true - } + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" } }, - "fs.realpath": { + "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, - "optional": true + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } }, - "function-bind": { + "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, - "functional-red-black-tree": { + "node_modules/functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, - "gauge": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-1.2.7.tgz", - "integrity": "sha1-6c7FSD09TuDvRLYKfZnkk14TbZM=", - "requires": { - "ansi": "^0.3.0", + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", "has-unicode": "^2.0.0", - "lodash.pad": "^4.1.0", - "lodash.padend": "^4.1.0", - "lodash.padstart": "^4.1.0" + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" } }, - "generator-jhipster": { - "version": "6.10.5", - "resolved": "https://registry.npmjs.org/generator-jhipster/-/generator-jhipster-6.10.5.tgz", - "integrity": "sha512-5NulSuou7sghjggc1rQuWWWigfJAdlzB0iMB92WQd90nXBC9ZopVFvgkjfLxWpKEgidFPjrwhrt5iWjoA+yo5A==", - "requires": { - "aws-sdk": "2.706.0", - "axios": "0.19.2", + "node_modules/gauge/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/generator-jhipster": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/generator-jhipster/-/generator-jhipster-7.0.0.tgz", + "integrity": "sha512-19u1ESpKl7D/SNCSsvEysS3g7zKOR40j79t0zyL1Oni1jCUsStlFFMXbJ8Bv2qQTN/uegKVsEpllbluF1JlxQQ==", + "dependencies": { + "aws-sdk": "2.863.0", + "axios": "0.21.1", "chalk": "4.1.0", - "commander": "5.1.0", - "conf": "6.2.4", + "chevrotain": "8.0.1", + "commander": "7.1.0", + "conf": "9.0.2", "didyoumean": "1.2.1", - "ejs": "3.1.3", - "faker": "4.1.0", + "ejs": "3.1.6", + "faker": "5.4.0", + "find-up": "5.0.0", "glob": "7.1.6", "gulp-filter": "6.0.0", "insight": "0.10.3", - "jhipster-core": "7.3.4", - "js-object-pretty-print": "0.3.0", - "js-yaml": "3.14.0", - "lodash": "4.17.15", - "meow": "6.1.0", - "mkdirp": "1.0.4", + "js-yaml": "4.0.0", + "lodash": "4.17.21", + "minimatch": "3.0.4", "normalize-path": "3.0.0", - "ora": "4.0.4", + "ora": "5.3.0", "os-locale": "5.0.0", "parse-gitignore": "1.0.1", "pluralize": "8.0.0", - "prettier": "2.1.2", - "prettier-plugin-java": "0.8.2", + "prettier": "2.2.1", + "prettier-plugin-java": "1.0.2", + "prettier-plugin-packagejson": "2.2.10", "progress": "2.0.3", "randexp": "0.5.3", - "semver": "7.3.2", + "semver": "7.3.4", "shelljs": "0.8.4", - "tabtab": "2.2.2", - "test": "^0.6.0", "then-request": "6.0.2", - "through2": "3.0.2", - "uuid": "7.0.3", - "yeoman-environment": "2.10.3", - "yeoman-generator": "4.11.0" + "through2": "4.0.2", + "uuid": "8.3.2", + "winston": "3.3.3", + "yeoman-environment": "3.2.0", + "yeoman-generator": "5.2.0" }, + "bin": { + "jhipster": "cli/jhipster.js" + }, + "engines": { + "node": ">=12.12.0", + "npm": ">=6.14.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/generator-jhipster" + } + }, + "node_modules/generator-jhipster/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/generator-jhipster/node_modules/ejs": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz", + "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==", "dependencies": { - "ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", - "requires": { - "type-fest": "^0.11.0" - } - }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "requires": { - "array-uniq": "^1.0.1" - } - }, - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "requires": { - "lodash": "^4.17.14" - } - }, - "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "requires": { - "restore-cursor": "^3.1.0" + "jake": "^10.6.1" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/generator-jhipster/node_modules/js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/git-hooks-list": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-1.0.3.tgz", + "integrity": "sha512-Y7wLWcrLUXwk2noSka166byGCvhMtDRpgHdzCno1UQv/n/Hegp++a2xBWJL1lJarnKD3SWaljD+0z1ztqxuKyQ==", + "funding": { + "url": "https://github.com/fisker/git-hooks-list?sponsor=1" + } + }, + "node_modules/github-username": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/github-username/-/github-username-6.0.0.tgz", + "integrity": "sha512-7TTrRjxblSI5l6adk9zd+cV5d6i1OrJSo3Vr9xdGqFLBQo0mz5P9eIfKCDJ7eekVGGFLbce0qbPSnktXV2BjDQ==", + "dependencies": { + "@octokit/rest": "^18.0.6" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globals": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.7.0.tgz", + "integrity": "sha512-Aipsz6ZKRxa/xQkZhNg0qIWXT6x6rD46f6x/PCnBomlttdIyAPak4YD9jTmKpZ72uROSMU87qJtcgpgHaVchiA==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", + "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby/node_modules/ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" + }, + "node_modules/grouped-queue": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grouped-queue/-/grouped-queue-2.0.0.tgz", + "integrity": "sha512-/PiFUa7WIsl48dUeCvhIHnwNmAAzlI/eHoJl0vu3nsFA366JleY7Ff8EVTplZu5kO0MIdZjKTTnzItL61ahbnw==", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/gulp-filter": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-6.0.0.tgz", + "integrity": "sha512-veQFW93kf6jBdWdF/RxMEIlDK2mkjHyPftM381DID2C9ImTVngwYpyyThxm4/EpgcNOT37BLefzMOjEKbyYg0Q==", + "dependencies": { + "multimatch": "^4.0.0", + "plugin-error": "^1.0.1", + "streamfilter": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" + }, + "node_modules/htmlparser2": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.0.1.tgz", + "integrity": "sha512-GDKPd+vk4jvSuvCbyuzx/unmXkk090Azec7LovXP8as1Hn8q9p3hbjmDGbUqqhknw0ajwit6LiiWqfiTUPMK7w==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.4.4", + "entities": "^2.0.0" + } + }, + "node_modules/http-basic": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz", + "integrity": "sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==", + "dependencies": { + "caseless": "^0.12.0", + "concat-stream": "^1.6.2", + "http-response-object": "^3.0.1", + "parse-cache-control": "^1.0.1" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-response-object": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz", + "integrity": "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==", + "dependencies": { + "@types/node": "^10.0.3" + } + }, + "node_modules/http-response-object/node_modules/@types/node": { + "version": "10.17.56", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.56.tgz", + "integrity": "sha512-LuAa6t1t0Bfw4CuSR0UITsm1hP17YL+u82kfHGrHUWdhlBtH7sa7jGY5z7glGaIj/WDYDkRtgGd+KCjCzxBW1w==" + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "dependencies": { + "minimatch": "^3.0.4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dependencies": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/inquirer/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/inquirer/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/inquirer/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "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" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/inquirer/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/inquirer/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/inquirer/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "engines": { + "node": ">=4" + } + }, + "node_modules/inquirer/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/inquirer/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/insight": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/insight/-/insight-0.10.3.tgz", + "integrity": "sha512-YOncxSN6Omh+1Oqxt+OJAvJVMDKw7l6IEG0wT2cTMGxjsTcroOGW4IR926QDzxg/uZHcFZ2cZbckDWdZhc2pZw==", + "dependencies": { + "async": "^2.6.2", + "chalk": "^2.4.2", + "conf": "^1.4.0", + "inquirer": "^6.3.1", + "lodash.debounce": "^4.0.8", + "os-name": "^3.1.0", + "request": "^2.88.0", + "tough-cookie": "^3.0.1", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/insight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/insight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "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" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/insight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/insight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/insight/node_modules/conf": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/conf/-/conf-1.4.0.tgz", + "integrity": "sha512-bzlVWS2THbMetHqXKB8ypsXN4DQ/1qopGwNJi1eYbpwesJcd86FBjFciCQX/YwAhp9bM7NVnPFqZ5LpV7gP0Dg==", + "dependencies": { + "dot-prop": "^4.1.0", + "env-paths": "^1.0.0", + "make-dir": "^1.0.0", + "pkg-up": "^2.0.0", + "write-file-atomic": "^2.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/insight/node_modules/dot-prop": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.1.tgz", + "integrity": "sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ==", + "dependencies": { + "is-obj": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/insight/node_modules/env-paths": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-1.0.0.tgz", + "integrity": "sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=", + "engines": { + "node": ">=4" + } + }, + "node_modules/insight/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/insight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "engines": { + "node": ">=4" + } + }, + "node_modules/insight/node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/insight/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/insight/node_modules/make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/insight/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/insight/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/insight/node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "engines": { + "node": ">=4" + } + }, + "node_modules/insight/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "engines": { + "node": ">=4" + } + }, + "node_modules/insight/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "engines": { + "node": ">=4" + } + }, + "node_modules/insight/node_modules/pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", + "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", + "dependencies": { + "find-up": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/insight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/insight/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/insight/node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/invert-kv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-3.0.1.tgz", + "integrity": "sha512-CYdFeFexxhv/Bcny+Q0BfOV+ltRlJcd4BBZBYFX/O0u4npJrgZtIcjokegtiSMAvlMTJ+Koq0GBCc//3bueQxw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sindresorhus/invert-kv?sponsor=1" + } + }, + "node_modules/ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, + "node_modules/ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "node_modules/is-bigint": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", + "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", + "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=" + }, + "node_modules/is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", + "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-scoped": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-scoped/-/is-scoped-2.1.0.tgz", + "integrity": "sha512-Cv4OpPTHAK9kHYzkzCrof3VJh7H/PrG2MBUMvvJebaaUMbqhm0YAtXnvh0I3Hnj2tMZWwrRROWLSgfJrKqWmlQ==", + "dependencies": { + "scoped-regex": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/isbinaryfile": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.6.tgz", + "integrity": "sha512-ORrEy+SNVqUhrCaal4hA4fBzhggQQ+BaLntyPOdoEiwlKZW9BZiJXjg3RMiruE4tPEI3pyVPpySHQF/dKWperg==", + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "node_modules/istextorbinary": { + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-5.12.0.tgz", + "integrity": "sha512-wLDRWD7qpNTYubk04+q3en1+XZGS4vYWK0+SxNSXJLaITMMEK+J3o/TlOMyULeH1qozVZ9uUkKcyMA8odyxz8w==", + "dependencies": { + "binaryextensions": "^4.15.0", + "editions": "^6.1.0", + "textextensions": "^5.11.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/jake": { + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", + "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", + "dependencies": { + "async": "0.9.x", + "chalk": "^2.4.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jake/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jake/node_modules/async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" + }, + "node_modules/jake/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "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" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jake/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/jake/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "node_modules/jake/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "engines": { + "node": ">=4" + } + }, + "node_modules/jake/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/java-parser": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/java-parser/-/java-parser-1.0.2.tgz", + "integrity": "sha512-lBXc+F62ds2W83eH5MwGnzuWdb6kgGBV0x0R7w0B4JKGDrJzolMUEhRMzzzlIX68HvRU7XtfPon22YaB+dVg+A==", + "dependencies": { + "chevrotain": "6.5.0", + "lodash": "4.17.21" + } + }, + "node_modules/java-parser/node_modules/chevrotain": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-6.5.0.tgz", + "integrity": "sha512-BwqQ/AgmKJ8jcMEjaSnfMybnKMgGTrtDKowfTP3pX4jwVy0kNjRsT/AP6h+wC3+3NC+X8X15VWBnTCQlX+wQFg==", + "dependencies": { + "regexp-to-ast": "0.4.0" + } + }, + "node_modules/java-parser/node_modules/regexp-to-ast": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.4.0.tgz", + "integrity": "sha512-4qf/7IsIKfSNHQXSwial1IFmfM1Cc/whNBQqRwe0V2stPe7KmN1U0tWQiIx6JiirgSrisjE0eECdNf7Tav1Ntw==" + }, + "node_modules/jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-schema-typed": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-7.0.3.tgz", + "integrity": "sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "node_modules/json-stringify-nice": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.2.tgz", + "integrity": "sha512-mc0EsmCq4Ru6jTdKtKvzKzGJPa7eUHXe5/WAprXwyYYR1iY2qTcvaw3QBkPKGfJYvRr5vXoaIvMtttM+/f1xOA==", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "node_modules/just-diff": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-3.0.2.tgz", + "integrity": "sha512-+EiNvacECnZbszZa5IMjzrJ3dy2HKMXyGaNYWBnXy+iWW+437jIvQUrWaM9M+XI/6gOH8EjqvhGUOSh7ETekyg==" + }, + "node_modules/just-diff-apply": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-3.0.0.tgz", + "integrity": "sha512-K2MLc+ZC2DVxX4V61bIKPeMUUfj1YYZ3h0myhchDXOW1cKoPZMnjIoNCqv9bF2n5Oob1PFxuR2gVJxkxz4e58w==" + }, + "node_modules/just-extend": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", + "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==", + "dev": true + }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + }, + "node_modules/lcid": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-3.1.1.tgz", + "integrity": "sha512-M6T051+5QCGLBQb8id3hdvIW8+zeFV2FyBGFS9IEK5H9Wt4MueD4bW1eWikpHgZp+5xR3l5c8pZUkQsIA0BFZg==", + "dependencies": { + "invert-kv": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" + }, + "node_modules/load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-yaml-file": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/load-yaml-file/-/load-yaml-file-0.2.0.tgz", + "integrity": "sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==", + "dependencies": { + "graceful-fs": "^4.1.5", + "js-yaml": "^3.13.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/load-yaml-file/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/logform": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz", + "integrity": "sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==", + "dependencies": { + "colors": "^1.2.1", + "fast-safe-stringify": "^2.0.4", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "triple-beam": "^1.3.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/macos-release": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.4.1.tgz", + "integrity": "sha512-H/QHeBIN1fIGJX517pvK8IEK53yQOW7YcEI55oYtgjDdoCQQz7eJS94qt5kNrscReEyuD/JcdFCm2XBEcGOITg==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-fetch-happen": { + "version": "8.0.14", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-8.0.14.tgz", + "integrity": "sha512-EsS89h6l4vbfJEtBZnENTOFk8mCRpY5ru36Xe5bcX1KYIli2mkSHqoFsp5O1wMDvTJJzxe/4THpCTtygjeeGWQ==", + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.0.5", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^5.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dependencies": { + "p-defer": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/mem": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-5.1.1.tgz", + "integrity": "sha512-qvwipnozMohxLXG1pOqoLiZKNkC4r4qqRucSoDwXowsNGDSULiqFTRUF05vcZWnwJSG22qTsynQhxbaMtnX9gw==", + "dependencies": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^2.1.0", + "p-is-promise": "^2.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mem-fs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-1.2.0.tgz", + "integrity": "sha512-b8g0jWKdl8pM0LqAPdK9i8ERL7nYrzmJfRhxMiWH2uYdfYnb7uXnmwVb0ZGe7xyEl4lj+nLIU3yf4zPUT+XsVQ==", + "dependencies": { + "through2": "^3.0.0", + "vinyl": "^2.0.1", + "vinyl-file": "^3.0.0" + } + }, + "node_modules/mem-fs-editor": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-8.0.0.tgz", + "integrity": "sha512-0+6Zp44EmPpF01MZOlY0kt7JTndjdvALo4jA7Kk9GPCuqGzGnBmWtcE44Cwzj1aru57IN5/LKIWd1lIvaT6sKw==", + "dependencies": { + "commondir": "^1.0.1", + "deep-extend": "^0.6.0", + "ejs": "^3.1.5", + "globby": "^11.0.1", + "isbinaryfile": "^4.0.0", + "multimatch": "^5.0.0", + "normalize-path": "^3.0.0", + "through2": "^4.0.2", + "vinyl": "^2.2.1" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/mem-fs-editor/node_modules/ejs": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz", + "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==", + "dependencies": { + "jake": "^10.6.1" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mem-fs-editor/node_modules/multimatch": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", + "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==", + "dependencies": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mem-fs/node_modules/through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + }, + "node_modules/mem/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mime-db": { + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", + "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.29", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", + "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", + "dependencies": { + "mime-db": "1.46.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "node_modules/minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.3.3.tgz", + "integrity": "sha512-akCrLDWfbdAWkMLBxJEeWTdNsjML+dt5YgOI4gJ53vuO0vrmYQkUPxa6j6V65s9CcePIr2SSWqjT2EcrNseryQ==", + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-json-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", + "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mkdirp-infer-owner": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mkdirp-infer-owner/-/mkdirp-infer-owner-2.0.0.tgz", + "integrity": "sha512-sdqtiFt3lkOaYvTXSRIUjkIdPTcxgv5+fgqYE/5qgwdw12cOrAuzzgzvVExIkH/ul1oeHN3bCLOWSG3XOqbKKw==", + "dependencies": { + "chownr": "^2.0.0", + "infer-owner": "^1.0.4", + "mkdirp": "^1.0.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.2.tgz", + "integrity": "sha512-UdmISwr/5w+uXLPKspgoV7/RXZwKRTiTjJ2/AC5ZiEztIoOYdfKb19+9jNmEInzx5pBsCyJQzarAxqIGBNYJhg==", + "dev": true, + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.1", + "debug": "4.3.1", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.0.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.1.20", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.1.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 10.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/mocha/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/mocha/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/mocha/node_modules/y18n": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", + "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/multimatch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", + "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", + "dependencies": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + }, + "node_modules/nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, + "node_modules/nise": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", + "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "node_modules/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/node-gyp": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz", + "integrity": "sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==", + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.3", + "nopt": "^5.0.0", + "npmlog": "^4.1.2", + "request": "^2.88.2", + "rimraf": "^3.0.2", + "semver": "^7.3.2", + "tar": "^6.0.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "dependencies": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/npm-install-checks": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-4.0.0.tgz", + "integrity": "sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==", + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + }, + "node_modules/npm-package-arg": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.2.tgz", + "integrity": "sha512-6Eem455JsSMJY6Kpd3EyWE+n5hC+g9bSyHr9K9U2zqZb7+02+hObQ2c0+8iDk/mNF+8r1MhY44WypKJAkySIYA==", + "dependencies": { + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-package-arg/node_modules/hosted-git-info": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", + "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-packlist": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-2.1.5.tgz", + "integrity": "sha512-KCfK3Vi2F+PH1klYauoQzg81GQ8/GGjQRKYY6tRnpQUPKTs/1gBZSRWtTEd7jGdSn1LZL7gpAmJT+BcS55k2XQ==", + "dependencies": { + "glob": "^7.1.6", + "ignore-walk": "^3.0.3", + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + }, + "bin": { + "npm-packlist": "bin/index.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-pick-manifest": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.1.tgz", + "integrity": "sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA==", + "dependencies": { + "npm-install-checks": "^4.0.0", + "npm-normalize-package-bin": "^1.0.1", + "npm-package-arg": "^8.1.2", + "semver": "^7.3.4" + } + }, + "node_modules/npm-registry-fetch": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-9.0.0.tgz", + "integrity": "sha512-PuFYYtnQ8IyVl6ib9d3PepeehcUeHN9IO5N/iCRhyg9tStQcqGQBRVHmfmMWPDERU3KwZoHFvbJ4FPXPspvzbA==", + "dependencies": { + "@npmcli/ci-detect": "^1.0.0", + "lru-cache": "^6.0.0", + "make-fetch-happen": "^8.0.9", + "minipass": "^3.1.3", + "minipass-fetch": "^1.3.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.0.0", + "npm-package-arg": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/nth-check": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz", + "integrity": "sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", + "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.3.tgz", + "integrity": "sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", + "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2", + "has": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "dependencies": { + "fn.name": "1.x.x" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/onetime/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", + "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", + "dependencies": { + "bl": "^4.0.3", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "log-symbols": "^4.0.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/os-locale": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-5.0.0.tgz", + "integrity": "sha512-tqZcNEDAIZKBEPnHPlVDvKrp7NzgLi7jRmhKiUoa2NUmhl13FtkAGLUVR+ZsYvApBQdBfYm43A4tXXQ4IrYLBA==", + "dependencies": { + "execa": "^4.0.0", + "lcid": "^3.0.0", + "mem": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/os-name": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-3.1.0.tgz", + "integrity": "sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==", + "dependencies": { + "macos-release": "^2.2.0", + "windows-release": "^3.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pacote": { + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-11.3.1.tgz", + "integrity": "sha512-TymtwoAG12cczsJIrwI/euOQKtjrQHlD0k0oyt9QSmZGpqa+KdlxKdWR/YUjYizkixaVyztxt/Wsfo8bL3A6Fg==", + "dependencies": { + "@npmcli/git": "^2.0.1", + "@npmcli/installed-package-contents": "^1.0.6", + "@npmcli/promise-spawn": "^1.2.0", + "@npmcli/run-script": "^1.8.2", + "cacache": "^15.0.5", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "infer-owner": "^1.0.4", + "minipass": "^3.1.3", + "mkdirp": "^1.0.3", + "npm-package-arg": "^8.0.1", + "npm-packlist": "^2.1.4", + "npm-pick-manifest": "^6.0.0", + "npm-registry-fetch": "^9.0.0", + "promise-retry": "^2.0.1", + "read-package-json-fast": "^2.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.1.0" + }, + "bin": { + "pacote": "lib/bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-cache-control": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", + "integrity": "sha1-juqz5U+laSD+Fro493+iGqzC104=" + }, + "node_modules/parse-conflict-json": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-1.1.1.tgz", + "integrity": "sha512-4gySviBiW5TRl7XHvp1agcS7SOe0KZOjC//71dzZVWJrY9hCrgtvl5v3SyIxCZ4fZF47TxD9nfzmxcx76xmbUw==", + "dependencies": { + "json-parse-even-better-errors": "^2.3.0", + "just-diff": "^3.0.1", + "just-diff-apply": "^3.0.0" + } + }, + "node_modules/parse-gitignore": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-gitignore/-/parse-gitignore-1.0.1.tgz", + "integrity": "sha512-UGyowyjtx26n65kdAMWhm6/3uy5uSrpcuH7tt+QEVudiBoVS+eqHxD5kbi9oWVRwj7sCzXqwuM+rUGw7earl6A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/path-to-regexp/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "node_modules/picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pipeline-pipe": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/pipeline-pipe/-/pipeline-pipe-0.1.5.tgz", + "integrity": "sha512-HFub9yAfxEWBZZmsA12dWiFpg9+er8Sp7bpVwKP41AsAeO6570PVhU2Ckkt8fMnHBwm1edLLg2wIfpNGCDvI0Q==", + "dependencies": { + "cyclist": "^1.0.1", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "dependencies": { + "find-up": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-dir/node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "engines": { + "node": ">=4" + } + }, + "node_modules/plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dependencies": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/plugin-error/node_modules/ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dependencies": { + "ansi-wrap": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/preferred-pm": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/preferred-pm/-/preferred-pm-3.0.3.tgz", + "integrity": "sha512-+wZgbxNES/KlJs9q40F/1sfOd/j7f1O9JaHcW5Dsn3aUUOZg3L2bjpVUcKV2jvtElYfoTuQiNeMfQJ4kwUAhCQ==", + "dependencies": { + "find-up": "^5.0.0", + "find-yarn-workspace-root2": "1.2.16", + "path-exists": "^4.0.0", + "which-pm": "2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/prettier-plugin-java": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/prettier-plugin-java/-/prettier-plugin-java-1.0.2.tgz", + "integrity": "sha512-YgcN1WGZlrH0E+bHdqtIYtfDp6k2PHBnIaGjzdff/7t/NyDWAA6ypAmnD7YQVG2OuoIaXYkC37HN7cz68lLWLg==", + "dependencies": { + "java-parser": "1.0.2", + "lodash": "4.17.21", + "prettier": "2.2.1" + } + }, + "node_modules/prettier-plugin-packagejson": { + "version": "2.2.10", + "resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.2.10.tgz", + "integrity": "sha512-/meFZrpGSg/F3jXspBJikHBLf/m1ol6XJjYslM++AQno7B/SPNrGICMMck0qHBU+f7vVfqbZmdC/OO5opU3HPw==", + "dependencies": { + "sort-package-json": "1.49.0" + }, + "peerDependencies": { + "prettier": ">= 1.16.0" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz", + "integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==", + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/promise-all-reject-late": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz", + "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/promise-call-limit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-call-limit/-/promise-call-limit-1.0.1.tgz", + "integrity": "sha512-3+hgaa19jzCGLuSCbieeRsu5C2joKfYn8pY6JAuXFRVfF4IO+L7UPpFWNTeWT9pM7uhskvbPPd/oEOktCn317Q==", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randexp": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.5.3.tgz", + "integrity": "sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w==", + "dependencies": { + "drange": "^1.0.2", + "ret": "^0.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/read-chunk": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-3.2.0.tgz", + "integrity": "sha512-CEjy9LCzhmD7nUpJ1oVOE6s/hBkejlcJEgLQHVnQznOSilOPb+kpKktlLfFDK3/WP43+F80xkUTM2VOkYoSYvQ==", + "dependencies": { + "pify": "^4.0.1", + "with-open-file": "^0.1.6" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/read-chunk/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/read-cmd-shim": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-2.0.0.tgz", + "integrity": "sha512-HJpV9bQpkl6KwjxlJcBoqu9Ba0PQg8TqSNIOrulGt54a0uup0HtevreFHzYzkm0lpnleRdNBzXznKrgxglEHQw==" + }, + "node_modules/read-input": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/read-input/-/read-input-0.3.1.tgz", + "integrity": "sha1-WzFpMIATRk/9puyS5Y0tPOqUjfE=", + "dev": true + }, + "node_modules/read-package-json-fast": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.2.tgz", + "integrity": "sha512-5fyFUyO9B799foVk4n6ylcoAktG/FbE3jwRKxvwaeSrIunaoMc0u81dzXxjeAFKOce7O5KncdfwpGvvs6r5PsQ==", + "dependencies": { + "json-parse-even-better-errors": "^2.3.0", + "npm-normalize-package-bin": "^1.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "dependencies": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "dependencies": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/read-pkg/node_modules/path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "dependencies": { + "pify": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdir-scoped-modules": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", + "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", + "dependencies": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/regexp-to-ast": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", + "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==" + }, + "node_modules/regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "node_modules/replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dependencies": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/restore-cursor/node_modules/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dependencies": { + "mimic-fn": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ret": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", + "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rewire": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/rewire/-/rewire-5.0.0.tgz", + "integrity": "sha512-1zfitNyp9RH5UDyGGLe9/1N0bMlPQ0WrX0Tmg11kMHBpqwPJI4gfPpP7YngFyLbFmhXh19SToAG0sKKEFcOIJA==", + "dev": true, + "dependencies": { + "eslint": "^6.8.0" + } + }, + "node_modules/rewire/node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rewire/node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rewire/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/rewire/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/rewire/node_modules/astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/rewire/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/rewire/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/rewire/node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/rewire/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/rewire/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/rewire/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/rewire/node_modules/cross-spawn/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/rewire/node_modules/eslint": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.3", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/rewire/node_modules/eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/rewire/node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/rewire/node_modules/eslint/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/rewire/node_modules/espree": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", + "dev": true, + "dependencies": { + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/rewire/node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rewire/node_modules/file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "dependencies": { + "flat-cache": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/rewire/node_modules/flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "dependencies": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/rewire/node_modules/flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "node_modules/rewire/node_modules/globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "dependencies": { + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rewire/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/rewire/node_modules/inquirer": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.19", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/rewire/node_modules/inquirer/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/rewire/node_modules/inquirer/node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/rewire/node_modules/inquirer/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/rewire/node_modules/inquirer/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/rewire/node_modules/inquirer/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/rewire/node_modules/inquirer/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/rewire/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/rewire/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/rewire/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/rewire/node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "node_modules/rewire/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/rewire/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/rewire/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/rewire/node_modules/regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true, + "engines": { + "node": ">=6.5.0" + } + }, + "node_modules/rewire/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/rewire/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/rewire/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/rewire/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rewire/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rewire/node_modules/slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/rewire/node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/rewire/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/rewire/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/rewire/node_modules/table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "dependencies": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/rewire/node_modules/table/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/rewire/node_modules/table/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/rewire/node_modules/table/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/rewire/node_modules/table/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/rewire/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/rewire/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/rewire/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" + }, + "node_modules/scoped-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/scoped-regex/-/scoped-regex-2.1.0.tgz", + "integrity": "sha512-g3WxHrqSWCZHGHlSrF51VXFdjImhwvH8ZO/pryFH56Qi0cDsZfylQa/t0jCzVQFNbNvM00HfHjkDPEuarKDSWQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/shelljs": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", + "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, + "node_modules/sinon": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", + "integrity": "sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.8.1", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/samsam": "^5.3.1", + "diff": "^4.0.2", + "nise": "^4.0.4", + "supports-color": "^7.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/sinon/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", + "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.0.tgz", + "integrity": "sha512-mNmr9owlinMplev0Wd7UHFlqI4ofnBnNzFuzrm63PPaHgbkqCFe4T5LzwKmtQ/f2tX0NTpcdVLyD/FHxFBstYw==", + "dependencies": { + "ip": "^1.1.5", + "smart-buffer": "^4.1.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.0.tgz", + "integrity": "sha512-lEpa1zsWCChxiynk+lCycKuC502RxDWLKJZoIhnxrWNjLSDGYRFflHA1/228VkRcnv9TIb8w98derGbpKxJRgA==", + "dependencies": { + "agent-base": "6", + "debug": "4", + "socks": "^2.3.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sort-object-keys": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz", + "integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==" + }, + "node_modules/sort-package-json": { + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-1.49.0.tgz", + "integrity": "sha512-3YuqFGThwc9X0TZLYohOUJJ/P6uJIVcTeuJOc6ZWw4f1fHpTHIfVysKer4qXtrZ2zvwwU2aEcb555Bo+2fwIgQ==", + "dependencies": { + "detect-indent": "^6.0.0", + "detect-newline": "3.1.0", + "git-hooks-list": "1.0.3", + "globby": "10.0.0", + "is-plain-obj": "2.1.0", + "sort-object-keys": "^1.1.3" + }, + "bin": { + "sort-package-json": "cli.js" + } + }, + "node_modules/sort-package-json/node_modules/globby": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.0.tgz", + "integrity": "sha512-3LifW9M4joGZasyYPz2A1U74zbC/45fvpXUvO/9KbSa+VV0aGZarWkfdgKyR9sExNP0t0x0ss/UMJpNpcaTspw==", + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sort-package-json/node_modules/ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", + "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==" + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "engines": { + "node": "*" + } + }, + "node_modules/streamfilter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/streamfilter/-/streamfilter-3.0.0.tgz", + "integrity": "sha512-kvKNfXCmUyC8lAXSSHCIXBUlo/lhsLcCU/OmzACZYpRUdtKIH68xYhm/+HI15jFJYtNJGYtCgn2wmIiExY1VwA==", + "dependencies": { + "readable-stream": "^3.0.6" + }, + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "engines": { + "node": ">=4" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-bom-buf": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-buf/-/strip-bom-buf-1.0.0.tgz", + "integrity": "sha1-HLRar1dTD0yvhsf3UXnSyaUd1XI=", + "dependencies": { + "is-utf8": "^0.2.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-bom-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz", + "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", + "dependencies": { + "first-chunk-stream": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-bom-stream/node_modules/strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dependencies": { + "is-utf8": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "dev": true, + "dependencies": { + "acorn-node": "^1.2.0" + } + }, + "node_modules/table": { + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/table/-/table-6.0.8.tgz", + "integrity": "sha512-OBAdezyozae8IvjHGXBDHByVkLCcsmffXUSj8LXkNb0SluRd4ug3GFCjk6JynZONIPhOkyr0Nnvbq1rlIspXyQ==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "lodash.clonedeep": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.0.1.tgz", + "integrity": "sha512-46ZA4TalFcLLqX1dEU3dhdY38wAtDydJ4e7QQTVekLUTzXkb1LfqU6VOBXC/a9wiv4T094WURqJH6ZitF92Kqw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/table/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", + "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + }, + "node_modules/textextensions": { + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-5.12.0.tgz", + "integrity": "sha512-IYogUDaP65IXboCiPPC0jTLLBzYlhhw2Y4b0a2trPgbHNGGGEfuHE6tds+yDcCf4mpNDaGISFzwSSezcXt+d6w==", + "engines": { + "node": ">=0.8" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/then-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/then-request/-/then-request-6.0.2.tgz", + "integrity": "sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==", + "dependencies": { + "@types/concat-stream": "^1.6.0", + "@types/form-data": "0.0.33", + "@types/node": "^8.0.0", + "@types/qs": "^6.2.31", + "caseless": "~0.12.0", + "concat-stream": "^1.6.0", + "form-data": "^2.2.0", + "http-basic": "^8.1.1", + "http-response-object": "^3.0.1", + "promise": "^8.0.0", + "qs": "^6.4.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tough-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", + "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==", + "dependencies": { + "ip-regex": "^2.1.0", + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/treeverse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/treeverse/-/treeverse-1.0.4.tgz", + "integrity": "sha512-whw60l7r+8ZU8Tu/Uc2yxtc4ZTZbR/PF3u1IPNKGQ6p8EICLb3Z2lAgoqw9bqYd8IkgnsaOcLzYHFckjqNsf0g==" + }, + "node_modules/triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" + }, + "node_modules/tsconfig-paths": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", + "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "dependencies": { + "builtins": "^1.0.3" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/version-compare": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/version-compare/-/version-compare-1.1.0.tgz", + "integrity": "sha512-zVKtPOJTC9x23lzS4+4D7J+drq80BXVYAmObnr5zqxxFVH7OffJ1lJlAS7LYsQNV56jx/wtbw0UV7XHLrvd6kQ==", + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/version-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/version-range/-/version-range-1.1.0.tgz", + "integrity": "sha512-R1Ggfg2EXamrnrV3TkZ6yBNgITDbclB3viwSjbZ3+eK0VVNK4ajkYJTnDz5N0bIMYDtK9MUBvXJUnKO5RWWJ6w==", + "dependencies": { + "version-compare": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "dependencies": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-file": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-3.0.0.tgz", + "integrity": "sha1-sQTZ5ECf+jJfqt1SBkLQo7SIs2U=", + "dependencies": { + "graceful-fs": "^4.1.2", + "pify": "^2.3.0", + "strip-bom-buf": "^1.0.0", + "strip-bom-stream": "^2.0.0", + "vinyl": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/vinyl/node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/walk-up-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-1.0.0.tgz", + "integrity": "sha512-hwj/qMDUEjCU5h0xr90KGCf0tg0/LgJbmOWgrWKYlcJZM7XvquvUJZ0G/HMGr7F7OQMOUuPHWP9JpriinkAlkg==" + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "node_modules/which-pm": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-pm/-/which-pm-2.0.0.tgz", + "integrity": "sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==", + "dependencies": { + "load-yaml-file": "^0.2.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8.15" + } + }, + "node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/windows-release": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.3.3.tgz", + "integrity": "sha512-OSOGH1QYiW5yVor9TtmXKQvt2vjQqbYS+DqmsZw+r7xDwLXEeT3JGW0ZppFmHx4diyXmxt238KFR3N9jzevBRg==", + "dependencies": { + "execa": "^1.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/windows-release/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/windows-release/node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.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" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/windows-release/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/windows-release/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/windows-release/node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/windows-release/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "engines": { + "node": ">=4" + } + }, + "node_modules/windows-release/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/windows-release/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/windows-release/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/windows-release/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/winston": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", + "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", + "dependencies": { + "@dabh/diagnostics": "^2.0.2", + "async": "^3.1.0", + "is-stream": "^2.0.0", + "logform": "^2.2.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.4.0" + }, + "engines": { + "node": ">= 6.4.0" + } + }, + "node_modules/winston-transport": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", + "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", + "dependencies": { + "readable-stream": "^2.3.7", + "triple-beam": "^1.2.0" + }, + "engines": { + "node": ">= 6.4.0" + } + }, + "node_modules/winston-transport/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/winston-transport/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/winston-transport/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/winston/node_modules/async": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" + }, + "node_modules/with-open-file": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/with-open-file/-/with-open-file-0.1.7.tgz", + "integrity": "sha512-ecJS2/oHtESJ1t3ZfMI3B7KIDKyfN0O16miWxdn30zdh66Yd3LsRFebXZXq6GU4xfxLf6nVxp9kIqElb5fqczA==", + "dependencies": { + "p-finally": "^1.0.0", + "p-try": "^2.1.0", + "pify": "^4.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/with-open-file/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workerpool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", + "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "dependencies": { + "mkdirp": "^0.5.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/write/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/xml2js": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~9.0.1" + } + }, + "node_modules/xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", + "dev": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.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": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser/node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yeoman-assert": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yeoman-assert/-/yeoman-assert-3.1.1.tgz", + "integrity": "sha512-bCuLb/j/WzpvrJZCTdJJLFzm7KK8IYQJ3+dF9dYtNs2CUYyezFJDuULiZ2neM4eqjf45GN1KH/MzCTT3i90wUQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/yeoman-environment": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-3.2.0.tgz", + "integrity": "sha512-Z2G4qgbjSLQ0BOiPQ4PCbqSYNhOP/HeWItu/hrlBv1gtBK6c3vkHSLioX8SduVYOKrn04X4H7cIG7hXpD3RsOQ==", + "dependencies": { + "@npmcli/arborist": "^2.2.2", + "are-we-there-yet": "^1.1.5", + "arrify": "^2.0.1", + "chalk": "^4.1.0", + "cli-table": "^0.3.1", + "commander": "7.1.0", + "dateformat": "^4.5.0", + "debug": "^4.1.1", + "diff": "^5.0.0", + "error": "^10.4.0", + "escape-string-regexp": "^4.0.0", + "execa": "^5.0.0", + "find-up": "^5.0.0", + "globby": "^11.0.1", + "grouped-queue": "^2.0.0", + "inquirer": "^8.0.0", + "is-scoped": "^2.1.0", + "istextorbinary": "^5.7.0", + "lodash": "^4.17.10", + "log-symbols": "^4.0.0", + "mem-fs": "^1.1.0", + "mem-fs-editor": "^8.0.0", + "minimatch": "^3.0.4", + "npmlog": "^4.1.2", + "pacote": "^11.2.6", + "pipeline-pipe": "^0.1.5", + "preferred-pm": "^3.0.3", + "pretty-bytes": "^5.3.0", + "read-chunk": "^3.2.0", + "semver": "^7.1.3", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0", + "text-table": "^0.2.0", + "through2": "^4.0.2", + "untildify": "^4.0.0" + }, + "bin": { + "yoe": "cli/index.js" + }, + "engines": { + "node": ">=12.10.0" + } + }, + "node_modules/yeoman-environment/node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yeoman-environment/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yeoman-environment/node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/yeoman-environment/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yeoman-environment/node_modules/execa": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", + "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/yeoman-environment/node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yeoman-environment/node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/yeoman-environment/node_modules/get-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", + "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yeoman-environment/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/yeoman-environment/node_modules/inquirer": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.0.0.tgz", + "integrity": "sha512-ON8pEJPPCdyjxj+cxsYRe6XfCJepTxANdNnTebsTuQgXpRyZRRT9t4dJwjRubgmvn20CLSEnozRUayXyM9VTXA==", + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.6", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/yeoman-environment/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/yeoman-environment/node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, + "node_modules/yeoman-environment/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yeoman-environment/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yeoman-environment/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yeoman-generator": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-5.2.0.tgz", + "integrity": "sha512-LCHaYrcgtC4NpYAkritCEteuDSjBdhsQNYrssZjnK0okRFvroMXDX4//CA1RfVsjCHKi4Df6lILOUYCRiYKG4g==", + "dependencies": { + "chalk": "^4.1.0", + "dargs": "^7.0.0", + "debug": "^4.1.1", + "execa": "^4.1.0", + "github-username": "^6.0.0", + "lodash": "^4.17.11", + "minimist": "^1.2.5", + "read-pkg-up": "^7.0.1", + "run-async": "^2.0.0", + "semver": "^7.2.1", + "shelljs": "^0.8.4", + "text-table": "^0.2.0" + }, + "engines": { + "node": ">=12.10.0" + }, + "peerDependencies": { + "yeoman-environment": "^3.2.0" + }, + "peerDependenciesMeta": { + "yeoman-environment": { + "optional": true + } + } + }, + "node_modules/yeoman-generator/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yeoman-generator/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yeoman-generator/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yeoman-generator/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yeoman-generator/node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yeoman-generator/node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yeoman-generator/node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yeoman-generator/node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/yeoman-generator/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/yeoman-test": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/yeoman-test/-/yeoman-test-5.1.0.tgz", + "integrity": "sha512-lcXcNRleJrIhohoKcRwmj9i8JO0lsYTySprwCfgZV1THeHJRqUsBEhHVgMr7DVB+coMoIkxk99wpn/bsOvpz4w==", + "dev": true, + "dependencies": { + "inquirer": "^7.3.3", + "lodash": "^4.17.19", + "mem-fs-editor": "^8.0.0", + "sinon": "^9.0.2" + }, + "engines": { + "node": ">=12.10.0" + }, + "peerDependencies": { + "yeoman-environment": "^3.0.0 || ^2.10.3", + "yeoman-generator": "*" + } + }, + "node_modules/yeoman-test/node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yeoman-test/node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yeoman-test/node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/yeoman-test/node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yeoman-test/node_modules/inquirer": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.19", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/yeoman-test/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yeoman-test/node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "node_modules/yeoman-test/node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yeoman-test/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yeoman-test/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", + "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==" + }, + "@babel/highlight": { + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", + "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", + "requires": { + "@babel/helper-validator-identifier": "^7.12.11", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@dabh/diagnostics": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", + "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", + "requires": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, + "@eslint/eslintrc": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", + "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz", + "integrity": "sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA==", + "requires": { + "@nodelib/fs.stat": "2.0.4", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==" + }, + "@nodelib/fs.walk": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz", + "integrity": "sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow==", + "requires": { + "@nodelib/fs.scandir": "2.1.4", + "fastq": "^1.6.0" + } + }, + "@npmcli/arborist": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-2.2.9.tgz", + "integrity": "sha512-ddC/CCAEHh28XYtgSAOudchdphNXcgErdYxwsEiykc2YbRA9Z+4XjI0BdBdXvv22DvkpO7zotUSxlVTcJmdURw==", + "requires": { + "@npmcli/installed-package-contents": "^1.0.7", + "@npmcli/map-workspaces": "^1.0.2", + "@npmcli/metavuln-calculator": "^1.1.0", + "@npmcli/move-file": "^1.1.0", + "@npmcli/name-from-folder": "^1.0.1", + "@npmcli/node-gyp": "^1.0.1", + "@npmcli/run-script": "^1.8.2", + "bin-links": "^2.2.1", + "cacache": "^15.0.3", + "common-ancestor-path": "^1.0.1", + "json-parse-even-better-errors": "^2.3.1", + "json-stringify-nice": "^1.1.1", + "mkdirp-infer-owner": "^2.0.0", + "npm-install-checks": "^4.0.0", + "npm-package-arg": "^8.1.0", + "npm-pick-manifest": "^6.1.0", + "npm-registry-fetch": "^9.0.0", + "pacote": "^11.2.6", + "parse-conflict-json": "^1.1.1", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^1.0.1", + "read-package-json-fast": "^2.0.2", + "readdir-scoped-modules": "^1.1.0", + "semver": "^7.3.5", + "tar": "^6.1.0", + "treeverse": "^1.0.4", + "walk-up-path": "^1.0.0" + }, + "dependencies": { + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@npmcli/ci-detect": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@npmcli/ci-detect/-/ci-detect-1.3.0.tgz", + "integrity": "sha512-oN3y7FAROHhrAt7Rr7PnTSwrHrZVRTS2ZbyxeQwSSYD0ifwM3YNgQqbaRmjcWoPyq77MjchusjJDspbzMmip1Q==" + }, + "@npmcli/git": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-2.0.6.tgz", + "integrity": "sha512-a1MnTfeRPBaKbFY07fd+6HugY1WAkKJzdiJvlRub/9o5xz2F/JtPacZZapx5zRJUQFIzSL677vmTSxEcDMrDbg==", + "requires": { + "@npmcli/promise-spawn": "^1.1.0", + "lru-cache": "^6.0.0", + "mkdirp": "^1.0.3", + "npm-pick-manifest": "^6.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.2", + "unique-filename": "^1.1.1", + "which": "^2.0.2" + } + }, + "@npmcli/installed-package-contents": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz", + "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==", + "requires": { + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "@npmcli/map-workspaces": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/map-workspaces/-/map-workspaces-1.0.3.tgz", + "integrity": "sha512-SdlRlOoQw4WKD4vtb/n5gUkobEABYBEOo8fRE4L8CtBkyWDSvIrReTfKvQ/Jc/LQqDaaZ5iv1iMSQzKCUr1n1A==", + "requires": { + "@npmcli/name-from-folder": "^1.0.1", + "glob": "^7.1.6", + "minimatch": "^3.0.4", + "read-package-json-fast": "^2.0.1" + } + }, + "@npmcli/metavuln-calculator": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/metavuln-calculator/-/metavuln-calculator-1.1.1.tgz", + "integrity": "sha512-9xe+ZZ1iGVaUovBVFI9h3qW+UuECUzhvZPxK9RaEA2mjU26o5D0JloGYWwLYvQELJNmBdQB6rrpuN8jni6LwzQ==", + "requires": { + "cacache": "^15.0.5", + "pacote": "^11.1.11", + "semver": "^7.3.2" + } + }, + "@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "requires": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + } + }, + "@npmcli/name-from-folder": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-1.0.1.tgz", + "integrity": "sha512-qq3oEfcLFwNfEYOQ8HLimRGKlD8WSeGEdtUa7hmzpR8Sa7haL1KVQrvgO6wqMjhWFFVjgtrh1gIxDz+P8sjUaA==" + }, + "@npmcli/node-gyp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.2.tgz", + "integrity": "sha512-yrJUe6reVMpktcvagumoqD9r08fH1iRo01gn1u0zoCApa9lnZGEigVKUd2hzsCId4gdtkZZIVscLhNxMECKgRg==" + }, + "@npmcli/promise-spawn": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz", + "integrity": "sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg==", + "requires": { + "infer-owner": "^1.0.4" + } + }, + "@npmcli/run-script": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-1.8.4.tgz", + "integrity": "sha512-Yd9HXTtF1JGDXZw0+SOn+mWLYS0e7bHBHVC/2C8yqs4wUrs/k8rwBSinD7rfk+3WG/MFGRZKxjyoD34Pch2E/A==", + "requires": { + "@npmcli/node-gyp": "^1.0.2", + "@npmcli/promise-spawn": "^1.3.2", + "infer-owner": "^1.0.4", + "node-gyp": "^7.1.0", + "read-package-json-fast": "^2.0.1" + } + }, + "@octokit/auth-token": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.5.tgz", + "integrity": "sha512-BpGYsPgJt05M7/L/5FoE1PiAbdxXFZkX/3kDYcsvd1v6UhlnE5e96dTDr0ezX/EFwciQxf3cNV0loipsURU+WA==", + "requires": { + "@octokit/types": "^6.0.3" + } + }, + "@octokit/core": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.3.1.tgz", + "integrity": "sha512-Dc5NNQOYjgZU5S1goN6A/E500yXOfDUFRGQB8/2Tl16AcfvS3H9PudyOe3ZNE/MaVyHPIfC0htReHMJb1tMrvw==", + "requires": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.4.12", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/endpoint": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.11.tgz", + "integrity": "sha512-fUIPpx+pZyoLW4GCs3yMnlj2LfoXTWDUVPTC4V3MUEKZm48W+XYpeWSZCv+vYF1ZABUm2CqnDVf1sFtIYrj7KQ==", + "requires": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + }, + "dependencies": { + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + } + } + }, + "@octokit/graphql": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.6.1.tgz", + "integrity": "sha512-2lYlvf4YTDgZCTXTW4+OX+9WTLFtEUc6hGm4qM1nlZjzxj+arizM4aHWzBVBCxY9glh7GIs0WEuiSgbVzv8cmA==", + "requires": { + "@octokit/request": "^5.3.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/openapi-types": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-6.0.0.tgz", + "integrity": "sha512-CnDdK7ivHkBtJYzWzZm7gEkanA7gKH6a09Eguz7flHw//GacPJLmkHA3f3N++MJmlxD1Fl+mB7B32EEpSCwztQ==" + }, + "@octokit/plugin-paginate-rest": { + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.13.3.tgz", + "integrity": "sha512-46lptzM9lTeSmIBt/sVP/FLSTPGx6DCzAdSX3PfeJ3mTf4h9sGC26WpaQzMEq/Z44cOcmx8VsOhO+uEgE3cjYg==", + "requires": { + "@octokit/types": "^6.11.0" + } + }, + "@octokit/plugin-request-log": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.3.tgz", + "integrity": "sha512-4RFU4li238jMJAzLgAwkBAw+4Loile5haQMQr+uhFq27BmyJXcXSKvoQKqh0agsZEiUlW6iSv3FAgvmGkur7OQ==", + "requires": {} + }, + "@octokit/plugin-rest-endpoint-methods": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.0.0.tgz", + "integrity": "sha512-Jc7CLNUueIshXT+HWt6T+M0sySPjF32mSFQAK7UfAg8qGeRI6OM1GSBxDLwbXjkqy2NVdnqCedJcP1nC785JYg==", + "requires": { + "@octokit/types": "^6.13.0", + "deprecation": "^2.3.1" + } + }, + "@octokit/request": { + "version": "5.4.14", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.4.14.tgz", + "integrity": "sha512-VkmtacOIQp9daSnBmDI92xNIeLuSRDOIuplp/CJomkvzt7M18NXgG044Cx/LFKLgjKt9T2tZR6AtJayba9GTSA==", + "requires": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.0.0", + "@octokit/types": "^6.7.1", + "deprecation": "^2.0.0", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.1", + "once": "^1.4.0", + "universal-user-agent": "^6.0.0" + }, + "dependencies": { + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + } + } + }, + "@octokit/request-error": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.5.tgz", + "integrity": "sha512-T/2wcCFyM7SkXzNoyVNWjyVlUwBvW3igM3Btr/eKYiPmucXTtkxt2RBsf6gn3LTzaLSLTQtNmvg+dGsOxQrjZg==", + "requires": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "@octokit/rest": { + "version": "18.5.2", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.5.2.tgz", + "integrity": "sha512-Kz03XYfKS0yYdi61BkL9/aJ0pP2A/WK5vF/syhu9/kY30J8He3P68hv9GRpn8bULFx2K0A9MEErn4v3QEdbZcw==", + "requires": { + "@octokit/core": "^3.2.3", + "@octokit/plugin-paginate-rest": "^2.6.2", + "@octokit/plugin-request-log": "^1.0.2", + "@octokit/plugin-rest-endpoint-methods": "5.0.0" + } + }, + "@octokit/types": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.13.0.tgz", + "integrity": "sha512-W2J9qlVIU11jMwKHUp5/rbVUeErqelCsO5vW5PKNb7wAXQVUz87Rc+imjlEvpvbH8yUb+KHmv8NEjVZdsdpyxA==", + "requires": { + "@octokit/openapi-types": "^6.0.0" + } + }, + "@sinonjs/commons": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.2.tgz", + "integrity": "sha512-sruwd86RJHdsVf/AtBoijDmUqJp3B6hF/DGC23C+JaegnDHaZyewCjoVGTdg3J0uz3Zs7NnIT05OBOmML72lQw==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@sinonjs/samsam": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", + "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==" + }, + "@types/concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-OU2+C7X+5Gs42JZzXoto7yOQ0A0=", + "requires": { + "@types/node": "*" + } + }, + "@types/form-data": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz", + "integrity": "sha1-yayFsqX9GENbjIXZ7LUObWyJP/g=", + "requires": { + "@types/node": "*" + } + }, + "@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==" + }, + "@types/node": { + "version": "8.10.66", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", + "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==" + }, + "@types/normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==" + }, + "@types/qs": { + "version": "6.9.6", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.6.tgz", + "integrity": "sha512-0/HnwIfW4ki2D8L8c9GVcG5I72s9jP5GSLVF0VIXDW00kmIpA6O33G7a8n59Tmh7Nz0WUC3rSb7PTY/sdW2JzA==" + }, + "@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true, + "requires": {} + }, + "acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "requires": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, + "agentkeepalive": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.1.4.tgz", + "integrity": "sha512-+V/rGa3EuU74H6wR04plBb7Ks10FbtUQgRj/FQOG7uUIEuaINI+AiqJR1k6t3SVNs7o7ZjIdus6706qqzVq8jQ==", + "requires": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + }, + "array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==" + }, + "array-includes": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", + "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.5" + } + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==" + }, + "array.prototype.flat": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", + "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + } + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "requires": { + "lodash": "^4.17.14" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true + }, + "atomically": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz", + "integrity": "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==" + }, + "aws-sdk": { + "version": "2.863.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.863.0.tgz", + "integrity": "sha512-krr0047EOl9qpRdhPoyYxI7+viVUpX+t+Vjbf+alXdOE172DC+hFi8y6egIM1xVV4KkMFm0y0EykBWgA93XNNA==", + "requires": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.15.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "uuid": "3.3.2", + "xml2js": "0.4.19" + }, + "dependencies": { + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + } + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" + }, + "axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "requires": { + "follow-redirects": "^1.10.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "before-after-hook": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.0.tgz", + "integrity": "sha512-jH6rKQIfroBbhEXVmI7XmXe3ix5S/PgJqpzdDPnR8JGLHWNYLsYZ6tK5iWOF/Ra3oqEX0NobXGlzbiylIzVphQ==" + }, + "bin-links": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/bin-links/-/bin-links-2.2.1.tgz", + "integrity": "sha512-wFzVTqavpgCCYAh8SVBdnZdiQMxTkGR+T3b14CNpBXIBe2neJWaMGAZ55XWWHELJJ89dscuq0VCBqcVaIOgCMg==", + "requires": { + "cmd-shim": "^4.0.1", + "mkdirp": "^1.0.3", + "npm-normalize-package-bin": "^1.0.0", + "read-cmd-shim": "^2.0.0", + "rimraf": "^3.0.0", + "write-file-atomic": "^3.0.3" + } + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "binaryextensions": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-4.15.0.tgz", + "integrity": "sha512-MkUl3szxXolQ2scI1PM14WOT951KnaTNJ0eMKg7WzOI4kvSxyNo/Cygx4LOBNhwyINhAuSQpJW1rYD9aBSxGaw==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } - }, - "cli-width": { + } + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, + "builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=" + }, + "cacache": { + "version": "15.0.6", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.6.tgz", + "integrity": "sha512-g1WYDMct/jzW+JdWEyjaX2zoBkZ6ZT9VpOyp2I/VMtDsNLffNat3kqPFfi1eDRSK9/SuKGyORDHcQMcPF8sQ/w==", + "requires": { + "@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": "^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", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chai": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "cheerio": { + "version": "1.0.0-rc.5", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.5.tgz", + "integrity": "sha512-yoqps/VCaZgN4pfXtenwHROTp8NG6/Hlt4Jpz2FEP0ZJQ+ZUkVDd0hAPDNKhj3nakpfPt/CNs57yEtxD1bXQiw==", + "requires": { + "cheerio-select-tmp": "^0.1.0", + "dom-serializer": "~1.2.0", + "domhandler": "^4.0.0", + "entities": "~2.1.0", + "htmlparser2": "^6.0.0", + "parse5": "^6.0.0", + "parse5-htmlparser2-tree-adapter": "^6.0.0" + } + }, + "cheerio-select-tmp": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/cheerio-select-tmp/-/cheerio-select-tmp-0.1.1.tgz", + "integrity": "sha512-YYs5JvbpU19VYJyj+F7oYrIE2BOll1/hRU7rEy/5+v9BzkSo3bK81iAeeQEMI92vRIxz677m72UmJUiVwwgjfQ==", + "requires": { + "css-select": "^3.1.2", + "css-what": "^4.0.0", + "domelementtype": "^2.1.0", + "domhandler": "^4.0.0", + "domutils": "^2.4.4" + } + }, + "chevrotain": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-8.0.1.tgz", + "integrity": "sha512-nE//TMrGF7Kb7mwrGbpTspMqcVMwcUKZ7/3AEbmDPW3kD0aBVUaqWjbHDgZDEuxCG8CaSos9hMN7EKJn1TgHqw==", + "requires": { + "regexp-to-ast": "0.5.0" + } + }, + "chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.3.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-spinners": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.0.tgz", + "integrity": "sha512-t+4/y50K/+4xcCRosKkA7W4gTr1MySvLV0q+PxmG7FJ5g+66ChKurYjxBCjHggHH3HA5Hh9cy+lcUGWDqVH+4Q==" + }, + "cli-table": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.6.tgz", + "integrity": "sha512-ZkNZbnZjKERTY5NwC2SeMeLeifSPq/pubeRoTpdr3WchLlnZg6hEgvHkK5zL7KNFdd9PmHN8lxrENUwI3cE8vQ==", + "requires": { + "colors": "1.0.3" + }, + "dependencies": { + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + } + } + }, + "cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==" + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==" + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + } + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=" + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" + }, + "cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "cmd-shim": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cmd-shim/-/cmd-shim-4.1.0.tgz", + "integrity": "sha512-lb9L7EM4I/ZRVuljLPEtUJOP+xiQVknZ4ZMpMgEp4JzNldPb27HU03hi6K1/6CoIuit/Zm/LQXySErFeXxDprw==", + "requires": { + "mkdirp-infer-owner": "^2.0.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "color": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", + "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + }, + "dependencies": { "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -2915,566 +10733,1289 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "dir-glob": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", - "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + } + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "color-string": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz", + "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, + "colorspace": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", + "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", + "requires": { + "color": "3.0.x", + "text-hex": "1.0.x" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.1.0.tgz", + "integrity": "sha512-pRxBna3MJe6HKnBGsDyMv8ETbptw3axEdYHoqNh7gu5oDcew8fs0xnivZGm06Ogk8zGAJ9VX+OPEr2GXEQK4dg==" + }, + "common-ancestor-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", + "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==" + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "requires": { - "path-type": "^3.0.0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "ejs": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.3.tgz", - "integrity": "sha512-wmtrUGyfSC23GC/B1SMv2ogAUgbQEtDmTIhfqielrG5ExIM9TP4UoYdi90jLF1aTcsWCJNEO0UrgKzP0y3nTSg==", - "requires": { - "jake": "^10.6.1" - } + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" + "safe-buffer": "~5.1.0" } - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + } + } + }, + "conf": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/conf/-/conf-9.0.2.tgz", + "integrity": "sha512-rLSiilO85qHgaTBIIHQpsv8z+NnVfZq3cKuYNCXN1AOqPzced0GWZEe/A517VldRLyQYXUMyV+vszavE2jSAqw==", + "requires": { + "ajv": "^7.0.3", + "ajv-formats": "^1.5.1", + "atomically": "^1.7.0", + "debounce-fn": "^4.0.0", + "dot-prop": "^6.0.1", + "env-paths": "^2.2.0", + "json-schema-typed": "^7.0.3", + "make-dir": "^3.1.0", + "onetime": "^5.1.2", + "pkg-up": "^3.1.0", + "semver": "^7.3.4" + }, + "dependencies": { + "ajv": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.2.4.tgz", + "integrity": "sha512-nBeQgg/ZZA3u3SYxyaDvpvDtgZ/EZPF547ARgZBrG9Bhu1vKDwAIjtIf+sDtJUKa2zOcEbmRLBRSyMraS/Oy1A==", "requires": { - "escape-string-regexp": "^1.0.5" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" } }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } + "ajv-formats": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-1.6.0.tgz", + "integrity": "sha512-iio2lsjYkuTq49avg+/coyM5D3qdjyW1dkiy+I79XG3DAQFAOcGltC6eXsw6dX10OtH2S9Kyez7OkFtY0bJBBA==", + "requires": {} }, - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + } + } + }, + "confusing-browser-globals": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz", + "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==", + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "css-select": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-3.1.2.tgz", + "integrity": "sha512-qmss1EihSuBNWNNhHjxzxSfJoFBM/lERB/Q4EnsJQQC62R2evJDW481091oAdOr9uh46/0n4nrg0It5cAnj1RA==", + "requires": { + "boolbase": "^1.0.0", + "css-what": "^4.0.0", + "domhandler": "^4.0.0", + "domutils": "^2.4.3", + "nth-check": "^2.0.0" + } + }, + "css-what": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-4.0.0.tgz", + "integrity": "sha512-teijzG7kwYfNVsUh2H/YN62xW3KK9YhXEgSlbxMlcyjPNvdKJqFx5lrwlJgoFP1ZHlB89iGDlo/JyshKeRhv5A==" + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=" + }, + "dargs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "dateformat": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.5.1.tgz", + "integrity": "sha512-OD0TZ+B7yP7ZgpJf5K2DIbj3FZvFvxgFUuaqA/V5zTjAtAAXZ1E8bktHxmAGs4x5b7PflqA9LeQ84Og7wYtF7Q==" + }, + "debounce-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/debounce-fn/-/debounce-fn-4.0.0.tgz", + "integrity": "sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==", + "requires": { + "mimic-fn": "^3.0.0" + } + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "requires": { + "ms": "2.1.2" + } + }, + "debuglog": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", + "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=" + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "requires": { + "clone": "^1.0.2" + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + }, + "detect-indent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.0.0.tgz", + "integrity": "sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==" + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==" + }, + "dezalgo": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", + "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "didyoumean": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.1.tgz", + "integrity": "sha1-6S7f2tplN9SE1zwBcv0eugxJdv8=" + }, + "diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==" + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-serializer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.2.0.tgz", + "integrity": "sha512-n6kZFH/KlCrqs/1GHMOd5i2fd/beQHuehKdWvNNffbGHTr/almdhuVvTVFb3V7fglz+nC50fFusu3lY33h12pA==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.1.0.tgz", + "integrity": "sha512-LsTgx/L5VpD+Q8lmsXSHW2WpA+eBlZ9HPf3erD1IoPF00/3JKHZ3BknUVA2QGDNu69ZNmyFmCWBSO45XjYKC5w==" + }, + "domhandler": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.0.0.tgz", + "integrity": "sha512-KPTbnGQ1JeEMQyO1iYXoagsI6so/C96HZiFyByU3T6iAzpXn8EGEvct6unm1ZGoed8ByO2oirxgwxBmqKF9haA==", + "requires": { + "domelementtype": "^2.1.0" + } + }, + "domutils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.5.0.tgz", + "integrity": "sha512-Ho16rzNMOFk2fPwChGh3D2D9OEHAfG19HgmRR2l+WLSsIstNsAYBzePH412bL0y5T44ejABIVfTHQ8nqi/tBCg==", + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0" + } + }, + "dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "requires": { + "is-obj": "^2.0.0" + } + }, + "drange": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/drange/-/drange-1.1.1.tgz", + "integrity": "sha512-pYxfDYpued//QpnLIm4Avk7rsNtAtQkUES2cwAYSvD/wd2pKD71gN2Ebj3e7klzXwjocvE8c5vx/1fxwpqmSxA==" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "editions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/editions/-/editions-6.1.0.tgz", + "integrity": "sha512-h6nWEyIocfgho9J3sTSuhU/WoFOu1hTX75rPBebNrbF38Y9QFDjCDizYXdikHTySW7Y3mSxli8bpDz9RAtc7rA==", + "requires": { + "errlop": "^4.0.0", + "version-range": "^1.0.0" + } + }, + "ejs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.0.1.tgz", + "integrity": "sha512-cuIMtJwxvzumSAkqaaoGY/L6Fc/t6YvoP9/VIaK0V/CyqKLEQ8sqODmYfy/cjXEdZ9+OOL8TecbJu+1RsofGDw==", + "dev": true + }, + "ejs-include-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ejs-include-regex/-/ejs-include-regex-1.0.0.tgz", + "integrity": "sha1-4vcVdcv9VRrIALJHTB9io45wCTo=", + "dev": true + }, + "ejs-lint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ejs-lint/-/ejs-lint-1.1.0.tgz", + "integrity": "sha512-SnOxzUtJug5C92wtFTZ+Zyb+eoqOlN+WyqDk6HDSXgY5FseDgm8MhZ/r70nkzrh0AMPpifzebep3gGILzAlQNg==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "ejs": "3.0.1", + "ejs-include-regex": "^1.0.0", + "globby": "^11.0.0", + "read-input": "^0.3.1", + "rewire": "^5.0.0", + "syntax-error": "^1.1.6", + "yargs": "^15.0.0" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "requires": { + "iconv-lite": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "optional": true, "requires": { - "pump": "^3.0.0" + "safer-buffer": ">= 2.1.2 < 3.0.0" } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" - }, - "inquirer": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", - "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + } + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==" + }, + "env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==" + }, + "err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" + }, + "errlop": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/errlop/-/errlop-4.1.0.tgz", + "integrity": "sha512-vul6gGBuVt0M2TPi1/WrcL86+Hb3Q2Tpu3TME3sbVhZrYf7J1ZMHCodI25RQKCVurh56qTfvgM0p3w5cT4reSQ==" + }, + "error": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/error/-/error-10.4.0.tgz", + "integrity": "sha512-YxIFEJuhgcICugOUvRx5th0UM+ActZ9sjY0QJmeVwsQdvosZ7kYzc9QqS0Da3R5iUmgU5meGIxh0xBeZpMVeLw==" + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", + "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.2", + "is-string": "^1.0.5", + "object-inspect": "^1.9.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.0" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "eslint": { + "version": "7.22.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.22.0.tgz", + "integrity": "sha512-3VawOtjSJUQiiqac8MQc+w457iGLfuNGLFn8JmF051tTKbh5/x/0vlcEj8OgDCaw7Ysa2Jn8paGshV7x2abKXg==", + "dev": true, + "requires": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.21", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.4", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + } + }, + "eslint-config-airbnb-base": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz", + "integrity": "sha512-GOrQyDtVEc1Xy20U7vsB2yAoB4nBlfH5HZJeatRXHleO+OS5Ot+MWij4Dpltw4/DyIkqUfqz1epfhVR5XWWQPA==", + "dev": true, + "requires": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.2" + } + }, + "eslint-config-prettier": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.1.0.tgz", + "integrity": "sha512-oKMhGv3ihGbCIimCAjqkdzx2Q+jthoqnXSP+d86M9tptwugycmTFdVR4IpLgq2c4SHifbwO90z2fQ8/Aio73yw==", + "dev": true, + "requires": {} + }, + "eslint-import-resolver-node": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.13.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.19", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.6.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "dependencies": { - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "requires": { - "ansi-regex": "^5.0.0" - } - } + "ms": "2.0.0" } }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "is-stream": { + "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" - }, - "jhipster-core": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/jhipster-core/-/jhipster-core-7.3.4.tgz", - "integrity": "sha512-AUhT69kNkqppaJZVfan/xnKG4Gs9Ggj7YLtTZFVe+xg+THrbMb5Ng7PL07PDlDw4KAEA33GMCwuAf65E8EpC4g==", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-module-utils": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", + "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "requires": { - "chevrotain": "7.0.1", - "fs-extra": "8.1.0", - "lodash": "4.17.15", - "winston": "3.2.1" + "ms": "2.0.0" } }, - "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-import": { + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", + "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "array.prototype.flat": "^1.2.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.4", + "eslint-module-utils": "^2.6.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.1", + "read-pkg-up": "^2.0.0", + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "ms": "2.0.0" } }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" - }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, "requires": { - "chalk": "^2.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } + "esutils": "^2.0.2", + "isarray": "^1.0.0" } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-prettier": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz", + "integrity": "sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + }, + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "faker": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/faker/-/faker-5.4.0.tgz", + "integrity": "sha512-Y9n/Ky/xZx/Bj8DePvXspUYRtHl/rGQytoIT5LaxmNwSe3wWyOeOXb3lT6Dpipq240PVpeFaGKzScz/5fvff2g==" + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "fast-glob": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", + "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "requires": { + "@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": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" + }, + "fastq": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", + "integrity": "sha512-7Eczs8gIPDrVzT+EksYBcupqMyxSHXXrHOLRRxU2/DicV8789MRBRR8+Hc2uWzUupOs4YS4JzBmBxjjCVBxD/g==", + "requires": { + "reusify": "^1.0.4" + } + }, + "fecha": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz", + "integrity": "sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg==" + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "filelist": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz", + "integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==", + "requires": { + "minimatch": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "find-yarn-workspace-root2": { + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root2/-/find-yarn-workspace-root2-1.2.16.tgz", + "integrity": "sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==", + "requires": { + "micromatch": "^4.0.2", + "pkg-dir": "^4.2.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "requires": { - "path-key": "^3.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" - }, - "read-pkg-up": { + "locate-path": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-5.0.0.tgz", - "integrity": "sha512-XBQjqOBtTzyol2CpsQOw8LHV0XbDZVG7xMMjmXAJomlVY03WOBRmYgDJETlvcg0H63AJvPRwT7GFi5rvOzUOKg==", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "requires": { - "find-up": "^3.0.0", - "read-pkg": "^5.0.0" + "p-locate": "^4.1.0" } }, - "replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==" - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "p-try": "^2.0.0" } }, - "rxjs": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", - "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "requires": { - "tslib": "^1.9.0" + "p-limit": "^2.2.0" } }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "requires": { - "shebang-regex": "^3.0.0" + "find-up": "^4.0.0" } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + } + } + }, + "first-chunk-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", + "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", + "requires": { + "readable-stream": "^2.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "requires": { - "ansi-regex": "^5.0.0" - } - } + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "ansi-regex": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - } + "safe-buffer": "~5.1.0" } + } + } + }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", + "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", + "dev": true + }, + "fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, + "follow-redirects": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz", + "integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" }, - "through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "requires": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" + "number-is-nan": "^1.0.0" } }, - "type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==" - }, - "vinyl": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", - "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { - "isexe": "^2.0.0" + "ansi-regex": "^2.0.0" } - }, - "yeoman-environment": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-2.10.3.tgz", - "integrity": "sha512-pLIhhU9z/G+kjOXmJ2bPFm3nejfbH+f1fjYRSOteEXDBrv1EoJE/e+kuHixSXfCYfTkxjYsvRaDX+1QykLCnpQ==", - "requires": { - "chalk": "^2.4.1", - "debug": "^3.1.0", - "diff": "^3.5.0", - "escape-string-regexp": "^1.0.2", - "execa": "^4.0.0", - "globby": "^8.0.1", - "grouped-queue": "^1.1.0", - "inquirer": "^7.1.0", - "is-scoped": "^1.0.0", - "lodash": "^4.17.10", - "log-symbols": "^2.2.0", - "mem-fs": "^1.1.0", - "mem-fs-editor": "^6.0.0", - "npm-api": "^1.0.0", - "semver": "^7.1.3", - "strip-ansi": "^4.0.0", - "text-table": "^0.2.0", - "untildify": "^3.0.3", - "yeoman-generator": "^4.8.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } + } + } + }, + "generator-jhipster": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/generator-jhipster/-/generator-jhipster-7.0.0.tgz", + "integrity": "sha512-19u1ESpKl7D/SNCSsvEysS3g7zKOR40j79t0zyL1Oni1jCUsStlFFMXbJ8Bv2qQTN/uegKVsEpllbluF1JlxQQ==", + "requires": { + "aws-sdk": "2.863.0", + "axios": "0.21.1", + "chalk": "4.1.0", + "chevrotain": "8.0.1", + "commander": "7.1.0", + "conf": "9.0.2", + "didyoumean": "1.2.1", + "ejs": "3.1.6", + "faker": "5.4.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "gulp-filter": "6.0.0", + "insight": "0.10.3", + "js-yaml": "4.0.0", + "lodash": "4.17.21", + "minimatch": "3.0.4", + "normalize-path": "3.0.0", + "ora": "5.3.0", + "os-locale": "5.0.0", + "parse-gitignore": "1.0.1", + "pluralize": "8.0.0", + "prettier": "2.2.1", + "prettier-plugin-java": "1.0.2", + "prettier-plugin-packagejson": "2.2.10", + "progress": "2.0.3", + "randexp": "0.5.3", + "semver": "7.3.4", + "shelljs": "0.8.4", + "then-request": "6.0.2", + "through2": "4.0.2", + "uuid": "8.3.2", + "winston": "3.3.3", + "yeoman-environment": "3.2.0", + "yeoman-generator": "5.2.0" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "ejs": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz", + "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==", + "requires": { + "jake": "^10.6.1" } }, - "yeoman-generator": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-4.11.0.tgz", - "integrity": "sha512-++t6t2Z6HjL5F1/UM7+uNvGknKmQdF8tstJx8WKzsUSEpB+19kLVtapSfQIh9uWqm0L59fLWDzUui//WXoynPw==", + "js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", "requires": { - "async": "^2.6.2", - "chalk": "^2.4.2", - "cli-table": "^0.3.1", - "cross-spawn": "^6.0.5", - "dargs": "^6.1.0", - "dateformat": "^3.0.3", - "debug": "^4.1.1", - "diff": "^4.0.1", - "error": "^7.0.2", - "find-up": "^3.0.0", - "github-username": "^3.0.0", - "grouped-queue": "^1.1.0", - "istextorbinary": "^2.5.1", - "lodash": "^4.17.11", - "make-dir": "^3.0.0", - "mem-fs-editor": "^7.0.1", - "minimist": "^1.2.5", - "pretty-bytes": "^5.2.0", - "read-chunk": "^3.2.0", - "read-pkg-up": "^5.0.0", - "rimraf": "^2.6.3", - "run-async": "^2.0.0", - "semver": "^7.2.1", - "shelljs": "^0.8.3", - "text-table": "^0.2.0", - "through2": "^3.0.1", - "yeoman-environment": "^2.9.5" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } - } - }, - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "requires": { - "ms": "2.1.2" - } - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" - }, - "ejs": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.5.tgz", - "integrity": "sha512-dldq3ZfFtgVTJMLjOe+/3sROTzALlL9E34V4/sDtUd/KlBSS0s6U1/+WPE1B4sj9CXHJpL1M6rhNJnc9Wbal9w==", - "requires": { - "jake": "^10.6.1" - } - }, - "globby": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", - "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", - "requires": { - "@types/glob": "^7.1.1", - "array-union": "^1.0.2", - "dir-glob": "^2.2.2", - "fast-glob": "^2.2.6", - "glob": "^7.1.3", - "ignore": "^4.0.3", - "pify": "^4.0.1", - "slash": "^2.0.0" - } - }, - "mem-fs-editor": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-7.1.0.tgz", - "integrity": "sha512-BH6QEqCXSqGeX48V7zu+e3cMwHU7x640NB8Zk8VNvVZniz+p4FK60pMx/3yfkzo6miI6G3a8pH6z7FeuIzqrzA==", - "requires": { - "commondir": "^1.0.1", - "deep-extend": "^0.6.0", - "ejs": "^3.1.5", - "glob": "^7.1.4", - "globby": "^9.2.0", - "isbinaryfile": "^4.0.0", - "mkdirp": "^1.0.0", - "multimatch": "^4.0.0", - "rimraf": "^3.0.0", - "through2": "^3.0.2", - "vinyl": "^2.2.1" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - } + "argparse": "^2.0.1" } } } @@ -3491,25 +12032,25 @@ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, - "get-stdin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", - "dev": true + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } }, "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "requires": { "pump": "^3.0.0" } }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" - }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -3518,21 +12059,17 @@ "assert-plus": "^1.0.0" } }, - "gh-got": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/gh-got/-/gh-got-5.0.0.tgz", - "integrity": "sha1-7pW+NxBv2HSKlvjR20uuqJ4b+oo=", - "requires": { - "got": "^6.2.0", - "is-plain-obj": "^1.1.0" - } + "git-hooks-list": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-1.0.3.tgz", + "integrity": "sha512-Y7wLWcrLUXwk2noSka166byGCvhMtDRpgHdzCno1UQv/n/Hegp++a2xBWJL1lJarnKD3SWaljD+0z1ztqxuKyQ==" }, "github-username": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/github-username/-/github-username-3.0.0.tgz", - "integrity": "sha1-CnciGbMTB0NCnyRW0L3T21Xc57E=", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/github-username/-/github-username-6.0.0.tgz", + "integrity": "sha512-7TTrRjxblSI5l6adk9zd+cV5d6i1OrJSo3Vr9xdGqFLBQo0mz5P9eIfKCDJ7eekVGGFLbce0qbPSnktXV2BjDQ==", "requires": { - "gh-got": "^5.0.0" + "@octokit/rest": "^18.0.6" } }, "glob": { @@ -3549,99 +12086,51 @@ } }, "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "requires": { - "is-extglob": "^2.1.0" - } - } + "is-glob": "^4.0.1" } }, - "glob-to-regexp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=" - }, "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.7.0.tgz", + "integrity": "sha512-Aipsz6ZKRxa/xQkZhNg0qIWXT6x6rD46f6x/PCnBomlttdIyAPak4YD9jTmKpZ72uROSMU87qJtcgpgHaVchiA==", "dev": true, "requires": { - "type-fest": "^0.8.1" + "type-fest": "^0.20.2" } }, "globby": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.2.tgz", - "integrity": "sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w==", - "requires": { - "array-union": "^1.0.1", - "dir-glob": "2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" - }, - "dependencies": { - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "requires": { - "array-uniq": "^1.0.1" - } - } - } - }, - "got": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", - "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.3.tgz", + "integrity": "sha512-ffdmosjA807y7+lA1NM0jELARVmYul/715xiILEjo3hBLPTcirgQNnXECn5g3mtR8TOLCVbkfua1Hpen25/Xcg==", "requires": { - "create-error-class": "^3.0.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-redirect": "^1.0.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "unzip-response": "^2.0.1", - "url-parse-lax": "^1.0.0" + "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" }, "dependencies": { - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==" } } }, "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" }, "grouped-queue": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/grouped-queue/-/grouped-queue-1.1.0.tgz", - "integrity": "sha512-rZOFKfCqLhsu5VqjBjEWiwrYqJR07KxIkH4mLZlNlGDfntbb4FbMyGFP14TlvRPrU9S3Hnn/sgxbC5ZeN0no3Q==", - "requires": { - "lodash": "^4.17.15" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grouped-queue/-/grouped-queue-2.0.0.tgz", + "integrity": "sha512-/PiFUa7WIsl48dUeCvhIHnwNmAAzlI/eHoJl0vu3nsFA366JleY7Ff8EVTplZu5kO0MIdZjKTTnzItL61ahbnw==" }, "growl": { "version": "1.10.5", @@ -3665,42 +12154,27 @@ "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" }, "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "requires": { - "ajv": "^6.5.5", + "ajv": "^6.12.3", "har-schema": "^2.0.0" } }, - "hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==" - }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "requires": { - "ansi-regex": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - } - } + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true }, "has-flag": { "version": "4.0.0", @@ -3708,9 +12182,9 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", "dev": true }, "has-unicode": { @@ -3718,35 +12192,6 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -3759,16 +12204,14 @@ "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" }, "htmlparser2": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", - "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", - "requires": { - "domelementtype": "^1.3.1", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^3.1.1" + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.0.1.tgz", + "integrity": "sha512-GDKPd+vk4jvSuvCbyuzx/unmXkk090Azec7LovXP8as1Hn8q9p3hbjmDGbUqqhknw0ajwit6LiiWqfiTUPMK7w==", + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.4.4", + "entities": "^2.0.0" } }, "http-basic": { @@ -3782,6 +12225,21 @@ "parse-cache-control": "^1.0.1" } }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, "http-response-object": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz", @@ -3791,9 +12249,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.44", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.44.tgz", - "integrity": "sha512-vHPAyBX1ffLcy4fQHmDyIUMUb42gHZjPHU66nhvbMzAWJqHnySGZ6STwN3rwrnSd1FHB0DI/RWgGELgKSYRDmw==" + "version": "10.17.56", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.56.tgz", + "integrity": "sha512-LuAa6t1t0Bfw4CuSR0UITsm1hP17YL+u82kfHGrHUWdhlBtH7sa7jGY5z7glGaIj/WDYDkRtgGd+KCjCzxBW1w==" } } }, @@ -3807,11 +12265,28 @@ "sshpk": "^1.7.0" } }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, "human-signals": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==" }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "requires": { + "ms": "^2.0.0" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -3826,14 +12301,23 @@ "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" }, "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==" + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "requires": { + "minimatch": "^3.0.4" + } }, "import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "requires": { "parent-module": "^1.0.0", @@ -3850,6 +12334,11 @@ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -3884,6 +12373,11 @@ "through": "^2.3.6" }, "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -3920,6 +12414,14 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -3954,14 +12456,6 @@ "color-convert": "^1.9.0" } }, - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "requires": { - "lodash": "^4.17.14" - } - }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -4066,6 +12560,16 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, "pkg-up": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", @@ -4100,42 +12604,35 @@ } }, "interpret": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", - "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" }, "invert-kv": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-3.0.1.tgz", "integrity": "sha512-CYdFeFexxhv/Bcny+Q0BfOV+ltRlJcd4BBZBYFX/O0u4npJrgZtIcjokegtiSMAvlMTJ+Koq0GBCc//3bueQxw==" }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, "ip-regex": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=" }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-bigint": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", + "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", + "dev": true }, "is-binary-path": { "version": "2.1.0", @@ -4146,33 +12643,27 @@ "binary-extensions": "^2.0.0" } }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + "is-boolean-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", + "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } }, "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", "dev": true }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "is-core-module": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", + "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } + "has": "^1.0.3" } }, "is-date-object": { @@ -4181,23 +12672,6 @@ "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", "dev": true }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" - } - } - }, "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", @@ -4229,23 +12703,27 @@ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" }, + "is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=" + }, + "is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true + }, "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "dev": true }, "is-obj": { "version": "2.0.0", @@ -4253,9 +12731,9 @@ "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" }, "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" }, "is-plain-object": { "version": "2.0.4", @@ -4265,42 +12743,28 @@ "isobject": "^3.0.1" } }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" - }, - "is-redirect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", - "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=" - }, "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", + "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", "dev": true, "requires": { - "has": "^1.0.3" + "call-bind": "^1.0.2", + "has-symbols": "^1.0.1" } }, - "is-retry-allowed": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", - "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==" - }, "is-scoped": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-scoped/-/is-scoped-1.0.0.tgz", - "integrity": "sha1-RJypgpnnEwOCViieyytUDcQ3yzA=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-scoped/-/is-scoped-2.1.0.tgz", + "integrity": "sha512-Cv4OpPTHAK9kHYzkzCrof3VJh7H/PrG2MBUMvvJebaaUMbqhm0YAtXnvh0I3Hnj2tMZWwrRROWLSgfJrKqWmlQ==", "requires": { - "scoped-regex": "^1.0.0" + "scoped-regex": "^2.0.0" } }, "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" }, "is-string": { "version": "1.0.5", @@ -4327,11 +12791,6 @@ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" - }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -4358,19 +12817,19 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "istextorbinary": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.6.0.tgz", - "integrity": "sha512-+XRlFseT8B3L9KyjxxLjfXSLMuErKDsd8DBNrsaxoViABMEZlOSCstwmw0qpoFX3+U6yWU1yhLudAe6/lETGGA==", + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-5.12.0.tgz", + "integrity": "sha512-wLDRWD7qpNTYubk04+q3en1+XZGS4vYWK0+SxNSXJLaITMMEK+J3o/TlOMyULeH1qozVZ9uUkKcyMA8odyxz8w==", "requires": { - "binaryextensions": "^2.1.2", - "editions": "^2.2.0", - "textextensions": "^2.5.0" + "binaryextensions": "^4.15.0", + "editions": "^6.1.0", + "textextensions": "^5.11.0" } }, "jake": { - "version": "10.6.1", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.6.1.tgz", - "integrity": "sha512-pHUK3+V0BjOb1XSi95rbBksrMdIqLVC9bJqDnshVyleYsET3H0XAq+3VB2E3notcYvv4wRdRHn13p7vobG+wfQ==", + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", + "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", "requires": { "async": "0.9.x", "chalk": "^2.4.2", @@ -4386,6 +12845,11 @@ "color-convert": "^1.9.0" } }, + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" + }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -4425,12 +12889,12 @@ } }, "java-parser": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/java-parser/-/java-parser-0.8.2.tgz", - "integrity": "sha512-YphTEk4zIpWAHqBriAdjlNnTEcEYQ2xBA8KOH5V7QxggNbxjkeEcKJjNYnQvqEue8+O1TLj7vfL0NVG6x5LGMw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/java-parser/-/java-parser-1.0.2.tgz", + "integrity": "sha512-lBXc+F62ds2W83eH5MwGnzuWdb6kgGBV0x0R7w0B4JKGDrJzolMUEhRMzzzlIX68HvRU7XtfPon22YaB+dVg+A==", "requires": { "chevrotain": "6.5.0", - "lodash": "4.17.20" + "lodash": "4.17.21" }, "dependencies": { "chevrotain": { @@ -4441,11 +12905,6 @@ "regexp-to-ast": "0.4.0" } }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" - }, "regexp-to-ast": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.4.0.tgz", @@ -4453,2035 +12912,2339 @@ } } }, - "jhipster-core": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/jhipster-core/-/jhipster-core-7.3.1.tgz", - "integrity": "sha512-iUHD5W+B3DhsGCMcJEWgD+pU9FdlZLajr2FyP/nUnkBId1LGPsGAYmWID5/COHcLxne3ceSrf/ctqsQz3kpVqg==", + "jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-schema-typed": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-7.0.3.tgz", + "integrity": "sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==" + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-nice": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/json-stringify-nice/-/json-stringify-nice-1.1.2.tgz", + "integrity": "sha512-mc0EsmCq4Ru6jTdKtKvzKzGJPa7eUHXe5/WAprXwyYYR1iY2qTcvaw3QBkPKGfJYvRr5vXoaIvMtttM+/f1xOA==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "just-diff": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/just-diff/-/just-diff-3.0.2.tgz", + "integrity": "sha512-+EiNvacECnZbszZa5IMjzrJ3dy2HKMXyGaNYWBnXy+iWW+437jIvQUrWaM9M+XI/6gOH8EjqvhGUOSh7ETekyg==" + }, + "just-diff-apply": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/just-diff-apply/-/just-diff-apply-3.0.0.tgz", + "integrity": "sha512-K2MLc+ZC2DVxX4V61bIKPeMUUfj1YYZ3h0myhchDXOW1cKoPZMnjIoNCqv9bF2n5Oob1PFxuR2gVJxkxz4e58w==" + }, + "just-extend": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", + "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==", + "dev": true + }, + "kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + }, + "lcid": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-3.1.1.tgz", + "integrity": "sha512-M6T051+5QCGLBQb8id3hdvIW8+zeFV2FyBGFS9IEK5H9Wt4MueD4bW1eWikpHgZp+5xR3l5c8pZUkQsIA0BFZg==", + "requires": { + "invert-kv": "^3.0.0" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "load-yaml-file": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/load-yaml-file/-/load-yaml-file-0.2.0.tgz", + "integrity": "sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==", + "requires": { + "graceful-fs": "^4.1.5", + "js-yaml": "^3.13.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + } + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", + "dev": true + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "requires": { + "chalk": "^4.0.0" + } + }, + "logform": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz", + "integrity": "sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==", + "requires": { + "colors": "^1.2.1", + "fast-safe-stringify": "^2.0.4", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "triple-beam": "^1.3.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "macos-release": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.4.1.tgz", + "integrity": "sha512-H/QHeBIN1fIGJX517pvK8IEK53yQOW7YcEI55oYtgjDdoCQQz7eJS94qt5kNrscReEyuD/JcdFCm2XBEcGOITg==" + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "make-fetch-happen": { + "version": "8.0.14", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-8.0.14.tgz", + "integrity": "sha512-EsS89h6l4vbfJEtBZnENTOFk8mCRpY5ru36Xe5bcX1KYIli2mkSHqoFsp5O1wMDvTJJzxe/4THpCTtygjeeGWQ==", + "requires": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.0.5", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^5.0.0", + "ssri": "^8.0.0" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "requires": { + "p-defer": "^1.0.0" + } + }, + "mem": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-5.1.1.tgz", + "integrity": "sha512-qvwipnozMohxLXG1pOqoLiZKNkC4r4qqRucSoDwXowsNGDSULiqFTRUF05vcZWnwJSG22qTsynQhxbaMtnX9gw==", + "requires": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^2.1.0", + "p-is-promise": "^2.1.0" + }, + "dependencies": { + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + } + } + }, + "mem-fs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-1.2.0.tgz", + "integrity": "sha512-b8g0jWKdl8pM0LqAPdK9i8ERL7nYrzmJfRhxMiWH2uYdfYnb7uXnmwVb0ZGe7xyEl4lj+nLIU3yf4zPUT+XsVQ==", "requires": { - "chevrotain": "7.0.1", - "fs-extra": "8.1.0", - "lodash": "4.17.15", - "winston": "3.2.1" + "through2": "^3.0.0", + "vinyl": "^2.0.1", + "vinyl-file": "^3.0.0" }, "dependencies": { - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "inherits": "^2.0.4", + "readable-stream": "2 || 3" } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" } } }, - "jmespath": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", - "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" + "mem-fs-editor": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-8.0.0.tgz", + "integrity": "sha512-0+6Zp44EmPpF01MZOlY0kt7JTndjdvALo4jA7Kk9GPCuqGzGnBmWtcE44Cwzj1aru57IN5/LKIWd1lIvaT6sKw==", + "requires": { + "commondir": "^1.0.1", + "deep-extend": "^0.6.0", + "ejs": "^3.1.5", + "globby": "^11.0.1", + "isbinaryfile": "^4.0.0", + "multimatch": "^5.0.0", + "normalize-path": "^3.0.0", + "through2": "^4.0.2", + "vinyl": "^2.2.1" + }, + "dependencies": { + "ejs": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz", + "integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==", + "requires": { + "jake": "^10.6.1" + } + }, + "multimatch": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", + "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==", + "requires": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + } + } + } }, - "js-object-pretty-print": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/js-object-pretty-print/-/js-object-pretty-print-0.3.0.tgz", - "integrity": "sha1-RnDkUAZu4ezPNRdMfRl/WqOLz3Q=" + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "braces": "^3.0.1", + "picomatch": "^2.0.5" } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + "mime-db": { + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", + "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==" }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "mime-types": { + "version": "2.1.29", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", + "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", + "requires": { + "mime-db": "1.46.0" + } }, - "json-schema-typed": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-7.0.3.tgz", - "integrity": "sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==" + "mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==" }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", "requires": { - "graceful-fs": "^4.1.6" + "yallist": "^4.0.0" } }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" + "minipass": "^3.0.0" } }, - "just-extend": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.0.tgz", - "integrity": "sha512-ApcjaOdVTJ7y4r08xI5wIqpvwS48Q0PBG4DJROcEkH1f8MdAiNFyFxz3xoL0LWAVwjrwPYZdVHHxhRHcx/uGLA==", - "dev": true + "minipass-fetch": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.3.3.tgz", + "integrity": "sha512-akCrLDWfbdAWkMLBxJEeWTdNsjML+dt5YgOI4gJ53vuO0vrmYQkUPxa6j6V65s9CcePIr2SSWqjT2EcrNseryQ==", + "requires": { + "encoding": "^0.1.12", + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + } }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "requires": { + "minipass": "^3.0.0" + } }, - "kuler": { + "minipass-json-stream": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", - "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", + "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", + "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", "requires": { - "colornames": "^1.1.1" + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" } }, - "lazy-cache": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", - "integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=", + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "requires": { - "set-getter": "^0.1.0" + "minipass": "^3.0.0" } }, - "lcid": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-3.1.1.tgz", - "integrity": "sha512-M6T051+5QCGLBQb8id3hdvIW8+zeFV2FyBGFS9IEK5H9Wt4MueD4bW1eWikpHgZp+5xR3l5c8pZUkQsIA0BFZg==", + "minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", "requires": { - "invert-kv": "^3.0.0" + "minipass": "^3.0.0" } }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "minipass": "^3.0.0", + "yallist": "^4.0.0" } }, - "lines-and-columns": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" }, - "load-json-file": { + "mkdirp-infer-owner": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "resolved": "https://registry.npmjs.org/mkdirp-infer-owner/-/mkdirp-infer-owner-2.0.0.tgz", + "integrity": "sha512-sdqtiFt3lkOaYvTXSRIUjkIdPTcxgv5+fgqYE/5qgwdw12cOrAuzzgzvVExIkH/ul1oeHN3bCLOWSG3XOqbKKw==", + "requires": { + "chownr": "^2.0.0", + "infer-owner": "^1.0.4", + "mkdirp": "^1.0.3" + } + }, + "mocha": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.2.tgz", + "integrity": "sha512-UdmISwr/5w+uXLPKspgoV7/RXZwKRTiTjJ2/AC5ZiEztIoOYdfKb19+9jNmEInzx5pBsCyJQzarAxqIGBNYJhg==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.1", + "debug": "4.3.1", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.0.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.1.20", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.1.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" }, "dependencies": { - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "requires": { - "error-ex": "^1.2.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, - "strip-bom": { + "is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", + "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } } } }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "multimatch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", + "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" } }, - "lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" - }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=" + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" }, - "lodash.difference": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", - "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=" + "nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "dev": true }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "lodash.pad": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/lodash.pad/-/lodash.pad-4.5.1.tgz", - "integrity": "sha1-QzCUmoM6fI2iLMIPaibE1Z3runA=" + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, + "nise": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", + "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + }, + "node-gyp": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz", + "integrity": "sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==", + "requires": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.3", + "nopt": "^5.0.0", + "npmlog": "^4.1.2", + "request": "^2.88.2", + "rimraf": "^3.0.2", + "semver": "^7.3.2", + "tar": "^6.0.2", + "which": "^2.0.2" + } + }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, - "lodash.padend": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", - "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=" + "npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } }, - "lodash.padstart": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", - "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=" + "npm-install-checks": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-4.0.0.tgz", + "integrity": "sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==", + "requires": { + "semver": "^7.1.1" + } }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" }, - "log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "npm-package-arg": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.2.tgz", + "integrity": "sha512-6Eem455JsSMJY6Kpd3EyWE+n5hC+g9bSyHr9K9U2zqZb7+02+hObQ2c0+8iDk/mNF+8r1MhY44WypKJAkySIYA==", "requires": { - "chalk": "^2.4.2" + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "hosted-git-info": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", + "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "requires": { - "has-flag": "^3.0.0" + "lru-cache": "^6.0.0" } } } }, - "logform": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.1.2.tgz", - "integrity": "sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ==", + "npm-packlist": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-2.1.5.tgz", + "integrity": "sha512-KCfK3Vi2F+PH1klYauoQzg81GQ8/GGjQRKYY6tRnpQUPKTs/1gBZSRWtTEd7jGdSn1LZL7gpAmJT+BcS55k2XQ==", "requires": { - "colors": "^1.2.1", - "fast-safe-stringify": "^2.0.4", - "fecha": "^2.3.3", - "ms": "^2.1.1", - "triple-beam": "^1.3.0" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } + "glob": "^7.1.6", + "ignore-walk": "^3.0.3", + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" } }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + "npm-pick-manifest": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.1.tgz", + "integrity": "sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA==", + "requires": { + "npm-install-checks": "^4.0.0", + "npm-normalize-package-bin": "^1.0.1", + "npm-package-arg": "^8.1.2", + "semver": "^7.3.4" + } }, - "macos-release": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.3.0.tgz", - "integrity": "sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA==" + "npm-registry-fetch": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-9.0.0.tgz", + "integrity": "sha512-PuFYYtnQ8IyVl6ib9d3PepeehcUeHN9IO5N/iCRhyg9tStQcqGQBRVHmfmMWPDERU3KwZoHFvbJ4FPXPspvzbA==", + "requires": { + "@npmcli/ci-detect": "^1.0.0", + "lru-cache": "^6.0.0", + "make-fetch-happen": "^8.0.9", + "minipass": "^3.1.3", + "minipass-fetch": "^1.3.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.0.0", + "npm-package-arg": "^8.0.0" + } }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } + "path-key": "^3.0.0" } }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "requires": { - "p-defer": "^1.0.0" + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" } }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + "nth-check": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz", + "integrity": "sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==", + "requires": { + "boolbase": "^1.0.0" + } }, - "map-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.1.0.tgz", - "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==" + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-inspect": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", + "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, "requires": { - "object-visit": "^1.0.0" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" } }, - "mem": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/mem/-/mem-5.1.1.tgz", - "integrity": "sha512-qvwipnozMohxLXG1pOqoLiZKNkC4r4qqRucSoDwXowsNGDSULiqFTRUF05vcZWnwJSG22qTsynQhxbaMtnX9gw==", + "object.entries": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.3.tgz", + "integrity": "sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg==", + "dev": true, "requires": { - "map-age-cleaner": "^0.1.3", - "mimic-fn": "^2.1.0", - "p-is-promise": "^2.1.0" + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1", + "has": "^1.0.3" } }, - "mem-fs": { + "object.values": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-1.1.3.tgz", - "integrity": "sha1-uK6NLj/Lb10/kWXBLUVRoGXZicw=", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.3.tgz", + "integrity": "sha512-nkF6PfDB9alkOUxpf1HNm/QlkeW3SReqL5WXeBLpEJJnlPSvRaDQpW3gQTksTN3fgJX4hL42RzKyOin6ff3tyw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2", + "has": "^1.0.3" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "requires": { + "fn.name": "1.x.x" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "requires": { - "through2": "^2.0.0", - "vinyl": "^1.1.0", - "vinyl-file": "^2.0.0" + "mimic-fn": "^2.1.0" }, "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" } } }, - "mem-fs-editor": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-6.0.0.tgz", - "integrity": "sha512-e0WfJAMm8Gv1mP5fEq/Blzy6Lt1VbLg7gNnZmZak7nhrBTibs+c6nQ4SKs/ZyJYHS1mFgDJeopsLAv7Ow0FMFg==", + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, "requires": { - "commondir": "^1.0.1", - "deep-extend": "^0.6.0", - "ejs": "^2.6.1", - "glob": "^7.1.4", - "globby": "^9.2.0", - "isbinaryfile": "^4.0.0", - "mkdirp": "^0.5.0", - "multimatch": "^4.0.0", - "rimraf": "^2.6.3", - "through2": "^3.0.1", - "vinyl": "^2.2.0" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "ora": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", + "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", + "requires": { + "bl": "^4.0.3", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "log-symbols": "^4.0.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" }, - "dependencies": { - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "requires": { - "array-uniq": "^1.0.1" - } - }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" - }, - "dir-glob": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", - "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", - "requires": { - "path-type": "^3.0.0" - } - }, - "ejs": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", - "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==" - }, - "globby": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", - "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", - "requires": { - "@types/glob": "^7.1.1", - "array-union": "^1.0.2", - "dir-glob": "^2.2.2", - "fast-glob": "^2.2.6", - "glob": "^7.1.3", - "ignore": "^4.0.3", - "pify": "^4.0.1", - "slash": "^2.0.0" - } - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dependencies": { + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "requires": { - "minimist": "^1.2.5" + "restore-cursor": "^3.1.0" } }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" - }, - "replace-ext": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", - "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==" - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==" - }, - "vinyl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" } } } }, - "meow": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-6.1.0.tgz", - "integrity": "sha512-iIAoeI01v6pmSfObAAWFoITAA4GgiT45m4SmJgoxtZfvI0fyZwhV4d0lTwiUXvAKIPlma05Feb2Xngl52Mj5Cg==", - "requires": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.1.1", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.0.0", - "minimist-options": "^4.0.1", - "normalize-package-data": "^2.5.0", - "read-pkg-up": "^7.0.0", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.8.1", - "yargs-parser": "^18.1.1" + "os-locale": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-5.0.0.tgz", + "integrity": "sha512-tqZcNEDAIZKBEPnHPlVDvKrp7NzgLi7jRmhKiUoa2NUmhl13FtkAGLUVR+ZsYvApBQdBfYm43A4tXXQ4IrYLBA==", + "requires": { + "execa": "^4.0.0", + "lcid": "^3.0.0", + "mem": "^5.0.0" } }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + "os-name": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-3.1.0.tgz", + "integrity": "sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==", + "requires": { + "macos-release": "^2.2.0", + "windows-release": "^3.1.0" + } }, - "merge2": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", - "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==" + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=" + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==" + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "requires": { - "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" + "yocto-queue": "^0.1.0" } }, - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "requires": { + "p-limit": "^3.0.2" + } }, - "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "requires": { - "mime-db": "1.44.0" + "aggregate-error": "^3.0.0" } }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, - "min-indent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.0.tgz", - "integrity": "sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY=" + "pacote": { + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-11.3.1.tgz", + "integrity": "sha512-TymtwoAG12cczsJIrwI/euOQKtjrQHlD0k0oyt9QSmZGpqa+KdlxKdWR/YUjYizkixaVyztxt/Wsfo8bL3A6Fg==", + "requires": { + "@npmcli/git": "^2.0.1", + "@npmcli/installed-package-contents": "^1.0.6", + "@npmcli/promise-spawn": "^1.2.0", + "@npmcli/run-script": "^1.8.2", + "cacache": "^15.0.5", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "infer-owner": "^1.0.4", + "minipass": "^3.1.3", + "mkdirp": "^1.0.3", + "npm-package-arg": "^8.0.1", + "npm-packlist": "^2.1.4", + "npm-pick-manifest": "^6.0.0", + "npm-registry-fetch": "^9.0.0", + "promise-retry": "^2.0.1", + "read-package-json-fast": "^2.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.1.0" + } }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "callsites": "^3.0.0" } }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "parse-cache-control": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", + "integrity": "sha1-juqz5U+laSD+Fro493+iGqzC104=" }, - "minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "parse-conflict-json": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parse-conflict-json/-/parse-conflict-json-1.1.1.tgz", + "integrity": "sha512-4gySviBiW5TRl7XHvp1agcS7SOe0KZOjC//71dzZVWJrY9hCrgtvl5v3SyIxCZ4fZF47TxD9nfzmxcx76xmbUw==", + "requires": { + "json-parse-even-better-errors": "^2.3.0", + "just-diff": "^3.0.1", + "just-diff-apply": "^3.0.0" + } + }, + "parse-gitignore": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-gitignore/-/parse-gitignore-1.0.1.tgz", + "integrity": "sha512-UGyowyjtx26n65kdAMWhm6/3uy5uSrpcuH7tt+QEVudiBoVS+eqHxD5kbi9oWVRwj7sCzXqwuM+rUGw7earl6A==" + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "requires": { + "parse5": "^6.0.1" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" + "isarray": "0.0.1" }, "dependencies": { - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true } } }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" + }, + "pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pipeline-pipe": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/pipeline-pipe/-/pipeline-pipe-0.1.5.tgz", + "integrity": "sha512-HFub9yAfxEWBZZmsA12dWiFpg9+er8Sp7bpVwKP41AsAeO6570PVhU2Ckkt8fMnHBwm1edLLg2wIfpNGCDvI0Q==", "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" + "cyclist": "^1.0.1", + "readable-stream": "^3.6.0" } }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" - }, - "mocha": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.1.2.tgz", - "integrity": "sha512-o96kdRKMKI3E8U0bjnfqW4QMk12MwZ4mhdBTf+B5a1q9+aq2HRnj+3ZdJu0B/ZhJeK78MgYuv6L8d/rA5AeBJA==", + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", "dev": true, "requires": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "chokidar": "3.3.0", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "3.0.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.5", - "ms": "2.1.1", - "node-environment-flags": "1.0.6", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.0" + "find-up": "^2.1.0" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", "dev": true, "requires": { - "ms": "^2.1.1" + "locate-path": "^2.0.0" } }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "dev": true, "requires": { - "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" + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" } }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, "requires": { - "minimist": "^1.2.5" + "p-try": "^1.0.0" } }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "p-limit": "^1.1.0" } }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, - "supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "requires": { - "has-flag": "^3.0.0" + "locate-path": "^3.0.0" } }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" } }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "requires": { - "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" + "p-try": "^2.0.0" } }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "p-limit": "^2.0.0" } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" } } }, - "moment": { - "version": "2.26.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.26.0.tgz", - "integrity": "sha512-oIixUO+OamkUkwjhAVE18rAMfRJNsNe/Stid/gwHSOfHrOtw9EhAY2AHvdKZ/k/MggcYELFCJz/Sn2pL8b8JMw==" - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "multimatch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", - "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", + "plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", "requires": { - "@types/minimatch": "^3.0.3", - "array-differ": "^3.0.0", - "array-union": "^2.1.0", - "arrify": "^2.0.1", - "minimatch": "^3.0.4" + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + }, + "dependencies": { + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "requires": { + "ansi-wrap": "^0.1.0" + } + } } }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + "pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==" }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "preferred-pm": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/preferred-pm/-/preferred-pm-3.0.3.tgz", + "integrity": "sha512-+wZgbxNES/KlJs9q40F/1sfOd/j7f1O9JaHcW5Dsn3aUUOZg3L2bjpVUcKV2jvtElYfoTuQiNeMfQJ4kwUAhCQ==", "requires": { - "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" + "find-up": "^5.0.0", + "find-yarn-workspace-root2": "1.2.16", + "path-exists": "^4.0.0", + "which-pm": "2.0.0" } }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + "prettier": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", + "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==" }, - "nise": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.3.tgz", - "integrity": "sha512-EGlhjm7/4KvmmE6B/UFsKh7eHykRl9VH+au8dduHLCyWUO/hr7+N+WtTvDUwc9zHuM1IaIJs/0lQ6Ag1jDkQSg==", + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, "requires": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" + "fast-diff": "^1.1.2" } }, - "node-environment-flags": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", - "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", - "dev": true, + "prettier-plugin-java": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/prettier-plugin-java/-/prettier-plugin-java-1.0.2.tgz", + "integrity": "sha512-YgcN1WGZlrH0E+bHdqtIYtfDp6k2PHBnIaGjzdff/7t/NyDWAA6ypAmnD7YQVG2OuoIaXYkC37HN7cz68lLWLg==", "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } + "java-parser": "1.0.2", + "lodash": "4.17.21", + "prettier": "2.2.1" } }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "prettier-plugin-packagejson": { + "version": "2.2.10", + "resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.2.10.tgz", + "integrity": "sha512-/meFZrpGSg/F3jXspBJikHBLf/m1ol6XJjYslM++AQno7B/SPNrGICMMck0qHBU+f7vVfqbZmdC/OO5opU3HPw==", "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } + "sort-package-json": "1.49.0" } }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, - "npm-api": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/npm-api/-/npm-api-1.0.0.tgz", - "integrity": "sha512-gtJhIhGq07g9H5sIAB9TZzTySW8MYtcYqg+e+J+5q1GmDsDLLVfyvVBL1VklzjtRsElph11GUtLBS191RDOJxQ==", - "requires": { - "JSONStream": "^1.3.5", - "clone-deep": "^4.0.1", - "download-stats": "^0.3.4", - "moment": "^2.24.0", - "paged-request": "^2.0.1", - "request": "^2.88.0" - } + "pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==" }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "requires": { - "path-key": "^2.0.0" - } + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, - "npmlog": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-2.0.4.tgz", - "integrity": "sha1-mLUlMPJRTKkNCexbIsiEZyI3VpI=", - "requires": { - "ansi": "~0.3.1", - "are-we-there-yet": "~1.1.2", - "gauge": "~1.2.5" - } + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" }, - "nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "promise": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz", + "integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==", "requires": { - "boolbase": "~1.0.0" + "asap": "~2.0.6" } }, - "number-is-nan": { + "promise-all-reject-late": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + "resolved": "https://registry.npmjs.org/promise-all-reject-late/-/promise-all-reject-late-1.0.1.tgz", + "integrity": "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw==" }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + "promise-call-limit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-call-limit/-/promise-call-limit-1.0.1.tgz", + "integrity": "sha512-3+hgaa19jzCGLuSCbieeRsu5C2joKfYn8pY6JAuXFRVfF4IO+L7UPpFWNTeWT9pM7uhskvbPPd/oEOktCn317Q==" }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } + "err-code": "^2.0.2", + "retry": "^0.12.0" } }, - "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "requires": { - "isobject": "^3.0.0" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, - "object.entries": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz", - "integrity": "sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "has": "^1.0.3" - } + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, - "object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - } + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "randexp": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.5.3.tgz", + "integrity": "sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w==", "requires": { - "isobject": "^3.0.1" + "drange": "^1.0.2", + "ret": "^0.2.0" } }, - "object.values": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", - "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" + "safe-buffer": "^5.1.0" } }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "read-chunk": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-3.2.0.tgz", + "integrity": "sha512-CEjy9LCzhmD7nUpJ1oVOE6s/hBkejlcJEgLQHVnQznOSilOPb+kpKktlLfFDK3/WP43+F80xkUTM2VOkYoSYvQ==", "requires": { - "wrappy": "1" + "pify": "^4.0.1", + "with-open-file": "^0.1.6" + }, + "dependencies": { + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" + } } }, - "one-time": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", - "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=" + "read-cmd-shim": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-2.0.0.tgz", + "integrity": "sha512-HJpV9bQpkl6KwjxlJcBoqu9Ba0PQg8TqSNIOrulGt54a0uup0HtevreFHzYzkm0lpnleRdNBzXznKrgxglEHQw==" }, - "onetime": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", - "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", - "requires": { - "mimic-fn": "^2.1.0" - } + "read-input": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/read-input/-/read-input-0.3.1.tgz", + "integrity": "sha1-WzFpMIATRk/9puyS5Y0tPOqUjfE=", + "dev": true }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, + "read-package-json-fast": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.2.tgz", + "integrity": "sha512-5fyFUyO9B799foVk4n6ylcoAktG/FbE3jwRKxvwaeSrIunaoMc0u81dzXxjeAFKOce7O5KncdfwpGvvs6r5PsQ==", "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "json-parse-even-better-errors": "^2.3.0", + "npm-normalize-package-bin": "^1.0.1" } }, - "ora": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/ora/-/ora-4.0.4.tgz", - "integrity": "sha512-77iGeVU1cIdRhgFzCK8aw1fbtT1B/iZAvWjS+l/o1x0RShMgxHUZaD2yDpWsNCPwXg9z1ZA78Kbdvr8kBmG/Ww==", + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, "requires": { - "chalk": "^3.0.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.2.0", - "is-interactive": "^1.0.0", - "log-symbols": "^3.0.0", - "mute-stream": "0.0.8", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, "requires": { - "ansi-regex": "^5.0.0" + "pify": "^2.0.0" } } } }, - "os-locale": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-5.0.0.tgz", - "integrity": "sha512-tqZcNEDAIZKBEPnHPlVDvKrp7NzgLi7jRmhKiUoa2NUmhl13FtkAGLUVR+ZsYvApBQdBfYm43A4tXXQ4IrYLBA==", + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, "requires": { - "execa": "^4.0.0", - "lcid": "^3.0.0", - "mem": "^5.0.0" + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" }, "dependencies": { - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "locate-path": "^2.0.0" } }, - "execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" } }, - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, "requires": { - "pump": "^3.0.0" + "p-try": "^1.0.0" } }, - "is-stream": { + "p-locate": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, "requires": { - "path-key": "^3.0.0" + "p-limit": "^1.1.0" } }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { - "shebang-regex": "^3.0.0" - } + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true }, - "shebang-regex": { + "path-exists": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true } } }, - "os-name": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-3.1.0.tgz", - "integrity": "sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==", - "requires": { - "macos-release": "^2.2.0", - "windows-release": "^3.1.0" - } - }, - "os-shim": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz", - "integrity": "sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc=" - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" - }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=" - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" - }, - "p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==" - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" - }, - "paged-request": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/paged-request/-/paged-request-2.0.1.tgz", - "integrity": "sha512-C0bB/PFk9rQskD1YEiz7uuchzqKDQGgdsEHN1ahify0UUWzgmMK4NDG9fhlQg2waogmNFwEvEeHfMRvJySpdVw==", + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "requires": { - "axios": "^0.18.0" - }, - "dependencies": { - "axios": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz", - "integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==", - "requires": { - "follow-redirects": "1.5.10", - "is-buffer": "^2.0.2" - } - }, - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==" - } + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, + "readdir-scoped-modules": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", + "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", "requires": { - "callsites": "^3.0.0" + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" } }, - "parse-cache-control": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", - "integrity": "sha1-juqz5U+laSD+Fro493+iGqzC104=" - }, - "parse-gitignore": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-gitignore/-/parse-gitignore-1.0.1.tgz", - "integrity": "sha512-UGyowyjtx26n65kdAMWhm6/3uy5uSrpcuH7tt+QEVudiBoVS+eqHxD5kbi9oWVRwj7sCzXqwuM+rUGw7earl6A==" - }, - "parse-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", - "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1", - "lines-and-columns": "^1.1.6" + "picomatch": "^2.2.1" } }, - "parse5": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", - "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "requires": { - "@types/node": "*" + "resolve": "^1.1.6" } }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + "regexp-to-ast": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", + "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==" }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=" + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" }, - "path-is-absolute": { + "replace-ext": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==" }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "requires": { - "isarray": "0.0.1" + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" }, "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" } } }, - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "requires": { - "pify": "^3.0.0" - } - }, - "pathval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "requires": { - "pinkie": "^2.0.0" + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "dependencies": { + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "requires": { + "mimic-fn": "^1.0.0" + } + } } }, - "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "ret": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", + "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==" + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + }, + "rewire": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/rewire/-/rewire-5.0.0.tgz", + "integrity": "sha512-1zfitNyp9RH5UDyGGLe9/1N0bMlPQ0WrX0Tmg11kMHBpqwPJI4gfPpP7YngFyLbFmhXh19SToAG0sKKEFcOIJA==", "dev": true, "requires": { - "find-up": "^2.1.0" + "eslint": "^6.8.0" }, "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + } + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "eslint": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.3", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", "dev": true, "requires": { - "locate-path": "^2.0.0" + "eslint-visitor-keys": "^1.1.0" } }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", "dev": true, "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.1.0" } }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "requires": { - "p-try": "^1.0.0" + "escape-string-regexp": "^1.0.5" } }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", "dev": true, "requires": { - "p-limit": "^1.1.0" + "flat-cache": "^2.0.1" } }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", "dev": true - } - } - }, - "pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", - "requires": { - "find-up": "^3.0.0" - } - }, - "plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "requires": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - }, - "dependencies": { - "ansi-colors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, "requires": { - "ansi-wrap": "^0.1.0" + "type-fest": "^0.8.1" } - } - } - }, - "pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==" - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" - }, - "prettier": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz", - "integrity": "sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==" - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, - "prettier-plugin-java": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/prettier-plugin-java/-/prettier-plugin-java-0.8.2.tgz", - "integrity": "sha512-G11PMutlfhUjLqmrB0gW9n6hTIvlnXX+lhzgH3Uhc1QSlDQoLBky5lNSRgvdYSDPpSF3DmyYd3/7U3Ez8n0ckg==", - "requires": { - "java-parser": "0.8.2", - "lodash": "4.17.20", - "prettier": "2.1.1" - }, - "dependencies": { - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, - "prettier": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.1.tgz", - "integrity": "sha512-9bY+5ZWCfqj3ghYBLxApy2zf6m+NJo5GzmLTpr9FsApsfjriNnS2dahWReHMi7qNPhhHl9SYHJs2cHZLgexNIw==" - } - } - }, - "pretty-bytes": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.3.0.tgz", - "integrity": "sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg==" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" - }, - "promise": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz", - "integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==", - "requires": { - "asap": "~2.0.6" - } - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" - }, - "quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==" - }, - "randexp": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.5.3.tgz", - "integrity": "sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w==", - "requires": { - "drange": "^1.0.2", - "ret": "^0.2.0" - } - }, - "read-chunk": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-3.2.0.tgz", - "integrity": "sha512-CEjy9LCzhmD7nUpJ1oVOE6s/hBkejlcJEgLQHVnQznOSilOPb+kpKktlLfFDK3/WP43+F80xkUTM2VOkYoSYvQ==", - "requires": { - "pify": "^4.0.1", - "with-open-file": "^0.1.6" - }, - "dependencies": { - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==" - } - } - }, - "read-input": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/read-input/-/read-input-0.3.1.tgz", - "integrity": "sha1-WzFpMIATRk/9puyS5Y0tPOqUjfE=", - "dev": true - }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==" - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "inquirer": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.19", + "mute-stream": "0.0.8", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" } }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, "requires": { - "p-locate": "^4.1.0" + "minimist": "^1.2.5" } }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, "requires": { - "p-limit": "^2.2.0" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" } }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" - } - } - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdirp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", - "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", - "dev": true, - "requires": { - "picomatch": "^2.0.4" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "requires": { - "resolve": "^1.1.6" - } - }, - "redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "requires": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexp-to-ast": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", - "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==" - }, - "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", - "dev": true - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==" - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" - }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "prelude-ls": "~1.1.2" } }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - } - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - }, - "dependencies": { - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "isexe": "^2.0.0" } } } }, - "ret": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", - "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==" - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rewire": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/rewire/-/rewire-5.0.0.tgz", - "integrity": "sha512-1zfitNyp9RH5UDyGGLe9/1N0bMlPQ0WrX0Tmg11kMHBpqwPJI4gfPpP7YngFyLbFmhXh19SToAG0sKKEFcOIJA==", - "dev": true, - "requires": { - "eslint": "^6.8.0" - } - }, "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "requires": { "glob": "^7.1.3" } }, "run-async": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.0.tgz", - "integrity": "sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg==", - "requires": { - "is-promise": "^2.1.0" - } + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" }, "run-parallel": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", - "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", - "dev": true - }, - "rx": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", - "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "requires": { + "queue-microtask": "^1.2.2" + } }, "rxjs": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", - "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", "requires": { "tslib": "^1.9.0" } }, "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "requires": { - "ret": "~0.1.10" - }, - "dependencies": { - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" - } - } + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safer-buffer": { "version": "2.1.2", @@ -6494,75 +15257,44 @@ "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" }, "scoped-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/scoped-regex/-/scoped-regex-1.0.0.tgz", - "integrity": "sha1-o0a7Gs1CB65wvXwMfKnlZra63bg=" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/scoped-regex/-/scoped-regex-2.1.0.tgz", + "integrity": "sha512-g3WxHrqSWCZHGHlSrF51VXFdjImhwvH8ZO/pryFH56Qi0cDsZfylQa/t0jCzVQFNbNvM00HfHjkDPEuarKDSWQ==" }, "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-getter": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz", - "integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", "requires": { - "to-object-path": "^0.3.0" + "lru-cache": "^6.0.0" } }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - } + "randombytes": "^2.1.0" } }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "requires": { - "kind-of": "^6.0.2" - } + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "requires": { - "shebang-regex": "^1.0.0" + "shebang-regex": "^3.0.0" } }, "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "shelljs": { "version": "0.8.4", @@ -6585,20 +15317,26 @@ "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", "requires": { "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + } } }, "sinon": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.0.2.tgz", - "integrity": "sha512-0uF8Q/QHkizNUmbK3LRFqx5cpTttEVXudywY9Uwzy8bTfZUhljZ7ARzSxnRHWYWtVTeh4Cw+tTb3iU21FQVO9A==", + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", + "integrity": "sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg==", "dev": true, "requires": { - "@sinonjs/commons": "^1.7.2", + "@sinonjs/commons": "^1.8.1", "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/formatio": "^5.0.1", - "@sinonjs/samsam": "^5.0.3", + "@sinonjs/samsam": "^5.3.1", "diff": "^4.0.2", - "nise": "^4.0.1", + "nise": "^4.0.4", "supports-color": "^7.1.0" }, "dependencies": { @@ -6611,188 +15349,93 @@ } }, "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" }, "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true } } }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "smart-buffer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", + "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==" + }, + "socks": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.0.tgz", + "integrity": "sha512-mNmr9owlinMplev0Wd7UHFlqI4ofnBnNzFuzrm63PPaHgbkqCFe4T5LzwKmtQ/f2tX0NTpcdVLyD/FHxFBstYw==", "requires": { - "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" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - } + "ip": "^1.1.5", + "smart-buffer": "^4.1.0" } }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "socks-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.0.tgz", + "integrity": "sha512-lEpa1zsWCChxiynk+lCycKuC502RxDWLKJZoIhnxrWNjLSDGYRFflHA1/228VkRcnv9TIb8w98derGbpKxJRgA==", "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } + "agent-base": "6", + "debug": "4", + "socks": "^2.3.3" } }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "requires": { - "kind-of": "^3.2.0" + "sort-object-keys": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz", + "integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==" + }, + "sort-package-json": { + "version": "1.49.0", + "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-1.49.0.tgz", + "integrity": "sha512-3YuqFGThwc9X0TZLYohOUJJ/P6uJIVcTeuJOc6ZWw4f1fHpTHIfVysKer4qXtrZ2zvwwU2aEcb555Bo+2fwIgQ==", + "requires": { + "detect-indent": "^6.0.0", + "detect-newline": "3.1.0", + "git-hooks-list": "1.0.3", + "globby": "10.0.0", + "is-plain-obj": "2.1.0", + "sort-object-keys": "^1.1.3" }, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "globby": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.0.tgz", + "integrity": "sha512-3LifW9M4joGZasyYPz2A1U74zbC/45fvpXUvO/9KbSa+VV0aGZarWkfdgKyR9sExNP0t0x0ss/UMJpNpcaTspw==", "requires": { - "is-buffer": "^1.1.5" + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" } + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==" } } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "requires": { - "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-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" - }, - "spawn-sync": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz", - "integrity": "sha1-sAeZVX63+wyDdsKdROih6mfldHY=", - "requires": { - "concat-stream": "^1.4.7", - "os-shim": "^0.1.2" - } - }, "spdx-correct": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", @@ -6817,17 +15460,9 @@ } }, "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==" - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "requires": { - "extend-shallow": "^3.0.0" - } + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", + "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==" }, "sprintf-js": { "version": "1.0.3", @@ -6850,30 +15485,19 @@ "tweetnacl": "~0.14.0" } }, + "ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "requires": { + "minipass": "^3.1.1" + } + }, "stack-trace": { "version": "0.0.10", "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, "streamfilter": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/streamfilter/-/streamfilter-3.0.0.tgz", @@ -6882,10 +15506,13 @@ "readable-stream": "^3.0.6" } }, - "string-template": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", - "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=" + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } }, "string-width": { "version": "2.1.1", @@ -6896,6 +15523,11 @@ "strip-ansi": "^4.0.0" }, "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -6907,76 +15539,44 @@ } }, "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "string.prototype.trimleft": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", - "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "string.prototype.trimstart": "^1.0.0" - } - }, - "string.prototype.trimright": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", - "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "string.prototype.trimend": "^1.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" } }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "requires": { - "ansi-regex": "^4.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - } + "ansi-regex": "^5.0.0" } }, "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, + "strip-bom-buf": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-buf/-/strip-bom-buf-1.0.0.tgz", + "integrity": "sha1-HLRar1dTD0yvhsf3UXnSyaUd1XI=", "requires": { - "is-utf8": "^0.2.0" + "is-utf8": "^0.2.1" } }, "strip-bom-stream": { @@ -6986,6 +15586,16 @@ "requires": { "first-chunk-stream": "^2.0.0", "strip-bom": "^2.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "^0.2.0" + } + } } }, "strip-eof": { @@ -6998,24 +15608,16 @@ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" }, - "strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "requires": { - "min-indent": "^1.0.0" - } - }, "strip-json-comments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", - "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "requires": { "has-flag": "^4.0.0" } @@ -7030,213 +15632,70 @@ } }, "table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/table/-/table-6.0.8.tgz", + "integrity": "sha512-OBAdezyozae8IvjHGXBDHByVkLCcsmffXUSj8LXkNb0SluRd4ug3GFCjk6JynZONIPhOkyr0Nnvbq1rlIspXyQ==", "dev": true, "requires": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" + "ajv": "^8.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "lodash.clonedeep": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0" }, "dependencies": { - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "ajv": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.0.1.tgz", + "integrity": "sha512-46ZA4TalFcLLqX1dEU3dhdY38wAtDydJ4e7QQTVekLUTzXkb1LfqU6VOBXC/a9wiv4T094WURqJH6ZitF92Kqw==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - } - } - }, - "tabtab": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tabtab/-/tabtab-2.2.2.tgz", - "integrity": "sha1-egR/FDsBC0y9MfhX6ClhUSy/ThQ=", - "requires": { - "debug": "^2.2.0", - "inquirer": "^1.0.2", - "lodash.difference": "^4.5.0", - "lodash.uniq": "^4.5.0", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "npmlog": "^2.0.3", - "object-assign": "^4.1.0" - }, - "dependencies": { - "ansi-escapes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "requires": { - "restore-cursor": "^1.0.1" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "external-editor": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-1.1.1.tgz", - "integrity": "sha1-Etew24UPf/fnCBuvQAVwAGDEYAs=", - "requires": { - "extend": "^3.0.0", - "spawn-sync": "^1.0.15", - "tmp": "^0.0.29" - } - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - } - }, - "inquirer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-1.2.3.tgz", - "integrity": "sha1-TexvMvN+97sLLtPx0aXD9UUHSRg=", - "requires": { - "ansi-escapes": "^1.1.0", - "chalk": "^1.0.0", - "cli-cursor": "^1.0.1", - "cli-width": "^2.0.0", - "external-editor": "^1.1.0", - "figures": "^1.3.5", - "lodash": "^4.3.0", - "mute-stream": "0.0.6", - "pinkie-promise": "^2.0.0", - "run-async": "^2.2.0", - "rx": "^4.1.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.0", - "through": "^2.3.6" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" } }, "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } - }, - "mute-stream": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.6.tgz", - "integrity": "sha1-SJYrGeFp/R38JAs/HnMXYnu8R9s=" - }, - "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" - } + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true }, "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" - }, - "tmp": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.29.tgz", - "integrity": "sha1-8lEl/w3Z2jzLDC3Tce4SiLuRKMA=", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, "requires": { - "os-tmpdir": "~1.0.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" } } } }, - "test": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/test/-/test-0.6.0.tgz", - "integrity": "sha1-WYasRF7Bd1QyJRLRBLoyyKY+k44=", + "tar": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", + "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", "requires": { - "ansi-font": "0.0.2" + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" } }, "text-hex": { @@ -7250,9 +15709,9 @@ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, "textextensions": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.6.0.tgz", - "integrity": "sha512-49WtAWS+tcsy93dRt6P0P3AMD2m5PvXRhuEA0kaXos5ZLlujtYmpmFsB+QvWUSxE1ZsstmYXfQ7L40+EcQgpAQ==" + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-5.12.0.tgz", + "integrity": "sha512-IYogUDaP65IXboCiPPC0jTLLBzYlhhw2Y4b0a2trPgbHNGGGEfuHE6tds+yDcCf4mpNDaGISFzwSSezcXt+d6w==" }, "then-request": { "version": "6.0.2", @@ -7270,13 +15729,6 @@ "http-response-object": "^3.0.1", "promise": "^8.0.0", "qs": "^6.4.0" - }, - "dependencies": { - "@types/node": { - "version": "8.10.66", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", - "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==" - } } }, "through": { @@ -7285,18 +15737,13 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, "through2": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.1.tgz", - "integrity": "sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "requires": { - "readable-stream": "2 || 3" + "readable-stream": "3" } }, - "timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" - }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -7305,42 +15752,12 @@ "os-tmpdir": "~1.0.2" } }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "is-number": "^7.0.0" } }, "tough-cookie": { @@ -7351,29 +15768,34 @@ "ip-regex": "^2.1.0", "psl": "^1.1.28", "punycode": "^2.1.1" - }, - "dependencies": { - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - } } }, - "trim-newlines": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz", - "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==" + "treeverse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/treeverse/-/treeverse-1.0.4.tgz", + "integrity": "sha512-whw60l7r+8ZU8Tu/Uc2yxtc4ZTZbR/PF3u1IPNKGQ6p8EICLb3Z2lAgoqw9bqYd8IkgnsaOcLzYHFckjqNsf0g==" }, "triple-beam": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, + "tsconfig-paths": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", + "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "tunnel-agent": { "version": "0.6.0", @@ -7389,12 +15811,12 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "requires": { - "prelude-ls": "~1.1.2" + "prelude-ls": "^1.2.1" } }, "type-detect": { @@ -7404,9 +15826,10 @@ "dev": true }, "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true }, "typedarray": { "version": "0.0.6", @@ -7421,95 +15844,58 @@ "is-typedarray": "^1.0.0" } }, - "union-value": { + "unbox-primitive": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" - } + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" } }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "requires": { + "unique-slug": "^2.0.0" + } }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" - } + "imurmurhash": "^0.1.4" } }, + "universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, "untildify": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.3.tgz", - "integrity": "sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA==" - }, - "unzip-response": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", - "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==" }, "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "requires": { "punycode": "^2.1.0" - }, - "dependencies": { - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - } } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" - }, "url": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", @@ -7517,35 +15903,29 @@ "requires": { "punycode": "1.3.2", "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" + } } }, - "url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "requires": { - "prepend-http": "^1.0.1" - } - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==" + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, "v8-compile-cache": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", - "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", "dev": true }, "validate-npm-package-license": { @@ -7557,6 +15937,14 @@ "spdx-expression-parse": "^3.0.0" } }, + "validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "requires": { + "builtins": "^1.0.3" + } + }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -7567,36 +15955,56 @@ "extsprintf": "^1.2.0" } }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "version-compare": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/version-compare/-/version-compare-1.1.0.tgz", + "integrity": "sha512-zVKtPOJTC9x23lzS4+4D7J+drq80BXVYAmObnr5zqxxFVH7OffJ1lJlAS7LYsQNV56jx/wtbw0UV7XHLrvd6kQ==" + }, + "version-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/version-range/-/version-range-1.1.0.tgz", + "integrity": "sha512-R1Ggfg2EXamrnrV3TkZ6yBNgITDbclB3viwSjbZ3+eK0VVNK4ajkYJTnDz5N0bIMYDtK9MUBvXJUnKO5RWWJ6w==", "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" + "version-compare": "^1.0.0" + } + }, + "vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + }, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + } } }, "vinyl-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz", - "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-3.0.0.tgz", + "integrity": "sha1-sQTZ5ECf+jJfqt1SBkLQo7SIs2U=", "requires": { "graceful-fs": "^4.1.2", "pify": "^2.3.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0", + "strip-bom-buf": "^1.0.0", "strip-bom-stream": "^2.0.0", - "vinyl": "^1.1.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } + "vinyl": "^2.0.1" } }, + "walk-up-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/walk-up-path/-/walk-up-path-1.0.0.tgz", + "integrity": "sha512-hwj/qMDUEjCU5h0xr90KGCf0tg0/LgJbmOWgrWKYlcJZM7XvquvUJZ0G/HMGr7F7OQMOUuPHWP9JpriinkAlkg==" + }, "wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", @@ -7606,68 +16014,166 @@ } }, "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "requires": { "isexe": "^2.0.0" } }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "which-pm": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-pm/-/which-pm-2.0.0.tgz", + "integrity": "sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==", + "requires": { + "load-yaml-file": "^0.2.0", + "path-exists": "^4.0.0" + } + }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, "requires": { "string-width": "^1.0.2 || 2" } }, "windows-release": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.3.0.tgz", - "integrity": "sha512-2HetyTg1Y+R+rUgrKeUEhAG/ZuOmTrI1NBb3ZyAGQMYmOJjBBPe4MTodghRkmLJZHwkuPi02anbeGP+Zf401LQ==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.3.3.tgz", + "integrity": "sha512-OSOGH1QYiW5yVor9TtmXKQvt2vjQqbYS+DqmsZw+r7xDwLXEeT3JGW0ZppFmHx4diyXmxt238KFR3N9jzevBRg==", "requires": { "execa": "^1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.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" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } } }, "winston": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.2.1.tgz", - "integrity": "sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw==", - "requires": { - "async": "^2.6.1", - "diagnostics": "^1.1.1", - "is-stream": "^1.1.0", - "logform": "^2.1.1", - "one-time": "0.0.4", - "readable-stream": "^3.1.1", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", + "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", + "requires": { + "@dabh/diagnostics": "^2.0.2", + "async": "^3.1.0", + "is-stream": "^2.0.0", + "logform": "^2.2.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", - "winston-transport": "^4.3.0" + "winston-transport": "^4.4.0" }, "dependencies": { "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "requires": { - "lodash": "^4.17.14" - } + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" } } }, "winston-transport": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz", - "integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", + "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", "requires": { - "readable-stream": "^2.3.6", + "readable-stream": "^2.3.7", "triple-beam": "^1.2.0" }, "dependencies": { @@ -7723,6 +16229,12 @@ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", "dev": true }, + "workerpool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", + "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "dev": true + }, "wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -7734,12 +16246,6 @@ "strip-ansi": "^6.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -7747,24 +16253,15 @@ "dev": true }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.0" } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } } } }, @@ -7821,18 +16318,24 @@ "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true }, "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", "dev": true }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "yargs": { - "version": "15.3.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", - "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "requires": { "cliui": "^6.0.0", @@ -7845,13 +16348,13 @@ "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^18.1.1" + "yargs-parser": "^18.1.2" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, "find-up": { @@ -7879,6 +16382,15 @@ "p-locate": "^4.1.0" } }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, "p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", @@ -7888,16 +16400,10 @@ "p-limit": "^2.2.0" } }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "dev": true, "requires": { "emoji-regex": "^8.0.0", @@ -7905,127 +16411,41 @@ "strip-ansi": "^6.0.0" } }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, "requires": { - "ansi-regex": "^5.0.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } }, "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true }, "yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "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-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } } } }, @@ -8036,60 +16456,53 @@ "dev": true }, "yeoman-environment": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-2.10.2.tgz", - "integrity": "sha512-7HuUixYvGO1lVPjOZ0HOweL+WXuX7COEO0V5/R+K6Rsyy+hcl+PHMOcsUQMgq5BAGfRJo9CTt4EkE6iqH+SoQA==", - "requires": { - "chalk": "^2.4.1", - "debug": "^3.1.0", - "diff": "^3.5.0", - "escape-string-regexp": "^1.0.2", - "execa": "^4.0.0", - "globby": "^8.0.1", - "grouped-queue": "^1.1.0", - "inquirer": "^7.1.0", - "is-scoped": "^1.0.0", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-3.2.0.tgz", + "integrity": "sha512-Z2G4qgbjSLQ0BOiPQ4PCbqSYNhOP/HeWItu/hrlBv1gtBK6c3vkHSLioX8SduVYOKrn04X4H7cIG7hXpD3RsOQ==", + "requires": { + "@npmcli/arborist": "^2.2.2", + "are-we-there-yet": "^1.1.5", + "arrify": "^2.0.1", + "chalk": "^4.1.0", + "cli-table": "^0.3.1", + "commander": "7.1.0", + "dateformat": "^4.5.0", + "debug": "^4.1.1", + "diff": "^5.0.0", + "error": "^10.4.0", + "escape-string-regexp": "^4.0.0", + "execa": "^5.0.0", + "find-up": "^5.0.0", + "globby": "^11.0.1", + "grouped-queue": "^2.0.0", + "inquirer": "^8.0.0", + "is-scoped": "^2.1.0", + "istextorbinary": "^5.7.0", "lodash": "^4.17.10", - "log-symbols": "^2.2.0", + "log-symbols": "^4.0.0", "mem-fs": "^1.1.0", - "mem-fs-editor": "^6.0.0", - "npm-api": "^1.0.0", + "mem-fs-editor": "^8.0.0", + "minimatch": "^3.0.4", + "npmlog": "^4.1.2", + "pacote": "^11.2.6", + "pipeline-pipe": "^0.1.5", + "preferred-pm": "^3.0.3", + "pretty-bytes": "^5.3.0", + "read-chunk": "^3.2.0", "semver": "^7.1.3", - "strip-ansi": "^4.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0", "text-table": "^0.2.0", - "untildify": "^3.0.3", - "yeoman-generator": "^4.8.2" + "through2": "^4.0.2", + "untildify": "^4.0.0" }, "dependencies": { "ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", - "requires": { - "type-fest": "^0.11.0" - } - }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "type-fest": "^0.21.3" } }, "cli-cursor": { @@ -8100,47 +16513,29 @@ "restore-cursor": "^3.1.0" } }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "cross-spawn": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.2.tgz", - "integrity": "sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==" }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" }, "execa": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.2.tgz", - "integrity": "sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.0.0.tgz", + "integrity": "sha512-ov6w/2LCiuyO4RLYGdpFGjkcs0wMTgGE8PrkTHikeUy5iJekXyPIKUjifk5CsE0pt7sMCrMZ3YNqoCj6idQOnQ==", "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" } }, @@ -8150,93 +16545,43 @@ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "requires": { "escape-string-regexp": "^1.0.5" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + } } }, "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", - "requires": { - "pump": "^3.0.0" - } + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.0.tgz", + "integrity": "sha512-A1B3Bh1UmL0bidM/YX2NsCOTnGJePL9rO/M+Mw3m9f2gUpfokS0hi5Eah0WSUEWZdZhIZtMjkIYS7mDfOqNHbg==" }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" }, "inquirer": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", - "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.0.0.tgz", + "integrity": "sha512-ON8pEJPPCdyjxj+cxsYRe6XfCJepTxANdNnTebsTuQgXpRyZRRT9t4dJwjRubgmvn20CLSEnozRUayXyM9VTXA==", "requires": { "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.21", "mute-stream": "0.0.8", "run-async": "^2.4.0", - "rxjs": "^6.5.3", + "rxjs": "^6.6.6", "string-width": "^4.1.0", "strip-ansi": "^6.0.0", "through": "^2.3.6" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "requires": { - "has-flag": "^4.0.0" - } - } } }, "is-fullwidth-code-point": { @@ -8244,37 +16589,11 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" - }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "requires": { - "chalk": "^2.0.1" - } - }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "requires": { - "path-key": "^3.0.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, "restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -8284,230 +16603,140 @@ "signal-exit": "^3.0.2" } }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "requires": { - "ansi-regex": "^5.0.0" - } - } - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "requires": { - "ansi-regex": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" - } - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" } }, "type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==" - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" } } }, "yeoman-generator": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-4.10.1.tgz", - "integrity": "sha512-QgbtHSaqBAkyJJM0heQUhT63ubCt34NBFMEBydOBUdAuy8RBvGSzeqVBSZOjdh1tSLrwWXlU3Ck6y14awinF6Q==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-5.2.0.tgz", + "integrity": "sha512-LCHaYrcgtC4NpYAkritCEteuDSjBdhsQNYrssZjnK0okRFvroMXDX4//CA1RfVsjCHKi4Df6lILOUYCRiYKG4g==", "requires": { - "async": "^2.6.2", - "chalk": "^2.4.2", - "cli-table": "^0.3.1", - "cross-spawn": "^6.0.5", - "dargs": "^6.1.0", - "dateformat": "^3.0.3", + "chalk": "^4.1.0", + "dargs": "^7.0.0", "debug": "^4.1.1", - "diff": "^4.0.1", - "error": "^7.0.2", - "find-up": "^3.0.0", - "github-username": "^3.0.0", - "grouped-queue": "^1.1.0", - "istextorbinary": "^2.5.1", + "execa": "^4.1.0", + "github-username": "^6.0.0", "lodash": "^4.17.11", - "make-dir": "^3.0.0", - "mem-fs-editor": "^6.0.0", "minimist": "^1.2.5", - "pretty-bytes": "^5.2.0", - "read-chunk": "^3.2.0", - "read-pkg-up": "^5.0.0", - "rimraf": "^2.6.3", + "read-pkg-up": "^7.0.1", "run-async": "^2.0.0", "semver": "^7.2.1", - "shelljs": "^0.8.3", - "text-table": "^0.2.0", - "through2": "^3.0.1", - "yeoman-environment": "^2.9.5" + "shelljs": "^0.8.4", + "text-table": "^0.2.0" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "requires": { - "color-convert": "^1.9.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "requires": { - "lodash": "^4.17.14" + "p-locate": "^4.1.0" } }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "p-try": "^2.0.0" } }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "requires": { - "color-name": "1.1.3" + "p-limit": "^2.2.0" } }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "requires": { - "ms": "^2.1.1" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" } }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "read-pkg-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-5.0.0.tgz", - "integrity": "sha512-XBQjqOBtTzyol2CpsQOw8LHV0XbDZVG7xMMjmXAJomlVY03WOBRmYgDJETlvcg0H63AJvPRwT7GFi5rvOzUOKg==", + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "requires": { - "find-up": "^3.0.0", - "read-pkg": "^5.0.0" + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==" + } } }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "requires": { - "has-flag": "^3.0.0" + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" } } }, "yeoman-test": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yeoman-test/-/yeoman-test-2.4.1.tgz", - "integrity": "sha512-1tcNVP7I8wizHV9eN7iZhDOVfFm6GHOaAfK50c1E1adbe9lpiUZ57wdc7q5GVB4QheWP98maEsDcswLWU2Xv9A==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/yeoman-test/-/yeoman-test-5.1.0.tgz", + "integrity": "sha512-lcXcNRleJrIhohoKcRwmj9i8JO0lsYTySprwCfgZV1THeHJRqUsBEhHVgMr7DVB+coMoIkxk99wpn/bsOvpz4w==", "dev": true, "requires": { - "inquirer": "^7.1.0", - "lodash": "^4.17.15", - "mkdirp": "^1.0.3", - "rimraf": "^3.0.2", - "sinon": "^9.0.1", - "yeoman-environment": "^2.8.1", - "yeoman-generator": "^4.7.2" + "inquirer": "^7.3.3", + "lodash": "^4.17.19", + "mem-fs-editor": "^8.0.0", + "sinon": "^9.0.2" }, "dependencies": { "ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", - "dev": true, - "requires": { - "type-fest": "^0.11.0" - } - }, - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "type-fest": "^0.21.3" } }, "cli-cursor": { @@ -8519,6 +16748,12 @@ "restore-cursor": "^3.1.0" } }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true + }, "figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -8529,21 +16764,21 @@ } }, "inquirer": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", - "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", "dev": true, "requires": { "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" @@ -8571,19 +16806,10 @@ "signal-exit": "^3.0.2" } }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "dev": true, "requires": { "emoji-regex": "^8.0.0", @@ -8591,22 +16817,18 @@ "strip-ansi": "^6.0.0" } }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, "type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true } } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" } } } diff --git a/package.json b/package.json index 79d375fc7..d699b6e00 100644 --- a/package.json +++ b/package.json @@ -2,10 +2,6 @@ "name": "generator-jhipster-kotlin", "version": "1.11.0", "description": "A Kotlin based JHipster (KHipster)", - "repository": { - "type": "git", - "url": "git+https://github.com/jhipster/jhipster-kotlin" - }, "keywords": [ "kotlin", "java", @@ -13,10 +9,16 @@ "yeoman-generator", "jhipster-blueprint" ], - "author": "Sendil Kumar N (https://sendilkumarn.com)", + "homepage": "https://github.com/jhipster/jhipster-kotlin#readme", "bugs": { "url": "https://github.com/jhipster/jhipster-kotlin/issues" }, + "repository": { + "type": "git", + "url": "git+https://github.com/jhipster/jhipster-kotlin" + }, + "license": "Apache-2.0", + "author": "Sendil Kumar N (https://sendilkumarn.com)", "bin": { "khipster": "./cli/khipster.js" }, @@ -33,49 +35,32 @@ "test:unit": "mocha --timeout 120000 --slow 0 --reporter spec" }, "dependencies": { - "chalk": "4.0.0", - "cheerio": "1.0.0-rc.2", - "commander": "4.1.1", - "didyoumean": "1.2.1", - "ejs": "3.1.2", - "faker": "4.1.0", - "generator-jhipster": "6.10.5", + "chalk": "4.1.0", + "cheerio": "1.0.0-rc.5", + "generator-jhipster": "7.0.0", "glob": "7.1.6", - "insight": "0.10.3", - "jhipster-core": "7.3.1", - "js-yaml": "3.13.1", - "lodash": "4.17.19", - "meow": "6.1.0", - "mkdirp": "1.0.4", - "pluralize": "8.0.0", - "prettier": "2.1.2", - "randexp": "0.5.3", - "semver": "7.3.2", + "lodash": "4.17.21", + "prettier": "2.2.1", + "semver": "7.3.4", "shelljs": "0.8.4", - "tabtab": "2.2.2", - "yeoman-environment": "2.10.2", - "yeoman-generator": "4.10.1" + "yeoman-environment": "3.2.0", + "yeoman-generator": "5.2.0" }, "devDependencies": { - "chai": "4.2.0", + "chai": "4.3.4", "ejs-lint": "1.1.0", - "eslint": "6.8.0", - "eslint-config-airbnb-base": "14.1.0", - "eslint-config-prettier": "6.11.0", - "eslint-plugin-import": "2.20.2", - "eslint-plugin-prettier": "3.1.3", - "fs-extra": "9.0.0", - "mocha": "7.1.2", + "eslint": "7.22.0", + "eslint-config-airbnb-base": "14.2.1", + "eslint-config-prettier": "8.1.0", + "eslint-plugin-import": "2.22.1", + "eslint-plugin-prettier": "3.3.1", + "fs-extra": "9.1.0", + "mocha": "8.3.2", "yeoman-assert": "3.1.1", - "yeoman-test": "2.4.1" - }, - "resolutions": { - "inquirer": "6.3.1" + "yeoman-test": "5.1.0" }, "engines": { - "node": ">=10.20.1", + "node": ">=12.12.0", "npm": ">=6.14.4" - }, - "license": "Apache-2.0", - "homepage": "https://github.com/jhipster/jhipster-kotlin#readme" + } } diff --git a/test-integration/samples-kotlin/kotlin-jdl-default/app.jdl b/test-integration/samples-kotlin/kotlin-jdl-default/app.jdl index 577827b16..2ebec9ecd 100644 --- a/test-integration/samples-kotlin/kotlin-jdl-default/app.jdl +++ b/test-integration/samples-kotlin/kotlin-jdl-default/app.jdl @@ -2,21 +2,25 @@ application { config { applicationType monolith, baseName jhipsterSampleApplication, - packageName io.github.jhipster.sample, + packageName tech.jhipster.sample, authenticationType jwt, - prodDatabaseType mysql, + prodDatabaseType postgresql, buildTool maven, searchEngine false, - testFrameworks [gatling, protractor], + testFrameworks [gatling, cypress], clientFramework angularX, enableTranslation true, nativeLanguage en, languages [ en, fr ], blueprint kotlin } - entities BankAccount, TheLabel, Operation + entities * } + +entity Bank { + bankNumber Integer +} entity BankAccount { name String required bankNumber Integer @@ -41,10 +45,96 @@ entity Operation { } enum BankAccountType { - CHECKING, - SAVINGS, - LOAN + CHECKING (checking_account), + SAVINGS (savings_account), + LOAN (loan_account) +} + +entity Department { + name String required, + description TextBlob, + advertisement Blob, + logo ImageBlob +} + +/** + * JobHistory comment. + */ +entity JobHistory { + startDate ZonedDateTime, + endDate ZonedDateTime, + language Language +} + +enum Language { + FRENCH, ENGLISH, SPANISH +} + +enum JobType { + BOSS, SLAVE +} + +entity Job { + title String minlength(5) maxlength(25), + type JobType, + minSalary Long, + maxSalary Long +} + +/** + * The Employee entity. + * Second line in javadoc. + */ +entity Employee { + /** + * The firstname attribute. + */ + firstName String, + lastName String, + email String, + phoneNumber String, + hireDate ZonedDateTime, + salary Long, + commissionPct Long +} + +entity Location { + streetAddress String, + postalCode String, + city String, + stateProvince String +} + +entity Task { + title String, + description String +} + +entity GoldenBadge { + name String +} + +entity SilverBadge { + name String +} + +entity Identifier { + name String required unique +} + +entity Country { + name String +} + +entity Region { + name String +} + +relationship OneToOne { + Department{location} to Location, + Employee{user(login)} to User with jpaDerivedIdentifier } + relationship OneToMany { BankAccount{operation} to Operation{bankAccount(name)} } @@ -54,11 +144,45 @@ relationship ManyToOne { relationship ManyToMany { Operation{theLabel(labelName)} to TheLabel{operation} } -dto BankAccount with mapstruct -service BankAccount with serviceImpl + +relationship OneToMany { + /** + * A relationship + */ + Department{employee} to + /** + * Another side of the same relationship, + */ + Employee{department}, + Employee{job} to Job{emp(lastName)}, + Location{country} to Country, + Country{area(name)} to Region +} + +relationship ManyToOne { + Employee{manager(lastName)} to Employee, + Employee{sibag(name) required} to SilverBadge, + Employee{gobag(name) required} to GoldenBadge, + SilverBadge{iden(name) required} to Identifier, + GoldenBadge{iden(name) required} to Identifier +} + +relationship ManyToMany { + JobHistory{department} to Department{history}, + JobHistory{job} to Job{history}, + JobHistory{emp(firstName)} to Employee{history}, + Job{chore(title)} to Task{linkedJob(title)}, + Bank{account} to BankAccount{bank} +} + +dto BankAccount, Employee, Department, Location, Country, Region, SilverBadge, GoldenBadge, Identifier with mapstruct + angularSuffix BankAccount with mySuffix -filter BankAccount +filter BankAccount, Employee clientRootFolder BankAccount, TheLabel, Operation with test-root -paginate TheLabel with pagination -service TheLabel with serviceClass -paginate Operation with infinite-scroll + +paginate TheLabel, Job with pagination +paginate Operation, JobHistory, Employee with infinite-scroll + +service TheLabel, Employee, Department, Region with serviceClass +service BankAccount, Location, Country with serviceImpl diff --git a/test-integration/samples-kotlin/kotlin-webflux-mongo-oauth/.yo-rc.json b/test-integration/samples-kotlin/kotlin-webflux-mongo-oauth/.yo-rc.json index f56fc0415..3d5a5c83c 100644 --- a/test-integration/samples-kotlin/kotlin-webflux-mongo-oauth/.yo-rc.json +++ b/test-integration/samples-kotlin/kotlin-webflux-mongo-oauth/.yo-rc.json @@ -3,8 +3,8 @@ "applicationType": "monolith", "reactive": true, "baseName": "sampleWebflux", - "packageName": "io.github.jhipster.sample", - "packageFolder": "io/github/jhipster/sample", + "packageName": "tech.jhipster.sample", + "packageFolder": "tech/jhipster/sample", "authenticationType": "oauth2", "cacheProvider": "no", "enableHibernateCache": false, @@ -17,7 +17,7 @@ "enableTranslation": true, "nativeLanguage": "en", "languages": ["en", "fr"], - "testFrameworks": ["gatling", "protractor"], + "testFrameworks": ["gatling", "cypress"], "serverPort": "8080", "jhiPrefix": "jhi", "clientPackageManager": "npm", @@ -25,7 +25,6 @@ "messageBroker": false, "serviceDiscoveryType": false, "embeddableLaunchScript": false, - "useSass": true, "clientTheme": "none", "creationTimestamp": 1580314672693, "entitySuffix": "", diff --git a/test-integration/samples-kotlin/kotlin-webflux-mongo/.yo-rc.json b/test-integration/samples-kotlin/kotlin-webflux-mongo/.yo-rc.json index 3fb76fe3a..bd0107ada 100644 --- a/test-integration/samples-kotlin/kotlin-webflux-mongo/.yo-rc.json +++ b/test-integration/samples-kotlin/kotlin-webflux-mongo/.yo-rc.json @@ -3,8 +3,8 @@ "applicationType": "monolith", "reactive": true, "baseName": "travisWebflux", - "packageName": "io.github.jhipster.travis", - "packageFolder": "io/github/jhipster/travis", + "packageName": "tech.jhipster.travis", + "packageFolder": "tech/jhipster/travis", "authenticationType": "jwt", "cacheProvider": "no", "enableHibernateCache": false, @@ -17,9 +17,11 @@ "enableTranslation": true, "nativeLanguage": "en", "languages": ["en", "fr"], - "testFrameworks": ["gatling", "protractor"], + "testFrameworks": ["gatling", "cypress"], "serverPort": "8080", "jhiPrefix": "jhi", - "clientFramework": "react" + "clientFramework": "react", + "creationTimestamp": 1596513172471, + "jwtSecretKey": "ZjY4MTM4YjI5YzMwZjhjYjI2OTNkNTRjMWQ5Y2Q0Y2YwOWNmZTE2NzRmYzU3NTMwM2NjOTE3MTllOTM3MWRkMzcyYTljMjVmNmQ0Y2MxOTUzODc0MDhhMTlkMDIxMzI2YzQzZDM2ZDE3MmQ3NjVkODk3OTVmYzljYTQyZDNmMTQ=" } } diff --git a/test-integration/samples-kotlin/ms-micro-eureka-uaa/.yo-rc.json b/test-integration/samples-kotlin/ms-micro-eureka-uaa/.yo-rc.json deleted file mode 100644 index b953ff653..000000000 --- a/test-integration/samples-kotlin/ms-micro-eureka-uaa/.yo-rc.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "generator-jhipster": { - "applicationType": "microservice", - "baseName": "travisMicroserviceEureka", - "packageName": "io.github.jhipster.travis", - "packageFolder": "io/github/jhipster/travis", - "authenticationType": "uaa", - "uaaBaseName": "travisUaa", - "cacheProvider": "hazelcast", - "enableHibernateCache": true, - "databaseType": "sql", - "devDatabaseType": "h2Disk", - "prodDatabaseType": "mysql", - "searchEngine": false, - "serviceDiscoveryType": "eureka", - "buildTool": "maven", - "enableTranslation": true, - "nativeLanguage": "en", - "languages": ["en", "fr"], - "testFrameworks": ["gatling"], - "skipClient": true, - "skipUserManagement": true, - "serverPort": "8081", - "jhiPrefix": "jhi", - "websocket": false, - "messageBroker": false, - "clientFramework": "angularX", - "clientPackageManager": "npm" - } -} diff --git a/test-integration/samples-kotlin/webflux-kt-gateway-oauth2/.yo-rc.json b/test-integration/samples-kotlin/webflux-kt-gateway-oauth2/.yo-rc.json index 328006486..fde91a301 100644 --- a/test-integration/samples-kotlin/webflux-kt-gateway-oauth2/.yo-rc.json +++ b/test-integration/samples-kotlin/webflux-kt-gateway-oauth2/.yo-rc.json @@ -3,8 +3,8 @@ "applicationType": "gateway", "reactive": true, "baseName": "reactiveGateway", - "packageName": "io.github.jhipster.gateway", - "packageFolder": "io/github/jhipster/gateway", + "packageName": "tech.jhipster.gateway", + "packageFolder": "tech/jhipster/gateway", "authenticationType": "oauth2", "cacheProvider": "no", "enableHibernateCache": false, @@ -18,7 +18,7 @@ "enableTranslation": true, "nativeLanguage": "en", "languages": ["en", "fr"], - "testFrameworks": ["gatling", "protractor"], + "testFrameworks": ["gatling", "cypress"], "serverPort": "8080", "jhiPrefix": "jhi", "clientFramework": "react" diff --git a/test-integration/scripts/00-init-env.sh b/test-integration/scripts/00-init-env.sh index 07e80e8ee..ac9d33dd5 100755 --- a/test-integration/scripts/00-init-env.sh +++ b/test-integration/scripts/00-init-env.sh @@ -1,4 +1,6 @@ -#!/bin/bash +#!/usr/bin/env bash + +KHI_DETECTED_DIR="$( cd "$( dirname $( dirname $( dirname "${BASH_SOURCE[0]}" ) ) )" >/dev/null 2>&1 && pwd )" init_var() { result="" @@ -12,31 +14,56 @@ init_var() { echo $result } +# KHipster locations + # uri of repo -JHI_REPO=$(init_var "$BUILD_REPOSITORY_URI" "$TRAVIS_REPO_SLUG" "$GITHUB_WORKSPACE" ) +JHI_REPO=$(init_var "$BUILD_REPOSITORY_URI" "$GITHUB_WORKSPACE" ) # folder where the repo is cloned -JHI_CLONED=$(init_var "$BUILD_REPOSITORY_LOCALPATH" "$TRAVIS_BUILD_DIR" "$GITHUB_WORKSPACE") - -# folder where the generator-jhipster is cloned -JHI_HOME="$HOME"/generator-jhipster +if [[ "$JHI_HOME" == "" ]]; then + JHI_HOME=$(init_var "$BUILD_REPOSITORY_LOCALPATH" "$GITHUB_WORKSPACE" "$JHI_DETECTED_DIR") +fi # folder for test-integration -JHI_INTEG="$JHI_HOME"/test-integration +if [[ "$KHI_INTEG" == "" ]]; then + KHI_INTEG="$JHI_HOME"/test-integration +fi # folder for samples -JHI_SAMPLES="$JHI_INTEG"/samples +if [[ "$KHI_SAMPLES" == "" ]]; then + KHI_SAMPLES="$KHI_INTEG"/samples-kotlin +fi # folder for scripts -JHI_SCRIPTS="$JHI_INTEG"/scripts - -# folder for app -JHI_FOLDER_APP="$HOME"/app +if [[ "$KHI_SCRIPTS" == "" ]]; then + KHI_SCRIPTS="$KHI_INTEG"/scripts +fi -# folder for uaa app -JHI_FOLDER_UAA="$HOME"/uaa +# folder for app +if [[ "$JHI_FOLDER_APP" == "" ]]; then + JHI_FOLDER_APP="$HOME"/app +fi # set correct OpenJDK version if [[ "$JHI_JDK" == "11" && "$JHI_GITHUB_CI" != "true" ]]; then JAVA_HOME=$(readlink -f /usr/bin/java | sed "s:bin/java::") fi + +# JHipster cloned +# folder where the generator-jhipster is cloned +JHI_CLONED_HOME="$HOME"/generator-jhipster + +# folder for generator-jhipster test-integration +if [[ "$JHI_INTEG" == "" ]]; then + JHI_INTEG="$JHI_CLONED_HOME"/test-integration +fi + +# folder for generator-jhipster samples +if [[ "$JHI_SAMPLES" == "" ]]; then + JHI_SAMPLES="$JHI_INTEG"/samples +fi + +# folder for generator-jhipster scripts +if [[ "$JHI_SCRIPTS" == "" ]]; then + JHI_SCRIPTS="$JHI_INTEG"/scripts +fi diff --git a/test-integration/scripts/01-display-configuration.sh b/test-integration/scripts/01-display-configuration.sh index dc466d93b..9d7fcd866 100755 --- a/test-integration/scripts/01-display-configuration.sh +++ b/test-integration/scripts/01-display-configuration.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash source $(dirname $0)/00-init-env.sh @@ -8,6 +8,7 @@ echo JHI_ENTITY="$JHI_ENTITY" echo JHI_PROFILE="$JHI_PROFILE" echo JHI_RUN_APP="$JHI_RUN_APP" echo JHI_PROTRACTOR="$JHI_PROTRACTOR" +echo JHI_JDK="$JHI_JDK" echo JHI_LIB_REPO="$JHI_LIB_REPO" echo JHI_LIB_BRANCH="$JHI_LIB_BRANCH" echo JHI_GEN_REPO="$JHI_GEN_REPO" @@ -19,11 +20,13 @@ echo SPRING_JPA_SHOW_SQL="$SPRING_JPA_SHOW_SQL" echo "----- technical vars -----" echo JHI_REPO="$JHI_REPO" echo JHI_HOME="$JHI_HOME" -echo JHI_CLONED="$JHI_CLONED" echo JHI_INTEG="$JHI_INTEG" echo JHI_SAMPLES="$JHI_SAMPLES" echo JHI_SCRIPTS="$JHI_SCRIPTS" echo JHI_FOLDER_APP="$JHI_FOLDER_APP" -echo JHI_FOLDER_UAA="$JHI_FOLDER_UAA" echo JAVA_HOME="$JAVA_HOME" -echo KOTLIN_JHI_SCRIPTS="$KOTLIN_JHI_SCRIPTS" +echo "----- generator-jhipster ------" +echo JHI_CLONED_HOME="$JHI_CLONED_HOME" +echo JHI_CLONED_INTEG="$JHI_CLONED_INTEG" +echo JHI_CLONED_SAMPLES="$JHI_CLONED_SAMPLES" +echo JHI_CLONED_SCRIPTS="$JHI_CLONED_SCRIPTS" diff --git a/test-integration/scripts/02-display-tools.sh b/test-integration/scripts/02-display-tools.sh new file mode 100644 index 000000000..0d5f3acba --- /dev/null +++ b/test-integration/scripts/02-display-tools.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +git version +java -version +node -v +npm -v +docker version +docker-compose version diff --git a/test-integration/scripts/03-system.sh b/test-integration/scripts/03-system.sh index 9e8349330..20cc501c4 100755 --- a/test-integration/scripts/03-system.sh +++ b/test-integration/scripts/03-system.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash sudo /etc/init.d/mysql stop \ No newline at end of file diff --git a/test-integration/scripts/04-git-config.sh b/test-integration/scripts/04-git-config.sh index 023fb2378..41cdacb8a 100755 --- a/test-integration/scripts/04-git-config.sh +++ b/test-integration/scripts/04-git-config.sh @@ -1,4 +1,7 @@ -#!/bin/bash +#!/usr/bin/env bash + +set -e +source $(dirname $0)/00-init-env.sh git config --global user.name "JHipster Bot" git config --global user.email "jhipster-bot@jhipster.tech" diff --git a/test-integration/scripts/10-install-jhipster-kotlin.sh b/test-integration/scripts/10-install-jhipster-kotlin.sh index 9ae1f68a0..651859f29 100755 --- a/test-integration/scripts/10-install-jhipster-kotlin.sh +++ b/test-integration/scripts/10-install-jhipster-kotlin.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e source $(dirname $0)/00-init-env.sh @@ -6,90 +6,39 @@ source $(dirname $0)/00-init-env.sh #------------------------------------------------------------------------------- # Install JHipster Dependencies and Server-side library #------------------------------------------------------------------------------- -cd "$HOME" -if [[ "$JHI_REPO" == *"/jhipster" ]]; then - echo "*** jhipster: use local version at JHI_REPO=$JHI_REPO" - - cd "$JHI_HOME" - git --no-pager log -n 10 --graph --pretty='%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit - - ./mvnw -ntp clean install -DskipTests -Dmaven.javadoc.skip=true -Dgpg.skip=true --batch-mode - -elif [[ "$JHI_LIB_BRANCH" == "release" ]]; then - echo "*** jhipster: use release version" - -else - echo "*** jhipster: JHI_LIB_REPO=$JHI_LIB_REPO with JHI_LIB_BRANCH=$JHI_LIB_BRANCH" - git clone "$JHI_LIB_REPO" jhipster - cd jhipster - if [ "$JHI_LIB_BRANCH" == "latest" ]; then - LATEST=$(git describe --abbrev=0) - git checkout "$LATEST" - elif [ "$JHI_LIB_BRANCH" != "main" ]; then - git checkout "$JHI_LIB_BRANCH" - fi - git --no-pager log -n 10 --graph --pretty='%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit - - test-integration/scripts/10-replace-version-jhipster.sh - - ./mvnw -ntp clean install -DskipTests -Dmaven.javadoc.skip=true -Dgpg.skip=true --batch-mode - ls -al ~/.m2/repository/io/github/jhipster/jhipster-framework/ - ls -al ~/.m2/repository/io/github/jhipster/jhipster-dependencies/ - ls -al ~/.m2/repository/io/github/jhipster/jhipster-parent/ -fi - +echo "Always use the ***Release*** version for the JHipster" #------------------------------------------------------------------------------- # Install JHipster Generator #------------------------------------------------------------------------------- cd "$HOME" -if [[ "$JHI_REPO" == *"/generator-jhipster" ]]; then - echo "*** generator-jhipster: use local version at JHI_REPO=$JHI_REPO" - - cd "$JHI_HOME" - git --no-pager log -n 10 --graph --pretty='%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit - - npm ci - npm install -g "$JHI_HOME" +echo "*** generator-jhipster: JHI_GEN_REPO=$JHI_GEN_REPO with JHI_GEN_BRANCH=$JHI_GEN_BRANCH" +git clone "$JHI_GEN_REPO" generator-jhipster +cd generator-jhipster +echo "*** Checkout branch $JHI_GEN_BRANCH" +git checkout "$JHI_GEN_BRANCH" +git --no-pager log -n 10 --graph --pretty='%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit +npm install -g npm@$(node -e "console.log(require('generator-jhipster/generators/generator-constants').NPM_VERSION);") || true -elif [[ "$JHI_GEN_BRANCH" == "release" ]]; then - echo "*** generator-jhipster: use release version" - npm install -g generator-jhipster -else - echo "*** generator-jhipster: JHI_GEN_REPO=$JHI_GEN_REPO with JHI_GEN_BRANCH=$JHI_GEN_BRANCH" - git clone "$JHI_GEN_REPO" generator-jhipster - cd generator-jhipster - if [ "$JHI_GEN_BRANCH" == "latest" ]; then - LATEST=$(git describe --abbrev=0) - git checkout "$LATEST" - elif [ "$JHI_GEN_BRANCH" != "main" ]; then - git checkout "$JHI_GEN_BRANCH" - fi - git --no-pager log -n 10 --graph --pretty='%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit - - npm ci - npm link - -fi +ls "$HOME"/generator-jhipster/test-integration/scripts/ #------------------------------------------------------------------------------- # Override config #------------------------------------------------------------------------------- # replace 00-init-env.sh -cp "$KOTLIN_JHI_SCRIPTS"/00-init-env.sh "$JHI_SCRIPTS"/ +cp "$KHI_SCRIPTS"/00-init-env.sh "$JHI_SCRIPTS"/ # copy all samples -cp -R "$JHI_CLONED"/test-integration/samples-kotlin/* "$JHI_HOME"/test-integration/samples/ +cp -R "$KHI_SAMPLES"/* "$JHI_SAMPLES"/ #------------------------------------------------------------------------------- # Install JHipster Kotlin #------------------------------------------------------------------------------- -cd "$JHI_CLONED"/ +cd "$JHI_HOME"/ npm ci npm link -npm link generator-jhipster if [[ "$JHI_APP" == "" ]]; then npm test diff --git a/test-integration/scripts/11-generate-config.sh b/test-integration/scripts/11-generate-config.sh new file mode 100755 index 000000000..a8da15657 --- /dev/null +++ b/test-integration/scripts/11-generate-config.sh @@ -0,0 +1,198 @@ +#!/usr/bin/env bash + +#------------------------------------------------------------------------------- +# Eg: 11-generate-config.sh ./ ngx-default sqlfull +#------------------------------------------------------------------------------- +if [[ "$1" != "" ]]; then + JHI_FOLDER_APP=$1 +fi + +if [[ "$2" != "" ]]; then + JHI_APP=$2 +fi + +if [[ "$3" != "" ]]; then + JHI_ENTITY=$3 +fi + +set -e +if [[ -a $(dirname $0)/00-init-env.sh ]]; then + source $(dirname $0)/00-init-env.sh +else + echo "*** 00-init-env.sh not found" +fi + +#------------------------------------------------------------------------------- +# Functions +#------------------------------------------------------------------------------- +moveEntity() { + local entity="$1" + cp "$JHI_SAMPLES"/.jhipster/"$entity".json "$JHI_FOLDER_APP"/.jhipster/ +} + +prepareFolder() { + rm -rf "$JHI_FOLDER_APP" +} +#------------------------------------------------------------------------------- +# Copy entities json +#------------------------------------------------------------------------------- + +if [[ $JHI_REPO != "" ]]; then + prepareFolder +fi + +mkdir -p "$JHI_FOLDER_APP"/.jhipster/ +cd "$JHI_FOLDER_APP" + +if [[ "$JHI_ENTITY" != "jdl" ]]; then + #------------------------------------------------------------------------------- + # Copy jhipster config + #------------------------------------------------------------------------------- + cp -f "$JHI_SAMPLES"/"$JHI_APP"/.yo-rc.json "$JHI_FOLDER_APP"/ +fi + +if [[ ("$JHI_ENTITY" == "mongodb") || ("$JHI_ENTITY" == "couchbase") ]]; then + moveEntity DocumentBankAccount + moveEntity EmbeddedOperation + moveEntity Place + moveEntity Division + + moveEntity FieldTestEntity + moveEntity FieldTestMapstructAndServiceClassEntity + moveEntity FieldTestServiceClassAndJpaFilteringEntity + moveEntity FieldTestServiceImplEntity + moveEntity FieldTestInfiniteScrollEntity + moveEntity FieldTestPaginationEntity + + moveEntity EntityWithDTO + moveEntity EntityWithPaginationAndDTO + moveEntity EntityWithServiceClassAndPagination + moveEntity EntityWithServiceClassPaginationAndDTO + moveEntity EntityWithServiceImplAndDTO + moveEntity EntityWithServiceImplAndPagination + moveEntity EntityWithServiceImplPaginationAndDTO + +elif [[ "$JHI_ENTITY" == "neo4j" ]]; then + moveEntity Album + moveEntity Track + moveEntity Genre + moveEntity Artist + +elif [[ "$JHI_ENTITY" == "cassandra" ]]; then + moveEntity CassBankAccount + + moveEntity FieldTestEntity + moveEntity FieldTestServiceImplEntity + moveEntity FieldTestMapstructAndServiceClassEntity + moveEntity FieldTestPaginationEntity + +elif [[ "$JHI_ENTITY" == "micro" ]]; then + moveEntity MicroserviceBankAccount + moveEntity MicroserviceOperation + moveEntity MicroserviceLabel + + moveEntity FieldTestEntity + moveEntity FieldTestMapstructAndServiceClassEntity + moveEntity FieldTestServiceClassAndJpaFilteringEntity + moveEntity FieldTestServiceImplEntity + moveEntity FieldTestInfiniteScrollEntity + moveEntity FieldTestPaginationEntity + +elif [[ "$JHI_ENTITY" == "sqllight" ]]; then + moveEntity BankAccount + moveEntity Label + moveEntity Operation + +elif [[ "$JHI_ENTITY" == "sqlfull" ]]; then + moveEntity BankAccount + moveEntity Label + moveEntity Operation + moveEntity Place + moveEntity Division + + moveEntity FieldTestEntity + moveEntity FieldTestMapstructAndServiceClassEntity + moveEntity FieldTestServiceClassAndJpaFilteringEntity + moveEntity FieldTestServiceImplEntity + moveEntity FieldTestInfiniteScrollEntity + moveEntity FieldTestPaginationEntity + moveEntity FieldTestEnumWithValue + + moveEntity TestEntity + moveEntity TestMapstruct + moveEntity TestServiceClass + moveEntity TestServiceImpl + moveEntity TestInfiniteScroll + moveEntity TestPagination + moveEntity TestManyToOne + moveEntity TestManyToMany + moveEntity TestManyRelPaginDTO + moveEntity TestOneToOne + moveEntity TestCustomTableName + moveEntity TestTwoRelationshipsSameEntity + moveEntity SuperMegaLargeTestEntity + + moveEntity EntityWithDTO + moveEntity EntityWithPaginationAndDTO + moveEntity EntityWithServiceClassAndPagination + moveEntity EntityWithServiceClassPaginationAndDTO + moveEntity EntityWithServiceImplAndDTO + moveEntity EntityWithServiceImplAndPagination + moveEntity EntityWithServiceImplPaginationAndDTO + + moveEntity MapsIdParentEntityWithoutDTO + moveEntity MapsIdChildEntityWithoutDTO + moveEntity MapsIdParentEntityWithDTO + moveEntity MapsIdChildEntityWithDTO + moveEntity MapsIdUserProfileWithDTO + + moveEntity JpaFilteringRelationship + moveEntity JpaFilteringOtherSide + +elif [[ "$JHI_ENTITY" == "sql" ]]; then + moveEntity BankAccount + moveEntity Label + moveEntity Operation + + moveEntity FieldTestEntity + moveEntity FieldTestMapstructAndServiceClassEntity + moveEntity FieldTestServiceClassAndJpaFilteringEntity + moveEntity FieldTestServiceImplEntity + moveEntity FieldTestInfiniteScrollEntity + moveEntity FieldTestPaginationEntity + moveEntity FieldTestEnumWithValue + + moveEntity EntityWithDTO + moveEntity EntityWithPaginationAndDTO + moveEntity EntityWithServiceClassAndPagination + moveEntity EntityWithServiceClassPaginationAndDTO + moveEntity EntityWithServiceImplAndDTO + moveEntity EntityWithServiceImplAndPagination + moveEntity EntityWithServiceImplPaginationAndDTO + + moveEntity MapsIdUserProfileWithDTO + +elif [[ "$3" != "" ]]; then + JHI_JDL_ENTITY=$3 +fi + +#------------------------------------------------------------------------------- +# Generate jdl entities +#------------------------------------------------------------------------------- +if [[ "$JHI_JDL_ENTITY" != "" && "$JHI_JDL_ENTITY" != "none" ]]; then + khipster --no-insight jdl "$JHI_SAMPLES"/jdl-entities/$JHI_JDL_ENTITY.jdl --json-only +fi + +#------------------------------------------------------------------------------- +# Print entities json +#------------------------------------------------------------------------------- +echo "*** Entities:" +ls -al "$JHI_FOLDER_APP"/.jhipster/ + +#------------------------------------------------------------------------------- +# Force no insight +#------------------------------------------------------------------------------- +if [ "$JHI_FOLDER_APP" == "$HOME/app" ]; then + mkdir -p "$HOME"/.config/configstore/ + cp "$JHI_INTEG"/configstore/*.json "$HOME"/.config/configstore/ +fi \ No newline at end of file diff --git a/test-integration/scripts/12-generate-project-kotlin.sh b/test-integration/scripts/12-generate-project-kotlin.sh index 6cfa2a4c5..6d0ccd084 100755 --- a/test-integration/scripts/12-generate-project-kotlin.sh +++ b/test-integration/scripts/12-generate-project-kotlin.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e source $(dirname $0)/00-init-env.sh @@ -19,28 +19,22 @@ if [[ "$JHI_ENTITY" == "jdl" ]]; then cp -f "$JHI_SAMPLES"/"$JHI_APP"/*.jdl "$JHI_FOLDER_APP"/ cd "$JHI_FOLDER_APP" npm link generator-jhipster-kotlin - jhipster import-jdl *.jdl --no-insight --blueprint kotlin + khipster import-jdl *.jdl --no-insight --blueprint kotlin $@ else - #------------------------------------------------------------------------------- - # Generate UAA project with jhipster - #------------------------------------------------------------------------------- - if [[ "$JHI_APP" == *"uaa"* ]]; then - mkdir -p "$JHI_FOLDER_UAA" - cp -f "$JHI_SAMPLES"/uaa/.yo-rc.json "$JHI_FOLDER_UAA"/ - cd "$JHI_FOLDER_UAA" - jhipster --force --no-insight --with-entities --skip-checks --from-cli - ls -al "$JHI_FOLDER_UAA" - fi #------------------------------------------------------------------------------- # Generate project with jhipster #------------------------------------------------------------------------------- mkdir -p "$JHI_FOLDER_APP" - cp -f "$JHI_SAMPLES"/"$JHI_APP"/.yo-rc.json "$JHI_FOLDER_APP"/ + if [[ "$JHI_GENERATE_SKIP_CONFIG" != "1" ]]; then + cp -f "$JHI_SAMPLES"/"$JHI_APP"/.yo-rc.json "$JHI_FOLDER_APP"/ + else + echo "skipping config file" + fi cd "$JHI_FOLDER_APP" npm link generator-jhipster-kotlin - khipster --force --no-insight --skip-checks --with-entities --from-cli + khipster --force --no-insight --skip-checks --with-entities $@ fi @@ -50,3 +44,4 @@ cd "$JHI_FOLDER_APP" # Check folder where the app is generated #------------------------------------------------------------------------------- ls -al "$JHI_FOLDER_APP" +git --no-pager log -n 10 --graph --pretty='%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit || true diff --git a/test-integration/scripts/14-jhipster-info.sh b/test-integration/scripts/14-jhipster-info.sh new file mode 100755 index 000000000..a72eb85c2 --- /dev/null +++ b/test-integration/scripts/14-jhipster-info.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -e +source $(dirname $0)/00-init-env.sh + +cd "$JHI_FOLDER_APP" +khipster info diff --git a/test-integration/scripts/22-tests-frontend.sh b/test-integration/scripts/22-tests-frontend.sh index 48b527e32..6f6c03f4a 100755 --- a/test-integration/scripts/22-tests-frontend.sh +++ b/test-integration/scripts/22-tests-frontend.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e source $(dirname $0)/00-init-env.sh @@ -7,11 +7,7 @@ source $(dirname $0)/00-init-env.sh # Launch frontend tests #------------------------------------------------------------------------------- cd "$HOME" -if [[ $(grep yarn .yo-rc.json) != "" ]]; then - JHI_CLIENT_PACKAGE_MANAGER=yarn -else - JHI_CLIENT_PACKAGE_MANAGER=npm -fi +JHI_CLIENT_PACKAGE_MANAGER=npm if [ -f "tsconfig.json" ]; then if [ -f "src/main/webapp/app/app.tsx" ]; then diff --git a/test-integration/scripts/25-sonar-analyze.sh b/test-integration/scripts/25-sonar-analyze.sh new file mode 100755 index 000000000..1f1dfbbcc --- /dev/null +++ b/test-integration/scripts/25-sonar-analyze.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +source $(dirname $0)/00-init-env.sh + +#-------------------------------------------------- +# Launch Sonar analysis +#-------------------------------------------------- +cd "$JHI_FOLDER_APP" + +if [[ "$JHI_APP" = "ngx-default" && "$GITHUB_REPOSITORY" = "jhipster/generator-jhipster" && "$GITHUB_REF" = "refs/heads/main" ]]; then + echo "*** Sonar analyze for main branch" + ./mvnw -ntp --batch-mode initialize org.jacoco:jacoco-maven-plugin:prepare-agent sonar:sonar \ + -Dsonar.host.url=https://sonarcloud.io \ + -Dsonar.projectKey=jhipster-sample-application \ + -Dsonar.organization=jhipster \ + -Dsonar.login=$SONAR_TOKEN + +elif [[ $JHI_SONAR = 1 ]]; then + echo "*** Sonar analyze locally" + ./mvnw -ntp --batch-mode initialize org.jacoco:jacoco-maven-plugin:prepare-agent sonar:sonar \ + -Dsonar.host.url=http://localhost:9001 \ + -Dsonar.projectKey=JHipsterSonar + + sleep 30 + docker-compose -f src/main/docker/sonar.yml logs + echo "*** Sonar results:" + curl 'http://localhost:9001/api/measures/component?componentKey=JHipsterSonar&metricKeys=bugs%2Ccoverage%2Cvulnerabilities%2Cduplicated_lines_density%2Ccode_smells' + +else + echo "*** No sonar analyze" + +fi \ No newline at end of file diff --git a/test/app.spec.js b/test/app.spec.js index 1e1b3d4d7..f2a964cbc 100644 --- a/test/app.spec.js +++ b/test/app.spec.js @@ -1,42 +1,29 @@ const path = require('path'); const assert = require('yeoman-assert'); -const helpers = require('yeoman-test'); -const fse = require('fs-extra'); + const constants = require('generator-jhipster/generators/generator-constants'); const angularFiles = require('generator-jhipster/generators/client/files-angular').files; const reactFiles = require('generator-jhipster/generators/client/files-react').files; -const getFilesForOptions = require('./utils/utils').getFilesForOptions; -const shouldBeV3DockerfileCompatible = require('./utils/utils').shouldBeV3DockerfileCompatible; const expectedFiles = require('./utils/expected-files'); -const ANGULAR = constants.SUPPORTED_CLIENT_FRAMEWORKS.ANGULAR; -const REACT = constants.SUPPORTED_CLIENT_FRAMEWORKS.REACT; -const CLIENT_MAIN_SRC_DIR = constants.CLIENT_MAIN_SRC_DIR; -const SERVER_MAIN_SRC_DIR = `${constants.MAIN_DIR}kotlin/`; -const SERVER_MAIN_RES_DIR = constants.SERVER_MAIN_RES_DIR; -const TEST_DIR = constants.TEST_DIR; +const { skipPrettierHelpers: helpers, getFilesForOptions, shouldBeV3DockerfileCompatible } = require('./utils/utils'); + +const { ANGULAR, REACT } = constants.SUPPORTED_CLIENT_FRAMEWORKS; +const { CLIENT_MAIN_SRC_DIR, MAIN_DIR, SERVER_MAIN_RES_DIR, TEST_DIR } = constants; +const SERVER_MAIN_KOTLIN_SRC_DIR = `${MAIN_DIR}kotlin/`; describe('JHipster generator', () => { context('Default configuration with', () => { describe(ANGULAR, () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, jhiPrefix: 'test', - blueprint: 'kotlin', + withGeneratedFlag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', clientFramework: ANGULAR, @@ -48,17 +35,17 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', - languages: ['fr'], + languages: ['fr', 'en'], buildTool: 'maven', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', skipClient: false, skipUserManagement: false, serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected default files for angularX', () => { @@ -68,7 +55,7 @@ describe('JHipster generator', () => { assert.file(expectedFiles.jwtServer); assert.file(expectedFiles.maven); assert.file(expectedFiles.dockerServices); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); assert.file( getFilesForOptions(angularFiles, { @@ -88,39 +75,18 @@ describe('JHipster generator', () => { it('generates a README with no undefined value', () => { assert.noFileContent('README.md', /undefined/); }); - it('uses correct prettier formatting', () => { - // tabWidth = 2 (see generators/common/templates/.prettierrc.ejs) - assert.fileContent('webpack/webpack.dev.js', / {2}devtool:/); - assert.fileContent('tsconfig.base.json', / {2}"compilerOptions":/); - }); - // it Should be a KTLINT check - // it('uses correct prettier formatting for Kotlin file', () => { - // // tabWidth = 4 (see generators/common/templates/.prettierrc.ejs) - // assert.fileContent('src/main/kotlin/com/mycompany/myapp/JhipsterApp.kt', / {8}fun main(args: Array)/); - // assert.fileContent('src/main/kotlin/com/mycompany/myapp/JhipsterApp.kt', / {12}val env = runApplication/); - // }); }); describe(REACT, () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, jhiPrefix: 'test', - experimental: true, - blueprint: 'kotlin', + withGeneratedFlag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', clientFramework: REACT, @@ -132,7 +98,7 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', languages: ['fr'], @@ -142,7 +108,7 @@ describe('JHipster generator', () => { skipUserManagement: false, serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected default files for react', () => { @@ -152,7 +118,7 @@ describe('JHipster generator', () => { assert.file(expectedFiles.jwtServer); assert.file(expectedFiles.maven); assert.file(expectedFiles.dockerServices); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); assert.file( getFilesForOptions(reactFiles, { @@ -166,32 +132,15 @@ describe('JHipster generator', () => { it('contains clientFramework with react value', () => { assert.fileContent('.yo-rc.json', /"clientFramework": "react"/); }); - it('uses correct prettier formatting', () => { - // tabWidth = 2 (see generators/common/templates/.prettierrc.ejs) - assert.fileContent('webpack/webpack.dev.js', / {2}devtool:/); - assert.fileContent('tsconfig.json', / {2}"compilerOptions":/); - }); }); describe('using npm flag', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - npm: true, - blueprint: 'kotlin', - 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -203,7 +152,7 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', languages: ['fr'], @@ -213,7 +162,7 @@ describe('JHipster generator', () => { skipUserManagement: false, serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected default files', () => { @@ -223,7 +172,7 @@ describe('JHipster generator', () => { assert.file(expectedFiles.jwtServer); assert.file(expectedFiles.maven); assert.file(expectedFiles.dockerServices); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); assert.file( getFilesForOptions(angularFiles, { @@ -243,23 +192,15 @@ describe('JHipster generator', () => { }); describe('Gradle', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -271,7 +212,7 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', languages: ['fr'], @@ -279,7 +220,7 @@ describe('JHipster generator', () => { rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected default files for gradle', () => { @@ -289,7 +230,7 @@ describe('JHipster generator', () => { assert.file(expectedFiles.jwtServer); assert.file(expectedFiles.gradle); assert.file(expectedFiles.dockerServices); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); assert.file( getFilesForOptions(angularFiles, { @@ -303,23 +244,15 @@ describe('JHipster generator', () => { }); describe('Maven with ktlint-format', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, jhiPrefix: 'test', - blueprint: 'kotlin', - }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) + withGeneratedFlag: true, + 'skip-ktlint-format': true, + blueprints: 'kotlin', + }) .withPrompts({ baseName: 'jhipster', clientFramework: ANGULAR, @@ -342,7 +275,7 @@ describe('JHipster generator', () => { skipUserManagement: false, serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected default files for angularX', () => { @@ -373,30 +306,18 @@ describe('JHipster generator', () => { it('generates a README with no undefined value', () => { assert.noFileContent('README.md', /undefined/); }); - it('uses correct prettier formatting', () => { - // tabWidth = 2 (see generators/common/templates/.prettierrc.ejs) - assert.fileContent('webpack/webpack.dev.js', / {2}devtool:/); - assert.fileContent('tsconfig.base.json', / {2}"compilerOptions":/); - }); }); describe('Gradle with ktlint-format', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', - }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) + jhiPrefix: 'test', + withGeneratedFlag: true, + 'skip-ktlint-format': true, + blueprints: 'kotlin', + }) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -416,7 +337,7 @@ describe('JHipster generator', () => { rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected default files for gradle', () => { @@ -442,23 +363,15 @@ describe('JHipster generator', () => { context('Application with DB option', () => { describe('mariadb', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -480,7 +393,7 @@ describe('JHipster generator', () => { skipUserManagement: false, serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected default files', () => { @@ -505,23 +418,15 @@ describe('JHipster generator', () => { }); describe('mongodb', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -543,7 +448,7 @@ describe('JHipster generator', () => { skipUserManagement: false, serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with "MongoDB"', () => { @@ -557,23 +462,15 @@ describe('JHipster generator', () => { }); describe('couchbase', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -595,7 +492,7 @@ describe('JHipster generator', () => { skipUserManagement: false, serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with "Couchbase"', () => { @@ -609,23 +506,15 @@ describe('JHipster generator', () => { }); describe('neo4j', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -647,7 +536,7 @@ describe('JHipster generator', () => { skipUserManagement: false, serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with "Neo4j"', () => { @@ -661,23 +550,15 @@ describe('JHipster generator', () => { }); describe('mssql', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -699,39 +580,27 @@ describe('JHipster generator', () => { skipUserManagement: false, serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with "Microsoft SQL Server"', () => { assert.file(expectedFiles.mssql); assert.file(expectedFiles.hibernateTimeZoneConfig); assert.fileContent('pom.xml', /mssql-jdbc/); - assert.fileContent( - `${SERVER_MAIN_RES_DIR}config/liquibase/changelog/00000000000000_initial_schema.xml`, - /identityInsertEnabled/ - ); }); shouldBeV3DockerfileCompatible('mssql'); }); describe('cassandra', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -753,7 +622,7 @@ describe('JHipster generator', () => { skipUserManagement: false, serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with "Cassandra"', () => { @@ -767,23 +636,15 @@ describe('JHipster generator', () => { }); describe('cassandra no i18n', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -803,7 +664,7 @@ describe('JHipster generator', () => { skipUserManagement: false, serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with "Cassandra"', () => { @@ -813,24 +674,16 @@ describe('JHipster generator', () => { }); }); - describe('postgresql and elasticsearch', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + describe('MySQL and elasticsearch', () => { + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -841,8 +694,8 @@ describe('JHipster generator', () => { cacheProvider: 'no', enableHibernateCache: false, databaseType: 'sql', - devDatabaseType: 'postgresql', - prodDatabaseType: 'postgresql', + devDatabaseType: 'mysql', + prodDatabaseType: 'mysql', enableTranslation: true, nativeLanguage: 'en', languages: ['fr'], @@ -852,35 +705,27 @@ describe('JHipster generator', () => { skipUserManagement: false, serverSideOptions: ['searchEngine:elasticsearch'], }) - .on('end', done); + .run(); }); - it('creates expected files with "PostgreSQL" and "Elasticsearch"', () => { - assert.file(expectedFiles.postgresql); + it('creates expected files with "MySQL" and "Elasticsearch"', () => { + assert.file(expectedFiles.mysql); assert.file(expectedFiles.elasticsearch); assert.file(expectedFiles.hibernateTimeZoneConfig); }); - shouldBeV3DockerfileCompatible('postgresql'); + shouldBeV3DockerfileCompatible('mysql'); }); describe('couchbase FTS', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -902,7 +747,7 @@ describe('JHipster generator', () => { skipUserManagement: false, serverSideOptions: ['searchEngine:couchbase'], }) - .on('end', done); + .run(); }); it('creates expected files with "Couchbbase FTS"', () => { @@ -913,23 +758,15 @@ describe('JHipster generator', () => { }); describe('no database', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ applicationType: 'microservice', baseName: 'jhipster', @@ -949,7 +786,7 @@ describe('JHipster generator', () => { rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with the microservice application type', () => { @@ -968,23 +805,15 @@ describe('JHipster generator', () => { context('Application with other options', () => { describe('oauth2', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -996,7 +825,7 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', languages: ['fr'], @@ -1004,13 +833,13 @@ describe('JHipster generator', () => { rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with authenticationType "oauth2"', () => { assert.file(expectedFiles.oauth2); assert.file(expectedFiles.oauth2Client); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); }); it('generates README with instructions for OAuth', () => { @@ -1019,23 +848,15 @@ describe('JHipster generator', () => { }); describe('oauth2 + elasticsearch', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -1047,7 +868,7 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', languages: ['fr'], @@ -1055,7 +876,7 @@ describe('JHipster generator', () => { rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: ['searchEngine:elasticsearch'], }) - .on('end', done); + .run(); }); it('creates expected files with authenticationType "oauth2" and elasticsearch', () => { @@ -1063,28 +884,20 @@ describe('JHipster generator', () => { assert.file(expectedFiles.oauth2Client); assert.file(expectedFiles.elasticsearch); assert.file(expectedFiles.hibernateTimeZoneConfig); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); }); }); describe('oauth2 + mongodb', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -1104,7 +917,7 @@ describe('JHipster generator', () => { rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with authenticationType "oauth2" and mongodb', () => { @@ -1115,23 +928,15 @@ describe('JHipster generator', () => { }); describe('hazelcast', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -1143,7 +948,7 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', languages: ['fr'], @@ -1151,48 +956,40 @@ describe('JHipster generator', () => { rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with "Hazelcast"', () => { assert.file(expectedFiles.common); assert.file(expectedFiles.server); assert.file(expectedFiles.userManagementServer); assert.file(expectedFiles.hazelcast); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); }); }); describe('Infinispan', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', packageFolder: 'com/mycompany/myapp', - clientFramework: 'angular1', + clientFramework: ANGULAR, serviceDiscoveryType: false, authenticationType: 'jwt', cacheProvider: 'infinispan', enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', languages: ['fr'], @@ -1200,7 +997,7 @@ describe('JHipster generator', () => { rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with "Infinispan"', () => { assert.file(expectedFiles.common); @@ -1208,41 +1005,33 @@ describe('JHipster generator', () => { assert.file(expectedFiles.userManagementServer); assert.file(expectedFiles.client); assert.file(expectedFiles.infinispan); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); }); }); describe('Infinispan and Eureka', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', packageFolder: 'com/mycompany/myapp', serviceDiscoveryType: 'eureka', - clientFramework: 'angular1', + clientFramework: ANGULAR, authenticationType: 'jwt', cacheProvider: 'infinispan', enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', languages: ['fr'], @@ -1250,7 +1039,7 @@ describe('JHipster generator', () => { rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with "Infinispan and Eureka"', () => { assert.file(expectedFiles.common); @@ -1259,29 +1048,21 @@ describe('JHipster generator', () => { assert.file(expectedFiles.client); assert.file(expectedFiles.eureka); assert.file(expectedFiles.infinispan); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); }); }); describe('Memcached', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -1293,7 +1074,7 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', languages: ['fr'], @@ -1301,7 +1082,7 @@ describe('JHipster generator', () => { rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with "Memcached"', () => { assert.file(expectedFiles.common); @@ -1309,29 +1090,21 @@ describe('JHipster generator', () => { assert.file(expectedFiles.userManagementServer); assert.file(expectedFiles.client); assert.file(expectedFiles.memcached); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); }); }); describe('Redis', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -1343,7 +1116,7 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', languages: ['fr'], @@ -1351,7 +1124,7 @@ describe('JHipster generator', () => { rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with "Redis"', () => { assert.file(expectedFiles.common); @@ -1359,29 +1132,21 @@ describe('JHipster generator', () => { assert.file(expectedFiles.userManagementServer); assert.file(expectedFiles.client); assert.file(expectedFiles.redis); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); }); }); describe('Messaging with Kafka configuration', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -1395,7 +1160,7 @@ describe('JHipster generator', () => { websocket: false, databaseType: 'sql', devDatabaseType: 'h2Disk', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', searchEngine: false, buildTool: 'maven', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', @@ -1407,7 +1172,7 @@ describe('JHipster generator', () => { languages: ['en'], serverSideOptions: ['messageBroker:kafka'], }) - .on('end', done); + .run(); }); it('creates expected files with Kafka message broker enabled', () => { @@ -1417,29 +1182,21 @@ describe('JHipster generator', () => { assert.file(expectedFiles.jwtServer); assert.file(expectedFiles.gatling); assert.file(expectedFiles.messageBroker); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); }); }); describe('API first using OpenAPI-generator (maven)', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -1453,7 +1210,7 @@ describe('JHipster generator', () => { websocket: false, databaseType: 'sql', devDatabaseType: 'h2Disk', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', searchEngine: false, buildTool: 'maven', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', @@ -1465,15 +1222,15 @@ describe('JHipster generator', () => { languages: ['en'], serverSideOptions: ['enableSwaggerCodegen:true'], }) - .on('end', done); + .run(); }); - it('creates expected files with Swagger API first enabled', () => { + it('creates expected files with OpenAPI first enabled', () => { assert.file(expectedFiles.common); assert.file(expectedFiles.server); assert.file(expectedFiles.userManagementServer); assert.file(expectedFiles.jwtServer); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); assert.file(expectedFiles.gatling); assert.file(expectedFiles.swaggerCodegen); @@ -1484,23 +1241,15 @@ describe('JHipster generator', () => { }); describe('API first using OpenAPI-generator (gradle)', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -1514,7 +1263,7 @@ describe('JHipster generator', () => { websocket: false, databaseType: 'sql', devDatabaseType: 'h2Disk', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', searchEngine: false, buildTool: 'gradle', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', @@ -1526,16 +1275,16 @@ describe('JHipster generator', () => { languages: ['en'], serverSideOptions: ['enableSwaggerCodegen:true'], }) - .on('end', done); + .run(); }); - it('creates expected files with Swagger API first enabled', () => { + it('creates expected files with OpenAPI first enabled', () => { assert.file(expectedFiles.common); assert.file(expectedFiles.server); assert.file(expectedFiles.userManagementServer); assert.file(expectedFiles.gradle); assert.file(expectedFiles.jwtServer); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); assert.file(expectedFiles.gatling); assert.file(expectedFiles.swaggerCodegen); @@ -1546,23 +1295,15 @@ describe('JHipster generator', () => { context('Application names', () => { describe('package names', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.otherpackage', @@ -1574,7 +1315,7 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', languages: ['fr'], @@ -1582,34 +1323,26 @@ describe('JHipster generator', () => { rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with correct package names', () => { - assert.file([`${SERVER_MAIN_SRC_DIR}com/otherpackage/JhipsterApp.kt`]); - assert.fileContent(`${SERVER_MAIN_SRC_DIR}com/otherpackage/JhipsterApp.kt`, /package com\.otherpackage/); - assert.fileContent(`${SERVER_MAIN_SRC_DIR}com/otherpackage/JhipsterApp.kt`, /class JhipsterApp/); + assert.file([`${SERVER_MAIN_KOTLIN_SRC_DIR}com/otherpackage/JhipsterApp.kt`]); + assert.fileContent(`${SERVER_MAIN_KOTLIN_SRC_DIR}com/otherpackage/JhipsterApp.kt`, /package com\.otherpackage/); + assert.fileContent(`${SERVER_MAIN_KOTLIN_SRC_DIR}com/otherpackage/JhipsterApp.kt`, /class JhipsterApp/); }); }); describe('bad application name for java', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: '21Points', packageName: 'com.otherpackage', @@ -1621,7 +1354,7 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', languages: ['fr'], @@ -1629,36 +1362,28 @@ describe('JHipster generator', () => { rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with default application name', () => { assert.file([ - `${SERVER_MAIN_SRC_DIR}com/otherpackage/Application.kt`, - `${SERVER_MAIN_SRC_DIR}com/otherpackage/ApplicationWebXml.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/otherpackage/Application.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/otherpackage/ApplicationWebXml.kt`, ]); - assert.fileContent(`${SERVER_MAIN_SRC_DIR}com/otherpackage/Application.kt`, /class Application/); + assert.fileContent(`${SERVER_MAIN_KOTLIN_SRC_DIR}com/otherpackage/Application.kt`, /class Application/); }); }); describe('application names', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'myapplication', packageName: 'com.mycompany.myapp', @@ -1670,7 +1395,7 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', languages: ['fr'], @@ -1678,35 +1403,27 @@ describe('JHipster generator', () => { rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with correct application name', () => { assert.file([`${CLIENT_MAIN_SRC_DIR}app/home/home.route.ts`]); - assert.fileContent(`${CLIENT_MAIN_SRC_DIR}app/app.module.ts`, /MyapplicationAppModule/); + assert.fileContent(`${CLIENT_MAIN_SRC_DIR}app/app.module.ts`, /AppModule/); }); }); }); context('i18n', () => { describe('no i18n', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -1718,13 +1435,13 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: false, buildTool: 'maven', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('does not create i18n files if i18n is disabled', () => { @@ -1734,23 +1451,15 @@ describe('JHipster generator', () => { }); describe('with RTL support', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', clientFramework: ANGULAR, @@ -1762,17 +1471,17 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', - languages: ['ar-ly'], + languages: ['ar-ly', 'en'], buildTool: 'maven', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', skipClient: false, skipUserManagement: false, serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected default files for i18n with RTL support', () => { @@ -1794,23 +1503,15 @@ describe('JHipster generator', () => { context('Auth options', () => { describe('JWT authentication', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -1822,15 +1523,15 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', - languages: ['fr'], + languages: ['fr', 'en'], buildTool: 'maven', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with JWT authentication', () => { @@ -1847,23 +1548,15 @@ describe('JHipster generator', () => { }); describe('HTTP session authentication', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -1875,15 +1568,15 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', - languages: ['fr'], + languages: ['fr', 'en'], buildTool: 'maven', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with HTTP session authentication', () => { @@ -1902,23 +1595,15 @@ describe('JHipster generator', () => { context('Testing options', () => { describe('Protractor tests', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -1932,7 +1617,7 @@ describe('JHipster generator', () => { websocket: false, databaseType: 'sql', devDatabaseType: 'h2Disk', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', searchEngine: false, buildTool: 'maven', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', @@ -1943,14 +1628,14 @@ describe('JHipster generator', () => { nativeLanguage: 'en', languages: ['en'], }) - .on('end', done); + .run(); }); it('creates expected files with Protractor enabled', () => { assert.file(expectedFiles.common); assert.file(expectedFiles.server); assert.file(expectedFiles.userManagementServer); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); assert.file( getFilesForOptions(angularFiles, { @@ -1965,23 +1650,15 @@ describe('JHipster generator', () => { }); describe('Cucumber tests', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -1995,7 +1672,7 @@ describe('JHipster generator', () => { websocket: false, databaseType: 'sql', devDatabaseType: 'h2Disk', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', searchEngine: false, buildTool: 'maven', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', @@ -2006,14 +1683,14 @@ describe('JHipster generator', () => { nativeLanguage: 'en', languages: ['en'], }) - .on('end', done); + .run(); }); it('creates expected files with Cucumber enabled', () => { assert.file(expectedFiles.common); assert.file(expectedFiles.server); assert.file(expectedFiles.userManagementServer); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); assert.file(expectedFiles.cucumber); assert.noFile([`${TEST_DIR}gatling/conf/gatling.conf`, `${TEST_DIR}gatling/conf/logback.xml`]); @@ -2021,26 +1698,70 @@ describe('JHipster generator', () => { }); }); + context('App with skip server', () => { + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) + .withOptions({ + fromCli: true, + skipInstall: true, + skipChecks: true, + skipServer: true, + db: 'postgresql', + auth: 'jwt', + 'skip-ktlint-format': true, + }) + .withPrompts({ + baseName: 'jhipster', + clientFramework: ANGULAR, + packageName: 'com.mycompany.myapp', + packageFolder: 'com/mycompany/myapp', + serviceDiscoveryType: false, + authenticationType: 'jwt', + enableTranslation: true, + nativeLanguage: 'en', + languages: ['fr', 'en'], + rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', + }) + .run(); + }); + + it('creates expected files for default configuration with skip server option enabled', () => { + assert.file(expectedFiles.common); + assert.noFile(expectedFiles.server); + assert.noFile(expectedFiles.userManagementServer); + assert.noFile(expectedFiles.maven); + assert.noFile(expectedFiles.postgresql); + assert.noFile(expectedFiles.hibernateTimeZoneConfig); + assert.file( + getFilesForOptions(angularFiles, { + enableTranslation: true, + serviceDiscoveryType: false, + authenticationType: 'jwt', + testFrameworks: [], + }) + ); + }); + it('generates a README with no undefined value', () => { + assert.noFileContent('README.md', /undefined/); + }); + it('generates a .prettierrc with no reference to kt extension', () => { + assert.noFileContent('.prettierrc', ',kt'); + }); + }); + context('App with skip client', () => { describe('Maven', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - skipClient: true, - blueprint: 'kotlin', + jhiPrefix: 'test', + withGeneratedFlag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', + skipClient: true, }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -2051,15 +1772,15 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', buildTool: 'maven', enableTranslation: true, nativeLanguage: 'en', - languages: ['fr'], + languages: ['fr', 'en'], rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files for default configuration with skip client option enabled', () => { @@ -2067,7 +1788,7 @@ describe('JHipster generator', () => { assert.file(expectedFiles.server); assert.file(expectedFiles.userManagementServer); assert.file(expectedFiles.maven); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); assert.noFile( getFilesForOptions( @@ -2091,27 +1812,29 @@ describe('JHipster generator', () => { assert.noFileContent('pom.xml', 'npm.version'); assert.noFileContent('pom.xml', 'frontend-maven-plugin'); }); + it('generates a .prettierrc with no reference to webpack', () => { + assert.noFileContent('.prettierrc', 'webpack'); + }); + it('generates a .prettierrc with no reference to client extensions', () => { + assert.noFileContent('.prettierrc', ',js'); + assert.noFileContent('.prettierrc', ',ts'); + assert.noFileContent('.prettierrc', ',tsx'); + assert.noFileContent('.prettierrc', ',css'); + assert.noFileContent('.prettierrc', ',scss'); + }); }); describe('Gradle', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - skipClient: true, - blueprint: 'kotlin', + jhiPrefix: 'test', + withGeneratedFlag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', + skipClient: true, }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -2122,15 +1845,15 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', buildTool: 'gradle', enableTranslation: true, nativeLanguage: 'en', - languages: ['fr'], + languages: ['fr', 'en'], rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files for default configuration with skip client option enabled', () => { @@ -2138,7 +1861,7 @@ describe('JHipster generator', () => { assert.file(expectedFiles.server); assert.file(expectedFiles.userManagementServer); assert.file(expectedFiles.gradle); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); assert.noFile( getFilesForOptions( @@ -2162,25 +1885,17 @@ describe('JHipster generator', () => { context('App with skip client and skip user management', () => { describe('Maven', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, + jhiPrefix: 'test', + withGeneratedFlag: true, + 'skip-ktlint-format': true, + blueprints: 'kotlin', skipClient: true, skipUserManagement: true, - skipChecks: true, - blueprint: 'kotlin', - 'skip-ktlint-format': true, }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', applicationType: 'monolith', @@ -2192,15 +1907,15 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', buildTool: 'maven', enableTranslation: true, nativeLanguage: 'en', - languages: ['fr'], + languages: ['fr', 'en'], rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected server files', () => { @@ -2208,30 +1923,22 @@ describe('JHipster generator', () => { assert.noFile(expectedFiles.userManagementServer); }); it('creates SecurityConfiguration for default configuration with skip client and skip user management option enabled', () => { - assert.file(`${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/SecurityConfiguration.kt`); + assert.file(`${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/config/SecurityConfiguration.kt`); }); }); }); context('Eureka', () => { describe('gateway with eureka', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ applicationType: 'gateway', baseName: 'jhipster', @@ -2244,45 +1951,35 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', - languages: ['fr'], + languages: ['fr', 'en'], buildTool: 'maven', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with the gateway application type', () => { - assert.file(expectedFiles.jwtServer); + assert.file(expectedFiles.jwtServerGateway); assert.file(expectedFiles.gateway); - assert.noFile(expectedFiles.rateLimitingFilesForGateways); - assert.file(expectedFiles.feignConfig); assert.file(expectedFiles.eureka); assert.noFile(expectedFiles.consul); }); }); describe('gateway with eureka and rate limiting', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ applicationType: 'gateway', baseName: 'jhipster', @@ -2295,45 +1992,35 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', - languages: ['fr'], + languages: ['fr', 'en'], buildTool: 'maven', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with the gateway application type', () => { - assert.file(expectedFiles.jwtServer); + assert.file(expectedFiles.jwtServerGateway); assert.file(expectedFiles.gateway); - assert.file(expectedFiles.rateLimitingFilesForGateways); - assert.file(expectedFiles.feignConfig); assert.file(expectedFiles.eureka); assert.noFile(expectedFiles.consul); }); }); describe('microservice with eureka', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ applicationType: 'microservice', baseName: 'jhipster', @@ -2344,16 +2031,16 @@ describe('JHipster generator', () => { cacheProvider: 'ehcache', enableHibernateCache: true, databaseType: 'sql', - devDatabaseType: 'mysql', - prodDatabaseType: 'mysql', + devDatabaseType: 'postgresql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', - languages: ['fr'], + languages: ['fr', 'en'], buildTool: 'maven', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with the microservice application type', () => { @@ -2367,23 +2054,15 @@ describe('JHipster generator', () => { }); describe('monolith with eureka', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ applicationType: 'monolith', baseName: 'jhipster', @@ -2395,22 +2074,22 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', - languages: ['fr'], + languages: ['fr', 'en'], buildTool: 'maven', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: ['serviceDiscoveryType:eureka'], }) - .on('end', done); + .run(); }); it('creates expected files with the monolith application type', () => { assert.file(expectedFiles.common); assert.file(expectedFiles.server); assert.file(expectedFiles.userManagementServer); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); assert.file(expectedFiles.client); assert.file(expectedFiles.eureka); @@ -2419,23 +2098,15 @@ describe('JHipster generator', () => { }); describe('microservice with gradle and eureka', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ applicationType: 'microservice', baseName: 'jhipster', @@ -2447,17 +2118,17 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', - languages: ['fr'], + languages: ['fr', 'en'], buildTool: 'gradle', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], skipClient: true, skipUserManagement: true, }) - .on('end', done); + .run(); }); it('creates expected files with the microservice application type', () => { @@ -2470,130 +2141,19 @@ describe('JHipster generator', () => { assert.noFile(expectedFiles.userManagementServer); }); }); - - describe('UAA server with Eureka', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') - .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) - .withPrompts({ - applicationType: 'uaa', - baseName: 'jhipster-uaa', - packageName: 'com.mycompany.myapp', - packageFolder: 'com/mycompany/myapp', - serverPort: '9999', - authenticationType: 'uaa', - cacheProvider: 'no', - enableHibernateCache: false, - databaseType: 'sql', - devDatabaseType: 'mysql', - prodDatabaseType: 'mysql', - enableTranslation: true, - nativeLanguage: 'en', - languages: ['fr'], - buildTool: 'maven', - rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', - serverSideOptions: [], - serviceDiscoveryType: 'eureka', - }) - .on('end', done); - }); - - it('creates expected files with the UAA application type', () => { - assert.file(expectedFiles.uaa); - assert.file(expectedFiles.dockerServices); - assert.file(expectedFiles.eureka); - }); - }); - - describe('UAA gateway with eureka', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') - .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) - .inTmpDir(dir => { - fse.copySync(path.join(__dirname, '../test/templates/uaaserver/'), dir); - }) - .withPrompts({ - applicationType: 'gateway', - baseName: 'jhipster', - packageName: 'com.mycompany.myapp', - packageFolder: 'com/mycompany/myapp', - serverPort: '8080', - authenticationType: 'uaa', - uaaBaseName: './uaa/', - cacheProvider: 'hazelcast', - enableHibernateCache: true, - databaseType: 'sql', - devDatabaseType: 'mysql', - prodDatabaseType: 'mysql', - enableTranslation: true, - nativeLanguage: 'en', - languages: ['fr'], - buildTool: 'maven', - rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', - serverSideOptions: [], - serviceDiscoveryType: 'eureka', - }) - .on('end', done); - }); - - it('creates expected files for UAA auth with the Gateway application type', () => { - assert.file(expectedFiles.gateway); - assert.file(expectedFiles.rateLimitingFilesForGateways); - assert.file(expectedFiles.gatewayWithUaa); - assert.file(expectedFiles.dockerServices); - assert.file(expectedFiles.eureka); - assert.file(expectedFiles.hazelcast); - }); - }); }); context('Consul', () => { describe('gateway with consul', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ applicationType: 'gateway', baseName: 'jhipster', @@ -2606,44 +2166,35 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', - languages: ['fr'], + languages: ['fr', 'en'], buildTool: 'maven', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with the gateway application type', () => { - assert.file(expectedFiles.jwtServer); + assert.file(expectedFiles.jwtServerGateway); assert.file(expectedFiles.gateway); - assert.file(expectedFiles.rateLimitingFilesForGateways); assert.noFile(expectedFiles.eureka); assert.file(expectedFiles.consul); }); }); describe('gateway with consul and rate limiting', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ applicationType: 'gateway', baseName: 'jhipster', @@ -2656,44 +2207,35 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', - languages: ['fr'], + languages: ['fr', 'en'], buildTool: 'maven', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with the gateway application type', () => { - assert.file(expectedFiles.jwtServer); + assert.file(expectedFiles.jwtServerGateway); assert.file(expectedFiles.gateway); - assert.file(expectedFiles.rateLimitingFilesForGateways); assert.noFile(expectedFiles.eureka); assert.file(expectedFiles.consul); }); }); describe('microservice with consul', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ applicationType: 'microservice', baseName: 'jhipster', @@ -2704,16 +2246,16 @@ describe('JHipster generator', () => { cacheProvider: 'ehcache', enableHibernateCache: true, databaseType: 'sql', - devDatabaseType: 'mysql', - prodDatabaseType: 'mysql', + devDatabaseType: 'postgresql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', - languages: ['fr'], + languages: ['fr', 'en'], buildTool: 'maven', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with the microservice application type', () => { @@ -2728,23 +2270,15 @@ describe('JHipster generator', () => { context('No Service Discovery', () => { describe('gateway with no service discovery', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ applicationType: 'gateway', baseName: 'jhipster', @@ -2757,95 +2291,35 @@ describe('JHipster generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', - enableTranslation: true, - nativeLanguage: 'en', - languages: ['fr'], - buildTool: 'maven', - rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', - serverSideOptions: [], - }) - .on('end', done); - }); - - it('creates expected files with the gateway application type', () => { - assert.file(expectedFiles.jwtServer); - assert.noFile(expectedFiles.gateway); - assert.noFile(expectedFiles.rateLimitingFilesForGateways); - assert.noFile(expectedFiles.eureka); - assert.noFile(expectedFiles.consul); - }); - }); - - describe('UAA gateway with no service discovery', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') - .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', - 'uaa-base-name': 'jhipsterApp', - }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) - .withPrompts({ - applicationType: 'gateway', - baseName: 'jhipster', - packageName: 'com.mycompany.myapp', - packageFolder: 'com/mycompany/myapp', - clientFramework: ANGULAR, - serviceDiscoveryType: false, - authenticationType: 'uaa', - uaaBaseName: 'jhipsterApp', - cacheProvider: 'ehcache', - enableHibernateCache: true, - databaseType: 'sql', - devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', - languages: ['fr'], + languages: ['fr', 'en'], buildTool: 'maven', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with the gateway application type', () => { - assert.file(expectedFiles.gatewayWithUaa); + assert.file(expectedFiles.jwtServerGateway); assert.noFile(expectedFiles.gateway); - assert.noFile(expectedFiles.rateLimitingFilesForGateways); assert.noFile(expectedFiles.eureka); assert.noFile(expectedFiles.consul); }); }); describe('microservice with no service discovery', () => { - before(done => { - helpers - .run('generator-jhipster/generators/app') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ - 'from-cli': true, - skipInstall: true, - skipChecks: true, - blueprint: 'kotlin', + jhiprefix: 'test', + withgeneratedflag: true, 'skip-ktlint-format': true, + blueprints: 'kotlin', }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ applicationType: 'microservice', baseName: 'jhipster', @@ -2855,17 +2329,16 @@ describe('JHipster generator', () => { authenticationType: 'jwt', cacheProvider: 'ehcache', enableHibernateCache: true, - databaseType: 'sql', - devDatabaseType: 'mysql', - prodDatabaseType: 'mysql', + devDatabaseType: 'postgresql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', - languages: ['fr'], + languages: ['fr', 'en'], buildTool: 'maven', rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files with the microservice application type', () => { @@ -2877,5 +2350,4 @@ describe('JHipster generator', () => { }); }); }); - // TODO: Add enum test }); diff --git a/test/entity.spec.js b/test/entity.spec.js index 3ad792901..236a58bc4 100644 --- a/test/entity.spec.js +++ b/test/entity.spec.js @@ -1,39 +1,30 @@ const path = require('path'); const assert = require('yeoman-assert'); -const helpers = require('yeoman-test'); const fse = require('fs-extra'); + const constants = require('generator-jhipster/generators/generator-constants'); +const { skipPrettierHelpers: helpers } = require('./utils/utils'); + const expectedFiles = require('./utils/expected-files').entity; -const CLIENT_MAIN_SRC_DIR = constants.CLIENT_MAIN_SRC_DIR; -const SERVER_MAIN_SRC_DIR = `${constants.MAIN_DIR}kotlin/`; -const SERVER_MAIN_RES_DIR = constants.SERVER_MAIN_RES_DIR; -const SERVER_TEST_SRC_DIR = `${constants.TEST_DIR}kotlin/`; +const { CLIENT_MAIN_SRC_DIR, MAIN_DIR, SERVER_MAIN_RES_DIR, TEST_DIR } = constants; + +const SERVER_MAIN_KOTLIN_SRC_DIR = `${MAIN_DIR}kotlin/`; +const SERVER_TEST_KOTLIN_SRC_DIR = `${TEST_DIR}kotlin/`; describe('JHipster generator for entity', () => { context('creation from CLI', () => { context('monolith with elasticsearch', () => { describe('search, no dto, no service, no pagination', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/default-elasticsearch'), dir); }) + .withOptions({ + 'skip-ktlint-format': true, + }) .withArguments(['foo']) .withPrompts({ fieldAdd: false, @@ -41,12 +32,11 @@ describe('JHipster generator for entity', () => { dto: 'no', service: 'no', pagination: 'no', - }) - .on('end', done); + }); }); it('does creates search files', () => { - assert.file(`${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/repository/search/FooSearchRepository.kt`); + assert.file(`${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/repository/search/FooSearchRepository.kt`); assert.file(expectedFiles.server); assert.file(expectedFiles.gatling); }); @@ -55,27 +45,18 @@ describe('JHipster generator for entity', () => { context('monolith with couchbase FTS', () => { describe('Couchbase search, no dto, no service, no pagination', () => { - before(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/default-couchbase-search'), dir); }) - .withOptions({ creationTimestamp: '2016-01-20', withEntities: true }) + .withOptions({ + creationTimestamp: '2016-01-20', + withEntities: true, + 'skip-ktlint-format': true, + blueprints: 'kotlin', + }) .withArguments(['foo']) .withPrompts({ fieldAdd: false, @@ -83,8 +64,7 @@ describe('JHipster generator for entity', () => { dto: 'no', service: 'no', pagination: 'no', - }) - .on('end', done); + }); }); it('does creates search files', () => { @@ -97,26 +77,16 @@ describe('JHipster generator for entity', () => { context('monolith with entity and dto suffixes', () => { describe('with entity and dto suffixes', () => { - beforeEach(done => { + before(() => helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + .create(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/entity-dto-suffixes'), dir); }) + .withOptions({ + 'skip-ktlint-format': true, + blueprints: 'kotlin', + }) .withArguments(['foo']) .withPrompts({ fieldAdd: false, @@ -124,108 +94,92 @@ describe('JHipster generator for entity', () => { dto: 'mapstruct', service: 'serviceImpl', }) - .on('end', done); - }); + .run() + ); it('creates expected files with suffix', () => { assert.file([ '.jhipster/Foo.json', - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/domain/FooXXX.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/repository/FooRepository.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/web/rest/FooResource.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/dto/FooYYY.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/mapper/FooMapper.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/FooService.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/domain/FooXXX.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/repository/FooRepository.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/web/rest/FooResource.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/service/dto/FooYYY.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/service/mapper/FooMapper.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/service/FooService.kt`, ]); + }); + it('correctly writes the repository', () => { assert.fileContent( - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/repository/FooRepository.kt`, - 'interface FooRepository : ' + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/repository/FooRepository.kt`, + 'interface FooRepository ' ); + }); - assert.fileContent(`${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/domain/FooXXX.kt`, /.+^data class FooXXX\(/gms); + it('correctly writes the entity', () => { + assert.fileContent(`${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/domain/FooXXX.kt`, 'data class FooXXX'); + }); - assert.fileContent(`${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/dto/FooYYY.kt`, /.+^data class FooYYY\($.*/gms); + it('correctly writes the dto file', () => { + assert.fileContent(`${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/service/dto/FooYYY.kt`, 'data class FooYYY'); }); }); describe('with entity suffix and no dto', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/entity-dto-suffixes'), dir); }) + .withOptions({ + 'skip-ktlint-format': true, + blueprints: 'kotlin', + }) .withArguments(['foo']) .withPrompts({ fieldAdd: false, relationshipAdd: false, dto: 'no', service: 'serviceImpl', - }) - .on('end', done); + }); }); it('creates expected files with suffix', () => { assert.file([ '.jhipster/Foo.json', - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/domain/FooXXX.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/repository/FooRepository.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/web/rest/FooResource.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/FooService.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/domain/FooXXX.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/repository/FooRepository.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/web/rest/FooResource.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/service/FooService.kt`, ]); assert.noFile([ - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/dto/FooYYY.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/mapper/FooMapper.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/service/dto/FooYYY.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/service/mapper/FooMapper.kt`, ]); assert.fileContent( - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/repository/FooRepository.kt`, - 'interface FooRepository : ' + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/repository/FooRepository.kt`, + 'interface FooRepository ' ); - assert.fileContent(`${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/domain/FooXXX.kt`, /.+^data class FooXXX\(/gms); + assert.fileContent(`${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/domain/FooXXX.kt`, 'data class FooXXX'); }); }); }); context('monolith with angularX', () => { describe('no dto, no service, no pagination', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/default-ng2'), dir); }) + .withOptions({ + 'skip-ktlint-format': true, + }) .withArguments(['foo']) .withPrompts({ fieldAdd: false, @@ -233,38 +187,27 @@ describe('JHipster generator for entity', () => { dto: 'no', service: 'no', pagination: 'no', - }) - .on('end', done); + }); }); it('creates expected default files', () => { assert.file(expectedFiles.server); assert.file(expectedFiles.clientNg2); assert.file(expectedFiles.gatling); + assert.file(expectedFiles.fakeData); }); }); describe('no dto, no service, with pagination', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/default-ng2'), dir); }) + .withOptions({ + 'skip-ktlint-format': true, + }) .withArguments(['foo']) .withPrompts({ fieldAdd: false, @@ -272,8 +215,7 @@ describe('JHipster generator for entity', () => { dto: 'no', service: 'no', pagination: 'pagination', - }) - .on('end', done); + }); }); it('creates expected default files', () => { @@ -284,26 +226,15 @@ describe('JHipster generator for entity', () => { }); describe('no dto, no service, with infinite-scroll', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/default-ng2'), dir); }) + .withOptions({ + 'skip-ktlint-format': true, + }) .withArguments(['foo']) .withPrompts({ fieldAdd: false, @@ -311,8 +242,7 @@ describe('JHipster generator for entity', () => { dto: 'no', service: 'no', pagination: 'infinite-scroll', - }) - .on('end', done); + }); }); it('creates expected default files', () => { @@ -323,26 +253,15 @@ describe('JHipster generator for entity', () => { }); describe('no dto, with serviceImpl, no pagination', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/default-ng2'), dir); }) + .withOptions({ + 'skip-ktlint-format': true, + }) .withArguments(['foo']) .withPrompts({ fieldAdd: false, @@ -350,8 +269,7 @@ describe('JHipster generator for entity', () => { dto: 'no', service: 'serviceImpl', pagination: 'no', - }) - .on('end', done); + }); }); it('creates expected default files', () => { @@ -359,33 +277,22 @@ describe('JHipster generator for entity', () => { assert.file(expectedFiles.clientNg2); assert.file(expectedFiles.gatling); assert.file([ - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/FooService.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/impl/FooServiceImpl.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/service/FooService.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/service/impl/FooServiceImpl.kt`, ]); }); }); describe('with dto, service, no pagination', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/default-ng2'), dir); }) + .withOptions({ + 'skip-ktlint-format': true, + }) .withArguments(['foo']) .withPrompts({ fieldAdd: false, @@ -393,8 +300,7 @@ describe('JHipster generator for entity', () => { dto: 'mapstruct', service: 'serviceClass', pagination: 'no', - }) - .on('end', done); + }); }); it('creates expected default files', () => { @@ -402,44 +308,33 @@ describe('JHipster generator for entity', () => { assert.file(expectedFiles.clientNg2); assert.file(expectedFiles.gatling); assert.file([ - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/dto/FooDTO.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/mapper/FooMapper.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/FooService.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/service/dto/FooDTO.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/service/mapper/FooMapper.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/service/FooService.kt`, ]); }); }); describe('with angular suffix', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/default-ng2'), dir); }) .withArguments(['foo']) - .withOptions({ 'angular-suffix': 'management' }) + .withOptions({ + angularSuffix: 'management', + + 'skip-ktlint-format': true, + }) .withPrompts({ fieldAdd: false, relationshipAdd: false, dto: 'yes', service: 'serviceImpl', pagination: 'infinite-scroll', - }) - .on('end', done); + }); }); it('creates expected default files', () => { @@ -451,36 +346,25 @@ describe('JHipster generator for entity', () => { }); describe('with client-root-folder', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/default-ng2'), dir); }) .withArguments(['foo']) - .withOptions({ 'client-root-folder': 'test-root' }) + .withOptions({ + clientRootFolder: 'test-root', + + 'skip-ktlint-format': true, + }) .withPrompts({ fieldAdd: false, relationshipAdd: false, dto: 'yes', service: 'serviceImpl', pagination: 'infinite-scroll', - }) - .on('end', done); + }); }); it('creates expected default files', () => { @@ -492,37 +376,26 @@ describe('JHipster generator for entity', () => { }); describe('with client-root-folder and angular-suffix', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/default-ng2'), dir); }) .withArguments(['foo']) - .withOptions({ 'client-root-folder': 'test-root' }) - .withOptions({ 'angular-suffix': 'management' }) + .withOptions({ + clientRootFolder: 'test-root', + angularSuffix: 'management', + + 'skip-ktlint-format': true, + }) .withPrompts({ fieldAdd: false, relationshipAdd: false, dto: 'yes', service: 'serviceImpl', pagination: 'infinite-scroll', - }) - .on('end', done); + }); }); it('creates expected default files', () => { @@ -534,28 +407,44 @@ describe('JHipster generator for entity', () => { }); }); - context('no i18n', () => { - describe('with dto, serviceImpl, with hazelcast, elasticsearch', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') + context('fake data', () => { + describe('sql database with fake data disabled', () => { + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) + .inTmpDir(dir => { + fse.copySync(path.join(__dirname, '../test/templates/psql-with-no-fake-data'), dir); + }) .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, 'skip-ktlint-format': true, }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + .withArguments(['foo']) + .withPrompts({ + fieldAdd: false, + relationshipAdd: false, + dto: 'no', + service: 'no', + pagination: 'no', + }); + }); + + it('creates expected default files', () => { + assert.noFile(expectedFiles.fakeData); + }); + }); + }); + + context('no i18n', () => { + describe('with dto, serviceImpl, with hazelcast, elasticsearch', () => { + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/noi18n'), dir); }) + .withOptions({ + 'skip-ktlint-format': true, + }) .withArguments(['foo']) .withPrompts({ fieldAdd: false, @@ -563,8 +452,7 @@ describe('JHipster generator for entity', () => { dto: 'yes', service: 'serviceImpl', pagination: 'infinite-scroll', - }) - .on('end', done); + }); }); it('creates expected default files', () => { @@ -578,26 +466,15 @@ describe('JHipster generator for entity', () => { context('all languages', () => { describe('no dto, no service, no pagination', () => { - beforeEach(done => { - helpers + before(async () => { + await helpers .run(require.resolve('generator-jhipster/generators/entity')) - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/all-languages'), dir); }) + .withOptions({ + 'skip-ktlint-format': true, + }) .withArguments(['foo']) .withPrompts({ fieldAdd: false, @@ -605,8 +482,7 @@ describe('JHipster generator for entity', () => { dto: 'no', service: 'no', pagination: 'no', - }) - .on('end', done); + }); }); it('creates expected languages files', () => { @@ -617,36 +493,25 @@ describe('JHipster generator for entity', () => { }); describe('no dto, no service, no pagination with client-root-folder', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/all-languages'), dir); }) .withArguments(['foo']) - .withOptions({ 'client-root-folder': 'test-root' }) + .withOptions({ + clientRootFolder: 'test-root', + + 'skip-ktlint-format': true, + }) .withPrompts({ fieldAdd: false, relationshipAdd: false, dto: 'no', service: 'no', pagination: 'no', - }) - .on('end', done); + }); }); it('creates expected languages files', () => { @@ -660,36 +525,25 @@ describe('JHipster generator for entity', () => { context('microservice', () => { describe('with client-root-folder microservice', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/default-microservice'), dir); }) .withArguments(['foo']) - .withOptions({ 'client-root-folder': 'test-root' }) + .withOptions({ + clientRootFolder: 'test-root', + + 'skip-ktlint-format': true, + }) .withPrompts({ fieldAdd: false, relationshipAdd: false, dto: 'yes', service: 'serviceImpl', pagination: 'infinite-scroll', - }) - .on('end', done); + }); }); it('sets expected custom clientRootFolder', () => { @@ -700,26 +554,15 @@ describe('JHipster generator for entity', () => { }); describe('with default microservice', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/default-microservice'), dir); }) + .withOptions({ + 'skip-ktlint-format': true, + }) .withArguments(['foo']) .withPrompts({ fieldAdd: false, @@ -727,8 +570,7 @@ describe('JHipster generator for entity', () => { dto: 'yes', service: 'serviceImpl', pagination: 'pagination', - }) - .on('end', done); + }); }); it('sets expected default clientRootFolder', () => { @@ -742,26 +584,15 @@ describe('JHipster generator for entity', () => { }); describe('with mongodb microservice', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/mongodb-with-relations'), dir); }) + .withOptions({ + 'skip-ktlint-format': true, + }) .withArguments(['foo']) .withPrompts({ fieldAdd: false, @@ -769,8 +600,7 @@ describe('JHipster generator for entity', () => { dto: 'yes', service: 'serviceImpl', pagination: 'pagination', - }) - .on('end', done); + }); }); it('sets expected custom databaseType', () => { @@ -781,32 +611,20 @@ describe('JHipster generator for entity', () => { context('gateway', () => { describe('with entity from microservice', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/default-gateway'), dir); }) + .withOptions({ + 'skip-ktlint-format': true, + }) .withPrompts({ useMicroserviceJson: true, - microservicePath: '../', + microservicePath: 'microservice1', }) - .withArguments(['bar']) - .on('end', done); + .withArguments(['bar']); }); it('sets expected default clientRootFolder', () => { @@ -816,42 +634,33 @@ describe('JHipster generator for entity', () => { assert.file(`${CLIENT_MAIN_SRC_DIR}i18n/en/sampleMicroserviceBar.json`); assert.file(expectedFiles.clientNg2GatewayMicroserviceEntity); assert.noFile(expectedFiles.gatling); - assert.fileContent(`${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/bar.service.ts`, 'samplemicroservice'); + assert.fileContent( + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/service/bar.service.ts`, + 'samplemicroservice' + ); assert.fileContent( `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/bar.module.ts`, 'SampleMicroserviceBarModule' ); - assert.noFile(`${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/web/rest/BarResource.kt`); + assert.noFile(`${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/web/rest/BarResource.kt`); }); }); describe('with entity from microservice and custom client-root-folder', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/default-gateway'), dir); }) + .withOptions({ + 'skip-ktlint-format': true, + }) .withArguments(['foo']) .withPrompts({ useMicroserviceJson: true, - microservicePath: '../', - }) - .on('end', done); + microservicePath: 'microservice1', + }); }); it('sets expected custom clientRootFolder', () => { @@ -861,37 +670,25 @@ describe('JHipster generator for entity', () => { assert.file(`${CLIENT_MAIN_SRC_DIR}i18n/en/testRootFoo.json`); assert.file(expectedFiles.clientNg2WithRootFolder); assert.noFile(expectedFiles.gatling); - assert.noFile(`${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/web/rest/FooResource.kt`); + assert.noFile(`${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/web/rest/FooResource.kt`); }); }); describe('with entity from mongodb microservice', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/default-gateway'), dir); }) + .withOptions({ + 'skip-ktlint-format': true, + }) .withArguments(['baz']) .withPrompts({ useMicroserviceJson: true, - microservicePath: '../', - }) - .on('end', done); + microservicePath: 'microservice1', + }); }); it('sets expected custom databaseType from the microservice', () => { @@ -901,34 +698,19 @@ describe('JHipster generator for entity', () => { assert.file(expectedFiles.clientBazGatewayMicroserviceEntity); }); it('generates a string id for the mongodb entity', () => { - assert.fileContent(`${CLIENT_MAIN_SRC_DIR}app/shared/model/sampleMicroservice/baz.model.ts`, 'id?: string'); + assert.fileContent(`${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/baz.model.ts`, 'id?: string'); }); }); }); describe('with creation timestamp', () => { - before(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - creationTimestamp: '2016-01-20', - withEntities: true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/default-ng2'), dir); }) + .withOptions({ creationTimestamp: '2016-01-20', withEntities: true, 'skip-ktlint-format': true }) .withArguments(['foo']) .withPrompts({ fieldAdd: false, @@ -936,8 +718,7 @@ describe('JHipster generator for entity', () => { dto: 'no', service: 'no', pagination: 'pagination', - }) - .on('end', done); + }); }); it('creates expected default files', () => { @@ -949,27 +730,17 @@ describe('JHipster generator for entity', () => { }); describe('with formated creation timestamp', () => { - before(done => { - helpers - .run('generator-jhipster/generators/entity') + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) + .inTmpDir(dir => { + fse.copySync(path.join(__dirname, '../test/templates/default-ng2'), dir); + }) .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, creationTimestamp: '2016-01-20T00:00:00.000Z', withEntities: true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) - .inTmpDir(dir => { - fse.copySync(path.join(__dirname, '../test/templates/default-ng2'), dir); + + 'skip-ktlint-format': true, }) .withArguments(['foo']) .withPrompts({ @@ -978,8 +749,7 @@ describe('JHipster generator for entity', () => { dto: 'no', service: 'no', pagination: 'pagination', - }) - .on('end', done); + }); }); it('creates expected default files', () => { @@ -991,27 +761,13 @@ describe('JHipster generator for entity', () => { }); describe('with wrong base changelog date', () => { - before(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - baseChangelogDate: '20-01-2016', - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/default-ng2'), dir); }) + .withOptions({ baseChangelogDate: '20-01-2016', 'skip-ktlint-format': true }) .withArguments(['foo']) .withPrompts({ fieldAdd: false, @@ -1019,8 +775,7 @@ describe('JHipster generator for entity', () => { dto: 'no', service: 'no', pagination: 'pagination', - }) - .on('end', done); + }); }); it('creates expected default files', () => { @@ -1035,33 +790,15 @@ describe('JHipster generator for entity', () => { context('regeneration from json file', () => { context('monolith with angularX', () => { describe('no dto, no service, no pagination', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { - fse.copySync(path.join(__dirname, '../test/templates/default-ng2'), dir); - fse.copySync( - path.join(__dirname, '../test/templates/export-jdl/.jhipster/Country.json'), - path.join(dir, '.jhipster/Foo.json') - ); + fse.copySync(path.join(__dirname, './templates/default-ng2'), dir); + fse.copySync(path.join(__dirname, 'templates/.jhipster/Simple.json'), path.join(dir, '.jhipster/Foo.json')); }) .withArguments(['Foo']) - .withOptions({ regenerate: true, force: true }) - .on('end', done); + .withOptions({ regenerate: true, force: true, 'skip-ktlint-format': true }); }); it('creates expected default files', () => { @@ -1069,41 +806,28 @@ describe('JHipster generator for entity', () => { assert.file(expectedFiles.clientNg2); assert.file(expectedFiles.gatling); }); - it('generates swagger annotations on domain model', () => { - assert.fileContent(`${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/domain/Foo.kt`, /@ApiModelProperty/); + it('generates OpenAPI annotations on domain model', () => { + assert.fileContent(`${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/domain/Foo.kt`, /@ApiModelProperty/); }); }); }); describe('with --skip-db-changelog', () => { describe('SQL database', () => { - before(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/default-ng2'), dir); - fse.copySync( - path.join(__dirname, '../test/templates/export-jdl/.jhipster/Country.json'), - path.join(dir, '.jhipster/Foo.json') - ); + fse.copySync(path.join(__dirname, 'templates/.jhipster/Simple.json'), path.join(dir, '.jhipster/Foo.json')); }) .withArguments(['Foo']) - .withOptions({ regenerate: true, force: true, skipDbChangelog: true }) - .on('end', done); + .withOptions({ + regenerate: true, + force: true, + skipDbChangelog: true, + 'skip-ktlint-format': true, + }); }); it('creates expected default files', () => { @@ -1120,36 +844,21 @@ describe('JHipster generator for entity', () => { }); describe('Cassandra database', () => { - before(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { - fse.copySync( - path.join(__dirname, '../node_modules/generator-jhipster/test/templates/compose/05-cassandra'), - dir - ); - fse.copySync( - path.join(__dirname, '../test/templates/export-jdl/.jhipster/Country.json'), - path.join(dir, '.jhipster/Foo.json') - ); + fse.copySync(path.join(__dirname, '../test/templates/compose/05-cassandra'), dir); + fse.copySync(path.join(__dirname, 'templates/.jhipster/Simple.json'), path.join(dir, '.jhipster/Foo.json')); }) .withArguments(['Foo']) - .withOptions({ regenerate: true, force: true, skipDbChangelog: true }) - .on('end', done); + .withOptions({ + regenerate: true, + force: true, + skipDbChangelog: true, + 'skip-ktlint-format': true, + blueprints: 'kotlin', + }); }); it('creates expected default files', () => { @@ -1164,75 +873,46 @@ describe('JHipster generator for entity', () => { context('microservice', () => { describe('with dto, service, pagination', () => { - beforeEach(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/default-microservice'), dir); fse.copySync( - path.join(__dirname, '../test/templates/export-jdl/.jhipster/Employee.json'), + path.join(__dirname, 'templates/.jhipster/DtoServicePagination.json'), path.join(dir, '.jhipster/Foo.json') ); }) .withArguments(['Foo']) - .withOptions({ regenerate: true, force: true }) - .on('end', done); + .withOptions({ regenerate: true, force: true, 'skip-ktlint-format': true }); }); it('creates expected default files', () => { assert.file(expectedFiles.server); assert.noFile(expectedFiles.clientNg2); assert.file([ - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/dto/FooDTO.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/mapper/FooMapper.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/FooService.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/service/dto/FooDTO.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/service/mapper/FooMapper.kt`, + `${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/service/FooService.kt`, ]); }); - it('generates swagger annotations on DTO', () => { - assert.noFileContent(`${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/domain/Foo.kt`, /@ApiModelProperty/); - assert.fileContent(`${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/dto/FooDTO.kt`, /@ApiModelProperty/); + it('generates OpenAPI annotations on DTO', () => { + assert.noFileContent(`${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/domain/Foo.kt`, /@ApiModelProperty/); + assert.fileContent(`${SERVER_MAIN_KOTLIN_SRC_DIR}com/mycompany/myapp/service/dto/FooDTO.kt`, /@ApiModelProperty/); }); }); }); context('reproducible build', () => { describe('no dto, no service, no pagination', () => { - before(done => { - helpers - .run('generator-jhipster/generators/entity') - .withOptions({ - 'from-cli': true, - skipInstall: true, - blueprint: 'kotlin', - skipChecks: true, - 'skip-ktlint-format': true, - }) - .withGenerators([ - [ - require('../generators/entity-server'), // eslint-disable-line global-require - 'jhipster-kotlin:entity-server', - path.join(__dirname, '../generators/entity-server/index.js'), - ], - ]) + before(async () => { + await helpers + .run(require.resolve('generator-jhipster/generators/entity')) .inTmpDir(dir => { fse.copySync(path.join(__dirname, '../test/templates/reproducible'), dir); }) - .withArguments(['foo']) - .on('end', done); + .withOptions({ 'skip-ktlint-format': true }) + .withArguments(['foo']); }); it('creates expected default files', () => { @@ -1240,19 +920,47 @@ describe('JHipster generator for entity', () => { assert.file(expectedFiles.clientNg2); assert.file(expectedFiles.gatling); assert.file(expectedFiles.fakeData); + }); - assert.fileContent(`${SERVER_MAIN_RES_DIR}config/liquibase/fake-data/foo.csv`, /1;Junction;"03508"/); + it('creates reproducible liquibase data', () => { + assert.fileContent(`${SERVER_MAIN_RES_DIR}config/liquibase/fake-data/foo.csv`, /1;Qatari salmon Monitored;65526;"6"/); + }); + it('creates reproducible backend test', () => { assert.fileContent( - `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/web/rest/FooResourceIT.kt`, - /DEFAULT_NUMBER_PATTERN_REQUIRED = "099573"/ + `${SERVER_TEST_KOTLIN_SRC_DIR}com/mycompany/myapp/web/rest/FooResourceIT.kt`, + /DEFAULT_NUMBER_PATTERN_REQUIRED = "4244"/ ); assert.fileContent( - `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/web/rest/FooResourceIT.kt`, - /UPDATED_NUMBER_PATTERN_REQUIRED = "5"/ + `${SERVER_TEST_KOTLIN_SRC_DIR}com/mycompany/myapp/web/rest/FooResourceIT.kt`, + /UPDATED_NUMBER_PATTERN_REQUIRED = "257856"/ ); }); }); }); }); + + describe('regeneration from app generator', () => { + describe('with creation timestamp', () => { + before(async () => { + await helpers + .create(require.resolve('../generators/app')) + .inTmpDir(dir => { + fse.copySync(path.join(__dirname, '../test/templates/default-ng2'), dir); + const jhipsterFolder = path.join(dir, '.jhipster'); + fse.ensureDirSync(jhipsterFolder); + fse.writeJsonSync(path.join(jhipsterFolder, 'Foo.json'), {}); + }) + .withOptions({ creationTimestamp: '2016-01-20', withEntities: true, 'skip-ktlint-format': true }) + .run(); + }); + + it('creates expected default files', () => { + assert.file(expectedFiles.server); + assert.file(expectedFiles.serverLiquibase); + assert.file(expectedFiles.clientNg2); + assert.file(expectedFiles.gatling); + }); + }); + }); }); diff --git a/test/server.spec.js b/test/server.spec.js index ed6efc0ad..d98ece4a6 100644 --- a/test/server.spec.js +++ b/test/server.spec.js @@ -7,23 +7,18 @@ const expectedFiles = require('./utils/expected-files'); describe('JHipster server generator', () => { describe('generate server with ehcache', () => { - before(done => { - helpers - .run('generator-jhipster/generators/server') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ + withGeneratedFlag: true, + blueprints: 'kotlin', 'from-cli': true, skipInstall: true, - blueprint: 'kotlin', skipChecks: true, 'skip-ktlint-format': true, + skipClient: true, }) - .withGenerators([ - [ - require('../generators/server'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -34,7 +29,7 @@ describe('JHipster server generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', languages: ['fr'], @@ -42,16 +37,16 @@ describe('JHipster server generator', () => { rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files for default configuration for server generator', () => { - assert.noFile(expectedFiles.common); + assert.file(expectedFiles.common); assert.file(expectedFiles.server); assert.file(expectedFiles.jwtServer); assert.file(expectedFiles.userManagementServer); assert.file(expectedFiles.maven); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); assert.noFile( getFilesForOptions( @@ -70,23 +65,18 @@ describe('JHipster server generator', () => { }); describe('generate server with caffeine', () => { - before(done => { - helpers - .run('generator-jhipster/generators/server') + before(async () => { + await helpers + .create(path.join(__dirname, '../generators/app')) .withOptions({ + withGeneratedFlag: true, + blueprints: 'kotlin', 'from-cli': true, skipInstall: true, - blueprint: 'kotlin', skipChecks: true, 'skip-ktlint-format': true, + skipClient: true, }) - .withGenerators([ - [ - require('../generators/server/index.js'), // eslint-disable-line global-require - 'jhipster-kotlin:server', - path.join(__dirname, '../generators/server/index.js'), - ], - ]) .withPrompts({ baseName: 'jhipster', packageName: 'com.mycompany.myapp', @@ -97,7 +87,7 @@ describe('JHipster server generator', () => { enableHibernateCache: true, databaseType: 'sql', devDatabaseType: 'h2Memory', - prodDatabaseType: 'mysql', + prodDatabaseType: 'postgresql', enableTranslation: true, nativeLanguage: 'en', languages: ['fr'], @@ -105,16 +95,16 @@ describe('JHipster server generator', () => { rememberMeKey: '5c37379956bd1242f5636c8cb322c2966ad81277', serverSideOptions: [], }) - .on('end', done); + .run(); }); it('creates expected files for caffeine cache configuration for server generator', () => { - assert.noFile(expectedFiles.common); + assert.file(expectedFiles.common); assert.file(expectedFiles.server); assert.file(expectedFiles.jwtServer); assert.file(expectedFiles.userManagementServer); assert.file(expectedFiles.maven); - assert.file(expectedFiles.mysql); + assert.file(expectedFiles.postgresql); assert.file(expectedFiles.hibernateTimeZoneConfig); assert.noFile( getFilesForOptions( diff --git a/test/spring-controller.spec.js b/test/spring-controller.spec.js index 140139009..6fc668db5 100644 --- a/test/spring-controller.spec.js +++ b/test/spring-controller.spec.js @@ -15,7 +15,7 @@ describe('JHipster generator spring-controller', () => { .withOptions({ 'from-cli': true, skipInstall: true, - blueprint: 'kotlin', + skipChecks: true, }) .inTmpDir(dir => { @@ -42,7 +42,7 @@ describe('JHipster generator spring-controller', () => { .withOptions({ 'from-cli': true, skipInstall: true, - blueprint: 'kotlin', + skipChecks: true, default: true, }) diff --git a/test/spring-service.spec.js b/test/spring-service.spec.js index 90de80b77..712ebeb0e 100644 --- a/test/spring-service.spec.js +++ b/test/spring-service.spec.js @@ -14,7 +14,7 @@ describe('JHipster generator service', () => { .withOptions({ 'from-cli': true, skipInstall: true, - blueprint: 'kotlin', + skipChecks: true, }) .inTmpDir(dir => { @@ -43,7 +43,7 @@ describe('JHipster generator service', () => { .withOptions({ 'from-cli': true, skipInstall: true, - blueprint: 'kotlin', + skipChecks: true, }) .inTmpDir(dir => { @@ -71,7 +71,7 @@ describe('JHipster generator service', () => { .withOptions({ 'from-cli': true, skipInstall: true, - blueprint: 'kotlin', + skipChecks: true, }) .inTmpDir(dir => { diff --git a/test/templates/.jhipster/DtoServicePagination.json b/test/templates/.jhipster/DtoServicePagination.json new file mode 100644 index 000000000..85a2cbf37 --- /dev/null +++ b/test/templates/.jhipster/DtoServicePagination.json @@ -0,0 +1,57 @@ +{ + "relationships": [], + "fields": [ + { + "fieldName": "employeeId", + "fieldType": "Long" + }, + { + "fieldName": "employeeUuid", + "fieldType": "UUID" + }, + { + "fieldName": "firstName", + "javadoc": "The firstname attribute.", + "fieldType": "String" + }, + { + "fieldName": "lastName", + "fieldType": "String" + }, + { + "fieldName": "email", + "fieldType": "String" + }, + { + "fieldName": "phoneNumber", + "fieldType": "String" + }, + { + "fieldName": "hireDate", + "fieldType": "ZonedDateTime" + }, + { + "fieldName": "salary", + "fieldType": "Long", + "fieldValidateRules": [ + "min", "max" + ], + "fieldValidateRulesMin": 10000, + "fieldValidateRulesMax": 1000000 + }, + { + "fieldName": "commissionPct", + "fieldType": "Long" + } + ], + "changelogDate": "20160926083805", + "javadoc": "The Employee entity.", + "entityTableName": "emp", + "dto": "mapstruct", + "pagination": "infinite-scroll", + "service": "serviceClass", + "fluentMethods": false, + "searchEngine": "elasticsearch", + "angularJSSuffix": "myentities", + "microserviceName": "mymicroservice" +} diff --git a/test/templates/.jhipster/Simple.json b/test/templates/.jhipster/Simple.json new file mode 100644 index 000000000..1f65c9b26 --- /dev/null +++ b/test/templates/.jhipster/Simple.json @@ -0,0 +1,20 @@ +{ + "fluentMethods": true, + "relationships": [], + "fields": [ + { + "fieldName": "simpleId", + "fieldType": "Long", + "javadoc": "The simple Id" + }, + { + "fieldName": "simpleName", + "fieldType": "String" + } + ], + "changelogDate": "20160926101210", + "entityTableName": "simple", + "dto": "no", + "pagination": "no", + "service": "no" +} diff --git a/test/templates/.jhipster/Simple2.json b/test/templates/.jhipster/Simple2.json new file mode 100644 index 000000000..5a1433da7 --- /dev/null +++ b/test/templates/.jhipster/Simple2.json @@ -0,0 +1,20 @@ +{ + "fluentMethods": true, + "relationships": [], + "fields": [ + { + "fieldName": "simpleId", + "fieldType": "Long", + "javadoc": "The simple Id" + }, + { + "fieldName": "simpleName", + "fieldType": "String" + } + ], + "changelogDate": "20160926101211", + "entityTableName": "simple", + "dto": "no", + "pagination": "no", + "service": "no" +} diff --git a/test/templates/.jhipster/Simple3.json b/test/templates/.jhipster/Simple3.json new file mode 100644 index 000000000..b20367c5b --- /dev/null +++ b/test/templates/.jhipster/Simple3.json @@ -0,0 +1,20 @@ +{ + "fluentMethods": true, + "relationships": [], + "fields": [ + { + "fieldName": "simpleId", + "fieldType": "Long", + "javadoc": "The simple Id" + }, + { + "fieldName": "simpleName", + "fieldType": "String" + } + ], + "changelogDate": "20160926101212", + "entityTableName": "simple", + "dto": "no", + "pagination": "no", + "service": "no" +} diff --git a/test/templates/all-languages/.yo-rc.json b/test/templates/all-languages/.yo-rc.json index e937f1356..e5b4f9b5e 100644 --- a/test/templates/all-languages/.yo-rc.json +++ b/test/templates/all-languages/.yo-rc.json @@ -21,7 +21,7 @@ "applicationType": "monolith", "testFrameworks": [ "gatling", - "protractor" + "cypress" ], "jhiPrefix": "jhi", "enableTranslation": true, @@ -48,6 +48,7 @@ "de", "el", "hi", + "hr", "hu", "in", "it", diff --git a/test/templates/compose/01-gateway/.yo-rc.json b/test/templates/compose/01-gateway/.yo-rc.json new file mode 100644 index 000000000..df39a39c6 --- /dev/null +++ b/test/templates/compose/01-gateway/.yo-rc.json @@ -0,0 +1,30 @@ +{ + "generator-jhipster": { + "jhipsterVersion": "3.0.0", + "baseName": "jhgate", + "packageName": "com.mycompany.myapp", + "packageFolder": "com/mycompany/myapp", + "serverPort": "8080", + "authenticationType": "jwt", + "cacheProvider": "hazelcast", + "enableHibernateCache": true, + "websocket": "no", + "databaseType": "sql", + "devDatabaseType": "h2Disk", + "prodDatabaseType": "mysql", + "searchEngine": "no", + "serviceDiscoveryType": "eureka", + "buildTool": "maven", + "jwtSecretKey": "fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8", + "applicationType": "gateway", + "testFrameworks": [ + "gatling" + ], + "jhiPrefix": "jhi", + "enableTranslation": true, + "nativeLanguage": "en", + "languages": [ + "en" + ] + } +} diff --git a/test/templates/compose/01-gateway/src/main/docker/app.yml b/test/templates/compose/01-gateway/src/main/docker/app.yml new file mode 100644 index 000000000..e72b48b2e --- /dev/null +++ b/test/templates/compose/01-gateway/src/main/docker/app.yml @@ -0,0 +1,42 @@ +version: '2' +services: + jhgate-app: + image: jhgate + environment: + - SPRING_PROFILES_ACTIVE=prod + - SPRING_CLOUD_CONFIG_URI=http://admin:admin@jhipster-registry:8761/config + - SPRING_DATASOURCE_URL=jdbc:mysql://jhgate-mysql:3306/jhgate?useUnicode=true&characterEncoding=utf8&useSSL=false&createDatabaseIfNotExist=true + ports: + - 8080:8080 + jhgate-mysql: + image: <%= DOCKER_MYSQL %> + # volumes: + # - ~/volumes/jhipster/jhgate/mysql/:/var/lib/mysql/ + environment: + - MYSQL_USER=root + - MYSQL_ALLOW_EMPTY_PASSWORD=yes + - MYSQL_DATABASE=jhgate + ports: + - 3306:3306 + command: mysqld --lower_case_table_names=1 --skip-ssl --character_set_server=utf8mb4 --explicit_defaults_for_timestamp + jhipster-registry: + image: <%= DOCKER_JHIPSTER_REGISTRY %> + volumes: + - ./central-server-config:/central-config + # By default the JHipster Registry runs with the "dev" and "native" + # Spring profiles. + # "native" profile means the filesystem is used to store data, see + # http://cloud.spring.io/spring-cloud-config/spring-cloud-config.html + environment: + - _JAVA_OPTIONS=-Xmx512m -Xms256m + - SPRING_PROFILES_ACTIVE=dev<% if (authenticationType === 'oauth2') { %>,oauth2<% } %> + - SPRING_SECURITY_USER_PASSWORD=<%= adminPassword %> + - JHIPSTER_REGISTRY_PASSWORD=<%= adminPassword %> + - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_TYPE=native + - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_SEARCH_LOCATIONS=file:./central-config + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_TYPE=git + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_URI=https://github.com/jhipster/jhipster-registry/ + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_SEARCH_PATHS=central-config + ports: + - 8761:8761 + diff --git a/test/templates/compose/01-gateway/src/main/docker/mysql.yml b/test/templates/compose/01-gateway/src/main/docker/mysql.yml new file mode 100644 index 000000000..facacb1a3 --- /dev/null +++ b/test/templates/compose/01-gateway/src/main/docker/mysql.yml @@ -0,0 +1,13 @@ +version: '2' +services: + jhgate-mysql: + image: mysql:5.7.18 + # volumes: + # - ~/volumes/jhipster/jhgate/mysql/:/var/lib/mysql/ + environment: + - MYSQL_USER=root + - MYSQL_ALLOW_EMPTY_PASSWORD=yes + - MYSQL_DATABASE=jhgate + ports: + - 3306:3306 + command: mysqld --lower_case_table_names=1 --skip-ssl --character_set_server=utf8mb4 --explicit_defaults_for_timestamp diff --git a/test/templates/compose/01-gateway/target/jib-cache/.gitkeep b/test/templates/compose/01-gateway/target/jib-cache/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/templates/uaaserver/uaa/.yo-rc.json b/test/templates/compose/02-mysql/.yo-rc.json similarity index 73% rename from test/templates/uaaserver/uaa/.yo-rc.json rename to test/templates/compose/02-mysql/.yo-rc.json index 7e628bec9..69df58f44 100644 --- a/test/templates/uaaserver/uaa/.yo-rc.json +++ b/test/templates/compose/02-mysql/.yo-rc.json @@ -1,11 +1,11 @@ { "generator-jhipster": { - "jhipsterVersion": "3.2.1", - "baseName": "uuaserver", + "jhipsterVersion": "3.0.0", + "baseName": "msmysql", "packageName": "com.mycompany.myapp", "packageFolder": "com/mycompany/myapp", - "serverPort": "9999", - "authenticationType": "uaa", + "serverPort": "8081", + "authenticationType": "jwt", "cacheProvider": "hazelcast", "enableHibernateCache": true, "databaseType": "sql", @@ -15,16 +15,17 @@ "buildTool": "maven", "jwtSecretKey": "fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8", "enableTranslation": true, - "applicationType": "uaa", + "applicationType": "microservice", + "serviceDiscoveryType": "eureka", "testFrameworks": [ "gatling" ], "jhiPrefix": "jhi", "skipClient": true, + "skipUserManagement": true, "nativeLanguage": "en", "languages": [ "en" - ], - "blueprint": "generator-jhipster-kotlin" + ] } } diff --git a/test/templates/compose/02-mysql/src/main/docker/app.yml b/test/templates/compose/02-mysql/src/main/docker/app.yml new file mode 100644 index 000000000..fb3c094ac --- /dev/null +++ b/test/templates/compose/02-mysql/src/main/docker/app.yml @@ -0,0 +1,40 @@ +version: '2' +services: + msmysql-app: + image: msmysql + environment: + - SPRING_PROFILES_ACTIVE=prod + - SPRING_CLOUD_CONFIG_URI=http://admin:admin@jhipster-registry:8761/config + - SPRING_DATASOURCE_URL=jdbc:mysql://msmysql-mysql:3306/msmysql?useUnicode=true&characterEncoding=utf8&useSSL=false&createDatabaseIfNotExist=true + msmysql-mysql: + image: <%= DOCKER_MYSQL %> + # volumes: + # - ~/volumes/jhipster/msmysql/mysql/:/var/lib/mysql/ + environment: + - MYSQL_USER=root + - MYSQL_ALLOW_EMPTY_PASSWORD=yes + - MYSQL_DATABASE=msmysql + ports: + - 3306:3306 + command: mysqld --lower_case_table_names=1 --skip-ssl --character_set_server=utf8mb4 --explicit_defaults_for_timestamp + jhipster-registry: + image: <%= DOCKER_JHIPSTER_REGISTRY %> + volumes: + - ./central-server-config:/central-config + # By default the JHipster Registry runs with the "dev" and "native" + # Spring profiles. + # "native" profile means the filesystem is used to store data, see + # http://cloud.spring.io/spring-cloud-config/spring-cloud-config.html + environment: + - _JAVA_OPTIONS=-Xmx512m -Xms256m + - SPRING_PROFILES_ACTIVE=dev<% if (authenticationType === 'oauth2') { %>,oauth2<% } %> + - SPRING_SECURITY_USER_PASSWORD=<%= adminPassword %> + - JHIPSTER_REGISTRY_PASSWORD=<%= adminPassword %> + - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_TYPE=native + - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_SEARCH_LOCATIONS=file:./central-config + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_TYPE=git + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_URI=https://github.com/jhipster/jhipster-registry/ + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_SEARCH_PATHS=central-config + ports: + - 8761:8761 + diff --git a/test/templates/compose/02-mysql/src/main/docker/mysql.yml b/test/templates/compose/02-mysql/src/main/docker/mysql.yml new file mode 100644 index 000000000..ea22d34ce --- /dev/null +++ b/test/templates/compose/02-mysql/src/main/docker/mysql.yml @@ -0,0 +1,13 @@ +version: '2' +services: + msmysql-mysql: + image: mysql:5.7.18 + # volumes: + # - ~/volumes/jhipster/msmysql/mysql/:/var/lib/mysql/ + environment: + - MYSQL_USER=root + - MYSQL_ALLOW_EMPTY_PASSWORD=yes + - MYSQL_DATABASE=msmysql + ports: + - 3306:3306 + command: mysqld --lower_case_table_names=1 --skip-ssl --character_set_server=utf8mb4 --explicit_defaults_for_timestamp diff --git a/test/templates/compose/02-mysql/target/jib-cache/.gitkeep b/test/templates/compose/02-mysql/target/jib-cache/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/templates/compose/03-psql/.yo-rc.json b/test/templates/compose/03-psql/.yo-rc.json new file mode 100644 index 000000000..eb8b50496 --- /dev/null +++ b/test/templates/compose/03-psql/.yo-rc.json @@ -0,0 +1,31 @@ +{ + "generator-jhipster": { + "jhipsterVersion": "3.0.0", + "baseName": "mspsql", + "packageName": "com.mycompany.myapp", + "packageFolder": "com/mycompany/myapp", + "serverPort": "8081", + "authenticationType": "jwt", + "cacheProvider": "hazelcast", + "enableHibernateCache": true, + "databaseType": "sql", + "devDatabaseType": "h2Disk", + "prodDatabaseType": "postgresql", + "searchEngine": "elasticsearch", + "buildTool": "maven", + "jwtSecretKey": "fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8", + "enableTranslation": true, + "applicationType": "microservice", + "serviceDiscoveryType": "eureka", + "testFrameworks": [ + "gatling" + ], + "jhiPrefix": "jhi", + "skipClient": true, + "skipUserManagement": true, + "nativeLanguage": "en", + "languages": [ + "en" + ] + } +} diff --git a/test/templates/compose/03-psql/src/main/docker/app.yml b/test/templates/compose/03-psql/src/main/docker/app.yml new file mode 100644 index 000000000..a708ee713 --- /dev/null +++ b/test/templates/compose/03-psql/src/main/docker/app.yml @@ -0,0 +1,46 @@ +version: '2' +services: + mspsql-app: + image: mspsql + environment: + - SPRING_PROFILES_ACTIVE=prod + - SPRING_CLOUD_CONFIG_URI=http://admin:admin@jhipster-registry:8761/config + - SPRING_DATASOURCE_URL=jdbc:postgresql://mspsql-postgresql:5432/mspsql + - SPRING_ELASTICSEARCH_REST_URIS=http://mspsql-elasticsearch:9200 + mspsql-postgresql: + image: <%= DOCKER_POSTGRESQL %> + # volumes: + # - ~/volumes/jhipster/mspsql/postgresql/:/var/lib/postgresql/ + environment: + - POSTGRES_USER=mspsql + - POSTGRES_PASSWORD= + ports: + - 5432:5432 + mspsql-elasticsearch: + image: <%= DOCKER_ELASTICSEARCH %> + # volumes: + # - ~/volumes/jhipster/mspsql/elasticsearch/:/usr/share/elasticsearch/data/ + ports: + - 9200:9200 + - 9300:9300 + jhipster-registry: + image: <%= DOCKER_JHIPSTER_REGISTRY %> + volumes: + - ./central-server-config:/central-config + # By default the JHipster Registry runs with the "dev" and "native" + # Spring profiles. + # "native" profile means the filesystem is used to store data, see + # http://cloud.spring.io/spring-cloud-config/spring-cloud-config.html + environment: + - _JAVA_OPTIONS=-Xmx512m -Xms256m + - SPRING_PROFILES_ACTIVE=dev<% if (authenticationType === 'oauth2') { %>,oauth2<% } %> + - SPRING_SECURITY_USER_PASSWORD=<%= adminPassword %> + - JHIPSTER_REGISTRY_PASSWORD=<%= adminPassword %> + - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_TYPE=native + - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_SEARCH_LOCATIONS=file:./central-config + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_TYPE=git + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_URI=https://github.com/jhipster/jhipster-registry/ + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_SEARCH_PATHS=central-config + ports: + - 8761:8761 + diff --git a/test/templates/compose/03-psql/src/main/docker/elasticsearch.yml b/test/templates/compose/03-psql/src/main/docker/elasticsearch.yml new file mode 100644 index 000000000..827308407 --- /dev/null +++ b/test/templates/compose/03-psql/src/main/docker/elasticsearch.yml @@ -0,0 +1,9 @@ +version: '2' +services: + mspsql-elasticsearch: + image: elasticsearch:2.4.6 + # volumes: + # - ~/volumes/jhipster/mspsql/elasticsearch/:/usr/share/elasticsearch/data/ + ports: + - 9200:9200 + - 9300:9300 diff --git a/test/templates/compose/03-psql/src/main/docker/postgresql.yml b/test/templates/compose/03-psql/src/main/docker/postgresql.yml new file mode 100644 index 000000000..259b22147 --- /dev/null +++ b/test/templates/compose/03-psql/src/main/docker/postgresql.yml @@ -0,0 +1,11 @@ +version: '2' +services: + mspsql-postgresql: + image: postgres:9.5.1 + # volumes: + # - ~/volumes/jhipster/mspsql/postgresql/:/var/lib/postgresql/ + environment: + - POSTGRES_USER=mspsql + - POSTGRES_PASSWORD= + ports: + - 5432:5432 diff --git a/test/templates/compose/03-psql/target/jib-cache/.gitkeep b/test/templates/compose/03-psql/target/jib-cache/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/templates/compose/04-mongo/.yo-rc.json b/test/templates/compose/04-mongo/.yo-rc.json new file mode 100644 index 000000000..90e078e30 --- /dev/null +++ b/test/templates/compose/04-mongo/.yo-rc.json @@ -0,0 +1,29 @@ +{ + "generator-jhipster": { + "jhipsterVersion": "3.0.0", + "baseName": "msmongodb", + "packageName": "com.mycompany.myapp", + "packageFolder": "com/mycompany/myapp", + "serverPort": "8081", + "authenticationType": "jwt", + "cacheProvider": "no", + "enableHibernateCache": false, + "databaseType": "mongodb", + "devDatabaseType": "mongodb", + "prodDatabaseType": "mongodb", + "buildTool": "maven", + "jwtSecretKey": "fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8", + "enableTranslation": true, + "applicationType": "microservice", + "testFrameworks": [ + "gatling" + ], + "jhiPrefix": "jhi", + "skipClient": true, + "skipUserManagement": true, + "nativeLanguage": "en", + "languages": [ + "en" + ] + } +} diff --git a/test/templates/compose/04-mongo/src/main/docker/app.yml b/test/templates/compose/04-mongo/src/main/docker/app.yml new file mode 100644 index 000000000..81d4a4e37 --- /dev/null +++ b/test/templates/compose/04-mongo/src/main/docker/app.yml @@ -0,0 +1,36 @@ +version: '2' +services: + msmongodb-app: + image: msmongodb + environment: + - SPRING_PROFILES_ACTIVE=prod + - SPRING_CLOUD_CONFIG_URI=http://admin:admin@jhipster-registry:8761/config + - SPRING_DATA_MONGODB_URI=mongodb://msmongodb-mongodb:27017 + - SPRING_DATA_MONGODB_DATABASE=msmongodb + msmongodb-mongodb: + image: <%= DOCKER_MONGODB %> + ports: + - "27017:27017" + # volumes: + # - ~/volumes/jhipster/msmongodb/mongodb/:/data/db/ + jhipster-registry: + image: <%= DOCKER_JHIPSTER_REGISTRY %> + volumes: + - ./central-server-config:/central-config + # By default the JHipster Registry runs with the "dev" and "native" + # Spring profiles. + # "native" profile means the filesystem is used to store data, see + # http://cloud.spring.io/spring-cloud-config/spring-cloud-config.html + environment: + - _JAVA_OPTIONS=-Xmx512m -Xms256m + - SPRING_PROFILES_ACTIVE=dev<% if (authenticationType === 'oauth2') { %>,oauth2<% } %> + - SPRING_SECURITY_USER_PASSWORD=<%= adminPassword %> + - JHIPSTER_REGISTRY_PASSWORD=<%= adminPassword %> + - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_TYPE=native + - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_SEARCH_LOCATIONS=file:./central-config + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_TYPE=git + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_URI=https://github.com/jhipster/jhipster-registry/ + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_SEARCH_PATHS=central-config + ports: + - 8761:8761 + diff --git a/test/templates/compose/04-mongo/src/main/docker/mongodb-cluster.yml b/test/templates/compose/04-mongo/src/main/docker/mongodb-cluster.yml new file mode 100644 index 000000000..387b335dd --- /dev/null +++ b/test/templates/compose/04-mongo/src/main/docker/mongodb-cluster.yml @@ -0,0 +1,15 @@ +version: '2' +services: + msmongodb-mongodb: + image: mongo:4.2.5 + ports: + - "27017:27017" + command: mongos --configdb csvr/msmongodb-mongodb-config --bind_ip 0.0.0.0 + msmongodb-mongodb-node: + build: + context: . + dockerfile: mongodb/MongoDB.Dockerfile + command: mongod --shardsvr --replSet rs1 + msmongodb-mongodb-config: + image: mongo:4.2.5 + command: mongod --configsvr --dbpath /data/db --replSet csvr diff --git a/test/templates/compose/04-mongo/src/main/docker/mongodb.yml b/test/templates/compose/04-mongo/src/main/docker/mongodb.yml new file mode 100644 index 000000000..39d64be0f --- /dev/null +++ b/test/templates/compose/04-mongo/src/main/docker/mongodb.yml @@ -0,0 +1,8 @@ +version: '2' +services: + msmongodb-mongodb: + image: mongo:4.2.3 + ports: + - "27017:27017" + # volumes: + # - ~/volumes/jhipster/msmongodb/mongodb/:/data/db/ diff --git a/test/templates/compose/04-mongo/target/jib-cache/.gitkeep b/test/templates/compose/04-mongo/target/jib-cache/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/templates/compose/05-cassandra/.yo-rc.json b/test/templates/compose/05-cassandra/.yo-rc.json new file mode 100644 index 000000000..fc00c0f75 --- /dev/null +++ b/test/templates/compose/05-cassandra/.yo-rc.json @@ -0,0 +1,31 @@ +{ + "generator-jhipster": { + "jhipsterVersion": "3.0.0", + "baseName": "mscassandra", + "packageName": "com.mycompany.myapp", + "packageFolder": "com/mycompany/myapp", + "serverPort": "8081", + "authenticationType": "jwt", + "cacheProvider": "no", + "enableHibernateCache": false, + "databaseType": "cassandra", + "devDatabaseType": "cassandra", + "prodDatabaseType": "cassandra", + "searchEngine": "no", + "buildTool": "maven", + "jwtSecretKey": "fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8", + "enableTranslation": true, + "applicationType": "microservice", + "testFrameworks": [ + "gatling" + ], + "jhiPrefix": "jhi", + "skipClient": true, + "skipUserManagement": true, + "nativeLanguage": "en", + "languages": [ + "en" + ], + "websocket": "no" + } +} diff --git a/test/templates/compose/05-cassandra/src/main/docker/app.yml b/test/templates/compose/05-cassandra/src/main/docker/app.yml new file mode 100644 index 000000000..655c70c87 --- /dev/null +++ b/test/templates/compose/05-cassandra/src/main/docker/app.yml @@ -0,0 +1,59 @@ +version: '2' +services: + mscassandra-app: + image: mscassandra + environment: + - SPRING_PROFILES_ACTIVE=prod + - SPRING_CLOUD_CONFIG_URI=http://admin:admin@jhipster-registry:8761/config + - SPRING_DATA_CASSANDRA_CONTACTPOINTS=cassandra + - JHIPSTER_SLEEP=30 # gives time for the Cassandra cluster to start and execute the migration scripts + mscassandra-cassandra: + build: + context: . + dockerfile: cassandra/Cassandra-Cluster.Dockerfile + environment: + - CASSANDRA_CONTACT_POINT=mscassandra-cassandra + # volumes: + # - ~/volumes/jhipster/mscassandra/cassandra/:/var/lib/cassandra/data + ports: + - 7000:7000 + - 7001:7001 + - 7199:7199 + - 9042:9042 + - 9160:9160 + mscassandra-cassandra-node: + image: <%= DOCKER_CASSANDRA %> + environment: + - CASSANDRA_SEEDS=mscassandra-cassandra + mscassandra-cassandra-migration: + environment: + - CASSANDRA_CONTACT_POINT=mscassandra-cassandra + - USER=docker-cassandra-migration + # - DEBUG_LOG=1 # uncomment to show debug logs during the migration process + - CREATE_KEYSPACE_SCRIPT=create-keyspace-prod.cql + build: + context: . + dockerfile: cassandra/Cassandra-Migration.Dockerfile + volumes: + - ../resources/config/cql:/cql:ro + jhipster-registry: + image: <%= DOCKER_JHIPSTER_REGISTRY %> + volumes: + - ./central-server-config:/central-config + # By default the JHipster Registry runs with the "dev" and "native" + # Spring profiles. + # "native" profile means the filesystem is used to store data, see + # http://cloud.spring.io/spring-cloud-config/spring-cloud-config.html + environment: + - _JAVA_OPTIONS=-Xmx512m -Xms256m + - SPRING_PROFILES_ACTIVE=dev<% if (authenticationType === 'oauth2') { %>,oauth2<% } %> + - SPRING_SECURITY_USER_PASSWORD=<%= adminPassword %> + - JHIPSTER_REGISTRY_PASSWORD=<%= adminPassword %> + - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_TYPE=native + - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_SEARCH_LOCATIONS=file:./central-config + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_TYPE=git + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_URI=https://github.com/jhipster/jhipster-registry/ + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_SEARCH_PATHS=central-config + ports: + - 8761:8761 + diff --git a/test/templates/compose/05-cassandra/src/main/docker/cassandra-cluster.yml b/test/templates/compose/05-cassandra/src/main/docker/cassandra-cluster.yml new file mode 100644 index 000000000..d748d8609 --- /dev/null +++ b/test/templates/compose/05-cassandra/src/main/docker/cassandra-cluster.yml @@ -0,0 +1,31 @@ +version: '2' +services: + mscassandra-cassandra: + build: + context: . + dockerfile: cassandra/Cassandra-Cluster.Dockerfile + environment: + - CASSANDRA_CONTACT_POINT=mscassandra-cassandra + # volumes: + # - ~/volumes/jhipster/mscassandra/cassandra/:/var/lib/cassandra/data + ports: + - 7000:7000 + - 7001:7001 + - 7199:7199 + - 9042:9042 + - 9160:9160 + mscassandra-cassandra-node: + image: cassandra:2.2.5 + environment: + - CASSANDRA_SEEDS=mscassandra-cassandra + mscassandra-cassandra-migration: + environment: + - CASSANDRA_CONTACT_POINT=mscassandra-cassandra + - USER=docker-cassandra-migration + # - DEBUG_LOG=1 # uncomment to show debug logs during the migration process + - CREATE_KEYSPACE_SCRIPT=create-keyspace-prod.cql + build: + context: . + dockerfile: cassandra/Cassandra-Migration.Dockerfile + volumes: + - ../resources/config/cql:/cql:ro diff --git a/test/templates/compose/05-cassandra/src/main/docker/cassandra-migration.yml b/test/templates/compose/05-cassandra/src/main/docker/cassandra-migration.yml new file mode 100644 index 000000000..ce4774f6a --- /dev/null +++ b/test/templates/compose/05-cassandra/src/main/docker/cassandra-migration.yml @@ -0,0 +1,12 @@ +version: '2' +services: + mscassandra-cassandra-migration: + environment: + - CASSANDRA_CONTACT_POINT=mscassandra-cassandra + - USER=docker-cassandra-migration + # - DEBUG_LOG=1 # uncomment to show debug logs during the migration process + build: + context: . + dockerfile: cassandra/Cassandra-Migration.Dockerfile + volumes: + - ../resources/config/cql:/cql:ro diff --git a/test/templates/compose/05-cassandra/src/main/docker/cassandra.yml b/test/templates/compose/05-cassandra/src/main/docker/cassandra.yml new file mode 100644 index 000000000..1259eea2b --- /dev/null +++ b/test/templates/compose/05-cassandra/src/main/docker/cassandra.yml @@ -0,0 +1,21 @@ +version: '2' +services: + mscassandra-cassandra: + image: cassandra:2.2.5 + # volumes: + # - ~/volumes/jhipster/mscassandra/cassandra/:/var/lib/cassandra/data + ports: + - 7000:7000 + - 7001:7001 + - 7199:7199 + - 9042:9042 + - 9160:9160 + mscassandra-cassandra-migration: + environment: + - CASSANDRA_CONTACT_POINT=mscassandra-cassandra + - CREATE_KEYSPACE_SCRIPT=create-keyspace.cql + build: + context: . + dockerfile: cassandra/Cassandra.Dockerfile + volumes: + - ../resources/config/cql:/cql:ro diff --git a/test/templates/compose/05-cassandra/target/jib-cache/.gitkeep b/test/templates/compose/05-cassandra/target/jib-cache/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/templates/compose/07-mariadb/.yo-rc.json b/test/templates/compose/07-mariadb/.yo-rc.json new file mode 100644 index 000000000..65e60fe63 --- /dev/null +++ b/test/templates/compose/07-mariadb/.yo-rc.json @@ -0,0 +1,30 @@ +{ + "generator-jhipster": { + "jhipsterVersion": "3.0.0", + "baseName": "msmariadb", + "packageName": "com.mycompany.myapp", + "packageFolder": "com/mycompany/myapp", + "serverPort": "8081", + "authenticationType": "jwt", + "cacheProvider": "hazelcast", + "enableHibernateCache": true, + "databaseType": "sql", + "devDatabaseType": "h2Disk", + "prodDatabaseType": "mariadb", + "searchEngine": "no", + "buildTool": "maven", + "jwtSecretKey": "fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8", + "enableTranslation": true, + "applicationType": "microservice", + "testFrameworks": [ + "gatling" + ], + "jhiPrefix": "jhi", + "skipClient": true, + "skipUserManagement": true, + "nativeLanguage": "en", + "languages": [ + "en" + ] + } +} diff --git a/test/templates/compose/07-mariadb/src/main/docker/app.yml b/test/templates/compose/07-mariadb/src/main/docker/app.yml new file mode 100644 index 000000000..f750c3ec6 --- /dev/null +++ b/test/templates/compose/07-mariadb/src/main/docker/app.yml @@ -0,0 +1,40 @@ +version: '2' +services: + msmariadb-app: + image: msmariadb + environment: + - SPRING_PROFILES_ACTIVE=prod + - SPRING_CLOUD_CONFIG_URI=http://admin:admin@jhipster-registry:8761/config + - SPRING_DATASOURCE_URL=jdbc:mariadb://msmariadb-mariadb:3306/msmariadb + msmariadb-mariadb: + image: <%= DOCKER_MARIADB %> + # volumes: + # - ~/volumes/jhipster/msmysql/mysql/:/var/lib/mysql/ + environment: + - MYSQL_USER=root + - MYSQL_ALLOW_EMPTY_PASSWORD=yes + - MYSQL_DATABASE=msmysql + ports: + - 3306:3306 + command: mysqld --lower_case_table_names=1 --skip-ssl --character_set_server=utf8mb4 --explicit_defaults_for_timestamp + jhipster-registry: + image: <%= DOCKER_JHIPSTER_REGISTRY %> + volumes: + - ./central-server-config:/central-config + # By default the JHipster Registry runs with the "dev" and "native" + # Spring profiles. + # "native" profile means the filesystem is used to store data, see + # http://cloud.spring.io/spring-cloud-config/spring-cloud-config.html + environment: + - _JAVA_OPTIONS=-Xmx512m -Xms256m + - SPRING_PROFILES_ACTIVE=dev<% if (authenticationType === 'oauth2') { %>,oauth2<% } %> + - SPRING_SECURITY_USER_PASSWORD=<%= adminPassword %> + - JHIPSTER_REGISTRY_PASSWORD=<%= adminPassword %> + - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_TYPE=native + - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_SEARCH_LOCATIONS=file:./central-config + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_TYPE=git + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_URI=https://github.com/jhipster/jhipster-registry/ + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_SEARCH_PATHS=central-config + ports: + - 8761:8761 + diff --git a/test/templates/compose/07-mariadb/src/main/docker/mariadb.yml b/test/templates/compose/07-mariadb/src/main/docker/mariadb.yml new file mode 100644 index 000000000..22fae3c0d --- /dev/null +++ b/test/templates/compose/07-mariadb/src/main/docker/mariadb.yml @@ -0,0 +1,13 @@ +version: '2' +services: + msmariadb-mariadb: + image: mariadb:10.3.7 + # volumes: + # - ~/volumes/jhipster/msmysql/mysql/:/var/lib/mysql/ + environment: + - MYSQL_USER=root + - MYSQL_ALLOW_EMPTY_PASSWORD=yes + - MYSQL_DATABASE=msmysql + ports: + - 3306:3306 + command: mysqld --lower_case_table_names=1 --skip-ssl --character_set_server=utf8mb4 --explicit_defaults_for_timestamp diff --git a/test/templates/compose/07-mariadb/target/jib-cache/.gitkeep b/test/templates/compose/07-mariadb/target/jib-cache/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/templates/compose/08-monolith/.yo-rc.json b/test/templates/compose/08-monolith/.yo-rc.json new file mode 100644 index 000000000..019e5b439 --- /dev/null +++ b/test/templates/compose/08-monolith/.yo-rc.json @@ -0,0 +1,27 @@ +{ + "generator-jhipster": { + "applicationType": "monolith", + "baseName": "sampleMysql", + "packageName": "com.mycompany.myapp", + "packageFolder": "com/mycompany/myapp", + "authenticationType": "session", + "cacheProvider": "ehcache", + "enableHibernateCache": true, + "websocket": false, + "databaseType": "sql", + "devDatabaseType": "h2Disk", + "prodDatabaseType": "mysql", + "searchEngine": "elasticsearch", + "buildTool": "maven", + "enableTranslation": true, + "rememberMeKey": "2bb60a80889aa6e6767e9ccd8714982681152aa5", + "testFrameworks": [ + "gatling" + ], + "jhipsterVersion": "3.8.0", + "serverPort": "8080", + "messageBroker": false, + "jhiPrefix": "jhi", + "languages": [] + } +} diff --git a/test/templates/compose/08-monolith/src/main/docker/app.yml b/test/templates/compose/08-monolith/src/main/docker/app.yml new file mode 100644 index 000000000..37f93b4a4 --- /dev/null +++ b/test/templates/compose/08-monolith/src/main/docker/app.yml @@ -0,0 +1,22 @@ +version: '2' +services: + samplemysql-app: + image: samplemysql + environment: + - SPRING_PROFILES_ACTIVE=prod,api-docs + - SPRING_DATASOURCE_URL=jdbc:mysql://samplemysql-mysql:3306/samplemysql?useUnicode=true&characterEncoding=utf8&useSSL=false&createDatabaseIfNotExist=true + - JHIPSTER_SLEEP=10 # gives time for the database to boot before the application + ports: + - 8080:8080 + samplemysql-mysql: + image: <%= DOCKER_MYSQL %> + # volumes: + # - ~/volumes/jhipster/sampleMysql/mysql/:/var/lib/mysql/ + environment: + - MYSQL_USER=root + - MYSQL_ALLOW_EMPTY_PASSWORD=yes + - MYSQL_DATABASE=samplemysql + ports: + - 3306:3306 + command: mysqld --lower_case_table_names=1 --skip-ssl --character_set_server=utf8mb4 --explicit_defaults_for_timestamp + diff --git a/test/templates/compose/08-monolith/src/main/docker/elasticsearch.yml b/test/templates/compose/08-monolith/src/main/docker/elasticsearch.yml new file mode 100644 index 000000000..969ec57f0 --- /dev/null +++ b/test/templates/compose/08-monolith/src/main/docker/elasticsearch.yml @@ -0,0 +1,9 @@ +version: '2' +services: + samplemysql-elasticsearch: + image: elasticsearch:2.4.6 + # volumes: + # - ~/volumes/jhipster/sampleMysql/elasticsearch/:/usr/share/elasticsearch/data/ + ports: + - 9200:9200 + - 9300:9300 diff --git a/test/templates/compose/08-monolith/src/main/docker/mysql.yml b/test/templates/compose/08-monolith/src/main/docker/mysql.yml new file mode 100644 index 000000000..9a7c7ba20 --- /dev/null +++ b/test/templates/compose/08-monolith/src/main/docker/mysql.yml @@ -0,0 +1,13 @@ +version: '2' +services: + samplemysql-mysql: + image: mysql:5.7.18 + # volumes: + # - ~/volumes/jhipster/sampleMysql/mysql/:/var/lib/mysql/ + environment: + - MYSQL_USER=root + - MYSQL_ALLOW_EMPTY_PASSWORD=yes + - MYSQL_DATABASE=samplemysql + ports: + - 3306:3306 + command: mysqld --lower_case_table_names=1 --skip-ssl --character_set_server=utf8mb4 --explicit_defaults_for_timestamp diff --git a/test/templates/compose/08-monolith/target/jib-cache/.gitkeep b/test/templates/compose/08-monolith/target/jib-cache/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/templates/compose/09-kafka/.yo-rc.json b/test/templates/compose/09-kafka/.yo-rc.json new file mode 100644 index 000000000..0da1143a6 --- /dev/null +++ b/test/templates/compose/09-kafka/.yo-rc.json @@ -0,0 +1,30 @@ +{ + "generator-jhipster": { + "jhipsterVersion": "3.10.0", + "baseName": "sampleKafka", + "packageName": "com.mycompany.myapp", + "packageFolder": "com/mycompany/myapp", + "serverPort": "8080", + "authenticationType": "session", + "cacheProvider": "ehcache", + "enableHibernateCache": true, + "websocket": false, + "databaseType": "sql", + "devDatabaseType": "h2Disk", + "prodDatabaseType": "mysql", + "searchEngine": false, + "messageBroker": "kafka", + "buildTool": "maven", + "rememberMeKey": "92b92094c42ee1d918471b00f1543c604888f041", + "applicationType": "monolith", + "testFrameworks": [ + "gatling" + ], + "jhiPrefix": "jhi", + "enableTranslation": true, + "nativeLanguage": "en", + "languages": [ + "en" + ] + } +} diff --git a/test/templates/compose/09-kafka/src/main/docker/app.yml b/test/templates/compose/09-kafka/src/main/docker/app.yml new file mode 100644 index 000000000..a9a1168b0 --- /dev/null +++ b/test/templates/compose/09-kafka/src/main/docker/app.yml @@ -0,0 +1,45 @@ +version: '2' +services: + samplekafka-app: + image: samplekafka + environment: + - SPRING_PROFILES_ACTIVE=prod,api-docs + - SPRING_DATASOURCE_URL=jdbc:mysql://samplekafka-mysql:3306/samplekafka?useUnicode=true&characterEncoding=utf8&useSSL=false&createDatabaseIfNotExist=true + - JHIPSTER_SLEEP=10 # gives time for the database to boot before the application + - KAFKA_CONSUMER_KEY_DESERIALIZER=org.apache.kafka.common.serialization.StringDeserializer + - KAFKA_CONSUMER_VALUE_DESERIALIZER=org.apache.kafka.common.serialization.StringDeserializer + - KAFKA_CONSUMER_BOOTSTRAP_SERVERS=kafka:9092 + - KAFKA_CONSUMER_GROUP_ID=<%= dasherizedBaseName %> + - KAFKA_CONSUMER_AUTO_OFFSET_RESET=earliest + - KAFKA_PRODUCER_BOOTSTRAP_SERVERS=kafka:9092 + - KAFKA_PRODUCER_KEY_DESERIALIZER=org.apache.kafka.common.serialization.StringDeserializer + - KAFKA_PRODUCER_VALUE_DESERIALIZER=org.apache.kafka.common.serialization.StringDeserializer + ports: + - 8080:8080 + samplekafka-mysql: + image: <%= DOCKER_MYSQL %> + # volumes: + # - ~/volumes/jhipster/sampleKafka/mysql/:/var/lib/mysql/ + environment: + - MYSQL_USER=root + - MYSQL_ALLOW_EMPTY_PASSWORD=yes + - MYSQL_DATABASE=samplekafka + ports: + - 3306:3306 + command: mysqld --lower_case_table_names=1 --skip-ssl --character_set_server=utf8mb4 --explicit_defaults_for_timestamp + kafka: + image: <%= DOCKER_KAFKA %> + environment: + KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092 + KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 + KAFKA_BROKER_ID: 2 + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + KAFKA_ADVERTISED_HOST_NAME: kafka + ports: + - 9092:9092 + zookeeper: + image: <%= DOCKER_ZOOKEEPER %> + environment: + ZOOKEEPER_CLIENT_PORT: 2181 + ZOOKEEPER_TICK_TIME: 2000 + ZOOKEEPER_SYNC_LIMIT: 2 diff --git a/test/templates/compose/09-kafka/src/main/docker/kafka.yml b/test/templates/compose/09-kafka/src/main/docker/kafka.yml new file mode 100644 index 000000000..a66bfe8c2 --- /dev/null +++ b/test/templates/compose/09-kafka/src/main/docker/kafka.yml @@ -0,0 +1,17 @@ +version: '2' +services: + zookeeper: + image: confluentinc/cp-zookeeper:5.2.1 + environment: + ZOOKEEPER_CLIENT_PORT: 2181 + ZOOKEEPER_TICK_TIME: 2000 + ZOOKEEPER_SYNC_LIMIT: 2 + kafka: + image: confluentinc/cp-kafka:5.2.1 + environment: + KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092 + KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 + KAFKA_BROKER_ID: 2 + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + ports: + - 9092:9092 diff --git a/test/templates/compose/09-kafka/src/main/docker/mysql.yml b/test/templates/compose/09-kafka/src/main/docker/mysql.yml new file mode 100644 index 000000000..4bd07b58f --- /dev/null +++ b/test/templates/compose/09-kafka/src/main/docker/mysql.yml @@ -0,0 +1,13 @@ +version: '2' +services: + samplekafka-mysql: + image: mysql:5.7.20 + # volumes: + # - ~/volumes/jhipster/sampleKafka/mysql/:/var/lib/mysql/ + environment: + - MYSQL_USER=root + - MYSQL_ALLOW_EMPTY_PASSWORD=yes + - MYSQL_DATABASE=samplekafka + ports: + - 3306:3306 + command: mysqld --lower_case_table_names=1 --skip-ssl --character_set_server=utf8mb4 --explicit_defaults_for_timestamp diff --git a/test/templates/compose/09-kafka/target/jib-cache/.gitkeep b/test/templates/compose/09-kafka/target/jib-cache/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/templates/compose/10-couchbase/.yo-rc.json b/test/templates/compose/10-couchbase/.yo-rc.json new file mode 100644 index 000000000..84e8ab9ad --- /dev/null +++ b/test/templates/compose/10-couchbase/.yo-rc.json @@ -0,0 +1,29 @@ +{ + "generator-jhipster": { + "jhipsterVersion": "3.0.0", + "baseName": "mscouchbase", + "packageName": "com.mycompany.myapp", + "packageFolder": "com/mycompany/myapp", + "serverPort": "8081", + "authenticationType": "jwt", + "cacheProvider": "no", + "enableHibernateCache": false, + "databaseType": "couchbase", + "devDatabaseType": "couchbase", + "prodDatabaseType": "couchbase", + "buildTool": "maven", + "jwtSecretKey": "fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8", + "enableTranslation": true, + "applicationType": "microservice", + "testFrameworks": [ + "gatling" + ], + "jhiPrefix": "jhi", + "skipClient": true, + "skipUserManagement": true, + "nativeLanguage": "en", + "languages": [ + "en" + ] + } +} diff --git a/test/templates/compose/10-couchbase/src/main/docker/app.yml b/test/templates/compose/10-couchbase/src/main/docker/app.yml new file mode 100644 index 000000000..e25aba739 --- /dev/null +++ b/test/templates/compose/10-couchbase/src/main/docker/app.yml @@ -0,0 +1,44 @@ +version: '2' +services: + mscouchbase-app: + image: mscouchbase + environment: + - SPRING_PROFILES_ACTIVE=prod + - SPRING_CLOUD_CONFIG_URI=http://admin:admin@jhipster-registry:8761/config + - SPRING_COUCHBASE_BOOTSTRAP_HOSTS=mscouchbase-couchbase + - SPRING_COUCHBASE_BUCKET_NAME=mscouchbase + mscouchbase-couchbase: + build: + context: . + dockerfile: couchbase/Couchbase.Dockerfile + ports: + - 8091:8091 + - 8092:8092 + - 8093:8093 + - 8094:80934 + - 11210:11210 + environment: + - BUCKET=mscouchbase +# volumes: +# - ~/volumes/jhipster/mscouchbase/couchbase/:/opt/couchbase/var + jhipster-registry: + image: <%= DOCKER_JHIPSTER_REGISTRY %> + volumes: + - ./central-server-config:/central-config + # By default the JHipster Registry runs with the "dev" and "native" + # Spring profiles. + # "native" profile means the filesystem is used to store data, see + # http://cloud.spring.io/spring-cloud-config/spring-cloud-config.html + environment: + - _JAVA_OPTIONS=-Xmx512m -Xms256m + - SPRING_PROFILES_ACTIVE=dev<% if (authenticationType === 'oauth2') { %>,oauth2<% } %> + - SPRING_SECURITY_USER_PASSWORD=<%= adminPassword %> + - JHIPSTER_REGISTRY_PASSWORD=<%= adminPassword %> + - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_TYPE=native + - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_SEARCH_LOCATIONS=file:./central-config + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_TYPE=git + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_URI=https://github.com/jhipster/jhipster-registry/ + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_SEARCH_PATHS=central-config + ports: + - 8761:8761 + diff --git a/test/templates/compose/10-couchbase/src/main/docker/couchbase-cluster.yml b/test/templates/compose/10-couchbase/src/main/docker/couchbase-cluster.yml new file mode 100644 index 000000000..546288fae --- /dev/null +++ b/test/templates/compose/10-couchbase/src/main/docker/couchbase-cluster.yml @@ -0,0 +1,24 @@ +version: '2' +services: + mscouchbase-couchbase: + build: + context: . + dockerfile: couchbase/Couchbase.Dockerfile + ports: + - 8091:8091 + - 8092:8092 + - 8093:8093 + - 8094:8094 + - 11210:11210 + environment: + - TYPE=MASTER + - BUCKET=mscouchbase + mscouchbase-couchbase-node: + build: + context: . + dockerfile: couchbase/Couchbase.Dockerfile + environment: + - TYPE=WORKER + - BUCKET=mscouchbase + - COUCHBASE_MASTER=mscouchbase-couchbase + - AUTO_REBALANCE=false diff --git a/test/templates/compose/10-couchbase/src/main/docker/couchbase.yml b/test/templates/compose/10-couchbase/src/main/docker/couchbase.yml new file mode 100644 index 000000000..49465bf85 --- /dev/null +++ b/test/templates/compose/10-couchbase/src/main/docker/couchbase.yml @@ -0,0 +1,16 @@ +version: '2' +services: + mscouchbase-couchbase: + build: + context: . + dockerfile: couchbase/Couchbase.Dockerfile + ports: + - 8091:8091 + - 8092:8092 + - 8093:8093 + - 8094:80934 + - 11210:11210 + environment: + - BUCKET=mscouchbase +# volumes: +# - ~/volumes/jhipster/mscouchbase/couchbase/:/opt/couchbase/var diff --git a/test/templates/compose/10-couchbase/target/jib-cache/.gitkeep b/test/templates/compose/10-couchbase/target/jib-cache/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/templates/compose/11-mssql/.yo-rc.json b/test/templates/compose/11-mssql/.yo-rc.json new file mode 100644 index 000000000..2b1e6a668 --- /dev/null +++ b/test/templates/compose/11-mssql/.yo-rc.json @@ -0,0 +1,30 @@ +{ + "generator-jhipster": { + "jhipsterVersion": "3.0.0", + "baseName": "msmssqldb", + "packageName": "com.mycompany.myapp", + "packageFolder": "com/mycompany/myapp", + "serverPort": "8081", + "authenticationType": "jwt", + "cacheProvider": "hazelcast", + "enableHibernateCache": true, + "databaseType": "sql", + "devDatabaseType": "h2Disk", + "prodDatabaseType": "mssql", + "searchEngine": "no", + "buildTool": "maven", + "jwtSecretKey": "fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8", + "enableTranslation": true, + "applicationType": "microservice", + "testFrameworks": [ + "gatling" + ], + "jhiPrefix": "jhi", + "skipClient": true, + "skipUserManagement": true, + "nativeLanguage": "en", + "languages": [ + "en" + ] + } +} diff --git a/test/templates/compose/11-mssql/src/main/docker/app.yml b/test/templates/compose/11-mssql/src/main/docker/app.yml new file mode 100644 index 000000000..1e73f0a35 --- /dev/null +++ b/test/templates/compose/11-mssql/src/main/docker/app.yml @@ -0,0 +1,46 @@ +version: '2' +services: + msmssql-app: + image: msmssql + environment: + - _JAVA_OPTIONS=-Xmx512m -Xms256m + - SPRING_PROFILES_ACTIVE=prod,api-docs + - MANAGEMENT_METRICS_EXPORT_PROMETHEUS_ENABLED=true + - EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://admin:$${jhipster.registry.password}@jhipster-registry:8761/eureka + - SPRING_CLOUD_CONFIG_URI=http://admin:$${jhipster.registry.password}@jhipster-registry:8761/config + - SPRING_DATASOURCE_URL=jdbc:sqlserver://msmssql-mssql:1433;database=msmssql + - JHIPSTER_SLEEP=30 # gives time for other services to boot before the application + msmssql-mssql: + image: <%= DOCKER_MSSQL %> + # volumes are not supported on macOS + # volumes: + # - ~/volumes/jhipster/tempdb/mssql/:/var/opt/mssql/data/ + environment: + - ACCEPT_EULA=Y + - SA_PASSWORD=yourStrong(!)Password + - MSSQL_DATABASE=msmssql + - MSSQL_PID=Express + - MSSQL_SLEEP=60 + ports: + - 1433:1433 + command: /bin/bash -c '/opt/mssql/bin/sqlservr & echo "wait $$MSSQL_SLEEP sec for DB to start "; sleep $$MSSQL_SLEEP; /opt/mssql-tools/bin/sqlcmd -U sa -P $$SA_PASSWORD -d tempdb -q "EXIT(CREATE DATABASE $$MSSQL_DATABASE)"; wait;' + jhipster-registry: + image: <%= DOCKER_JHIPSTER_REGISTRY %> + volumes: + - ./central-server-config:/central-config + # By default the JHipster Registry runs with the "dev" and "native" + # Spring profiles. + # "native" profile means the filesystem is used to store data, see + # http://cloud.spring.io/spring-cloud-config/spring-cloud-config.html + environment: + - _JAVA_OPTIONS=-Xmx512m -Xms256m + - SPRING_PROFILES_ACTIVE=dev<% if (authenticationType === 'oauth2') { %>,oauth2<% } %> + - SPRING_SECURITY_USER_PASSWORD=<%= adminPassword %> + - JHIPSTER_REGISTRY_PASSWORD=<%= adminPassword %> + - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_TYPE=native + - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_SEARCH_LOCATIONS=file:./central-config + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_TYPE=git + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_URI=https://github.com/jhipster/jhipster-registry/ + # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_SEARCH_PATHS=central-config + ports: + - 8761:8761 diff --git a/test/templates/compose/11-mssql/src/main/docker/mssql.yml b/test/templates/compose/11-mssql/src/main/docker/mssql.yml new file mode 100644 index 000000000..cb0166769 --- /dev/null +++ b/test/templates/compose/11-mssql/src/main/docker/mssql.yml @@ -0,0 +1,16 @@ +version: '2' +services: + msmssql-mssql: + image: mcr.microsoft.com/mssql/server:2017-latest-ubuntu + # volumes are not supported on macOS + # volumes: + # - ~/volumes/jhipster/tempdb/mssql/:/var/opt/mssql/data/ + environment: + - ACCEPT_EULA=Y + - SA_PASSWORD=yourStrong(!)Password + - MSSQL_DATABASE=msmssql + - MSSQL_PID=Express + - MSSQL_SLEEP=60 + ports: + - 1433:1433 + command: /bin/bash -c '/opt/mssql/bin/sqlservr & echo "wait $$MSSQL_SLEEP sec for DB to start "; sleep $$MSSQL_SLEEP; /opt/mssql-tools/bin/sqlcmd -U sa -P $$SA_PASSWORD -d tempdb -q "EXIT(CREATE DATABASE $$MSSQL_DATABASE)"; wait;' diff --git a/test/templates/compose/11-mssql/target/jib-cache/.gitkeep b/test/templates/compose/11-mssql/target/jib-cache/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/templates/compose/12-oracle/.yo-rc.json b/test/templates/compose/12-oracle/.yo-rc.json new file mode 100644 index 000000000..74f6fd9c1 --- /dev/null +++ b/test/templates/compose/12-oracle/.yo-rc.json @@ -0,0 +1,30 @@ +{ + "generator-jhipster": { + "jhipsterVersion": "3.0.0", + "baseName": "oracle-mono", + "packageName": "com.mycompany.myapp", + "packageFolder": "com/mycompany/myapp", + "serverPort": "8081", + "authenticationType": "jwt", + "cacheProvider": "hazelcast", + "enableHibernateCache": true, + "databaseType": "sql", + "devDatabaseType": "h2Disk", + "prodDatabaseType": "oracle", + "searchEngine": "no", + "buildTool": "maven", + "jwtSecretKey": "fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8", + "enableTranslation": true, + "applicationType": "monolith", + "testFrameworks": [ + "gatling" + ], + "jhiPrefix": "jhi", + "skipClient": true, + "skipUserManagement": true, + "nativeLanguage": "en", + "languages": [ + "en" + ] + } +} diff --git a/test/templates/compose/12-oracle/src/main/docker/app.yml b/test/templates/compose/12-oracle/src/main/docker/app.yml new file mode 100644 index 000000000..71b401179 --- /dev/null +++ b/test/templates/compose/12-oracle/src/main/docker/app.yml @@ -0,0 +1,12 @@ +version: '2' +services: + oracle-mono-app: + image: oracle-mono + environment: + - _JAVA_OPTIONS=-Xmx512m -Xms256m + - SPRING_PROFILES_ACTIVE=prod,api-docs + - MANAGEMENT_METRICS_EXPORT_PROMETHEUS_ENABLED=true + - SPRING_DATASOURCE_URL=jdbc:oracle:thin:@oracle-mono-oracle:1521:oracle-mono + - JHIPSTER_SLEEP=30 # gives time for other services to boot before the application + ports: + - 8080:8080 diff --git a/test/templates/compose/12-oracle/target/jib-cache/.gitkeep b/test/templates/compose/12-oracle/target/jib-cache/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/test/templates/default-elasticsearch/.yo-rc.json b/test/templates/default-elasticsearch/.yo-rc.json index a7941453a..d991855c2 100644 --- a/test/templates/default-elasticsearch/.yo-rc.json +++ b/test/templates/default-elasticsearch/.yo-rc.json @@ -1,7 +1,7 @@ { "generator-jhipster": { "applicationType": "monolith", - "baseName": "sampleMysql", + "baseName": "samplePsql", "packageName": "com.mycompany.myapp", "packageFolder": "com/mycompany/myapp", "authenticationType": "session", @@ -9,7 +9,7 @@ "websocket": "no", "databaseType": "sql", "devDatabaseType": "h2Disk", - "prodDatabaseType": "mysql", + "prodDatabaseType": "postgresql", "searchEngine": "elasticsearch", "buildTool": "maven", "enableTranslation": true, diff --git a/test/templates/default-gateway/.jhipster/Bar.json b/test/templates/default-gateway/microservice1/.jhipster/Bar.json similarity index 100% rename from test/templates/default-gateway/.jhipster/Bar.json rename to test/templates/default-gateway/microservice1/.jhipster/Bar.json diff --git a/test/templates/default-gateway/.jhipster/Baz.json b/test/templates/default-gateway/microservice1/.jhipster/Baz.json similarity index 100% rename from test/templates/default-gateway/.jhipster/Baz.json rename to test/templates/default-gateway/microservice1/.jhipster/Baz.json diff --git a/test/templates/default-gateway/.jhipster/Foo.json b/test/templates/default-gateway/microservice1/.jhipster/Foo.json similarity index 100% rename from test/templates/default-gateway/.jhipster/Foo.json rename to test/templates/default-gateway/microservice1/.jhipster/Foo.json diff --git a/test/templates/mongodb-with-relations/.yo-rc.json b/test/templates/mongodb-with-relations/.yo-rc.json index 00df83e62..3940158e6 100644 --- a/test/templates/mongodb-with-relations/.yo-rc.json +++ b/test/templates/mongodb-with-relations/.yo-rc.json @@ -1,6 +1,6 @@ { "generator-jhipster": { - "applicationType": "monolith", + "applicationType": "microservice", "baseName": "sampleMongodb", "packageName": "com.mycompany.myapp", "packageFolder": "com/mycompany/myapp", diff --git a/test/templates/psql-with-no-fake-data/.yo-rc.json b/test/templates/psql-with-no-fake-data/.yo-rc.json new file mode 100644 index 000000000..5f008ee99 --- /dev/null +++ b/test/templates/psql-with-no-fake-data/.yo-rc.json @@ -0,0 +1,27 @@ +{ + "generator-jhipster": { + "applicationType": "monolith", + "baseName": "sampleMysql", + "packageName": "com.mycompany.myapp", + "packageFolder": "com/mycompany/myapp", + "authenticationType": "session", + "cacheProvider": "ehcache", + "websocket": "no", + "databaseType": "sql", + "devDatabaseType": "h2Disk", + "prodDatabaseType": "postgresql", + "skipFakeData": true, + "searchEngine": "no", + "buildTool": "maven", + "enableTranslation": true, + "nativeLanguage": "en", + "languages": [ + "en", + "fr" + ], + "rememberMeKey": "2bb60a80889aa6e6767e9ccd8714982681152aa5", + "testFrameworks": [ + "gatling" + ] + } + } \ No newline at end of file diff --git a/test/templates/reproducible/.jhipster/Foo.json b/test/templates/reproducible/.jhipster/Foo.json index 3462e6291..41105b7d8 100644 --- a/test/templates/reproducible/.jhipster/Foo.json +++ b/test/templates/reproducible/.jhipster/Foo.json @@ -5,6 +5,10 @@ "fieldName": "name", "fieldType": "String" }, + { + "fieldName": "age", + "fieldType": "Integer" + }, { "fieldName": "numberPatternRequired", "fieldType": "String", diff --git a/test/utils/expected-files.js b/test/utils/expected-files.js index b4f2382da..cfbd90db7 100644 --- a/test/utils/expected-files.js +++ b/test/utils/expected-files.js @@ -13,112 +13,124 @@ const SERVER_TEST_SRC_DIR = `${constants.TEST_DIR}kotlin/`; const expectedFiles = { entity: { clientNg2: [ - `${CLIENT_MAIN_SRC_DIR}app/entities/foo/foo.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/foo/foo-detail.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/foo/foo-update.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/foo/foo-delete-dialog.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/foo/foo.route.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/foo/foo.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/foo/foo-update.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/foo/foo-delete-dialog.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/foo/foo-detail.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/foo/foo.service.ts`, - `${CLIENT_MAIN_SRC_DIR}app/shared/model/foo.model.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/foo/foo-delete-dialog.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/foo/foo-detail.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/foo/foo-update.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/foo/foo.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/foo/foo.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo/list/foo.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo/detail/foo-detail.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo/update/foo-update.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo/delete/foo-delete-dialog.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo/route/foo-routing.module.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo/route/foo-routing-resolve.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo/list/foo.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo/update/foo-update.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo/delete/foo-delete-dialog.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo/detail/foo-detail.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo/service/foo.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo/foo.model.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo/delete/foo-delete-dialog.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo/detail/foo-detail.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo/update/foo-update.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo/list/foo.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo/service/foo.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo/route/foo-routing-resolve.service.spec.ts`, ], clientNg2WithSuffix: [ - `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/foo-management.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/foo-management-detail.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/foo-management-update.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/foo-management-delete-dialog.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/foo-management.route.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/foo-management.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/foo-management-update.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/foo-management-delete-dialog.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/foo-management-detail.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/foo-management.service.ts`, - `${CLIENT_MAIN_SRC_DIR}app/shared/model/foo-management.model.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/foo-management/foo-management-delete-dialog.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/foo-management/foo-management-detail.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/foo-management/foo-management-update.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/foo-management/foo-management.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/foo-management/foo-management.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/list/foo-management.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/detail/foo-management-detail.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/update/foo-management-update.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/delete/foo-management-delete-dialog.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/route/foo-management-routing.module.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/route/foo-management-routing-resolve.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/list/foo-management.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/update/foo-management-update.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/delete/foo-management-delete-dialog.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/detail/foo-management-detail.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/service/foo-management.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/foo-management.model.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/delete/foo-management-delete-dialog.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/detail/foo-management-detail.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/update/foo-management-update.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/list/foo-management.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/service/foo-management.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/foo-management/route/foo-management-routing-resolve.service.spec.ts`, ], clientNg2WithRootFolder: [ - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/foo.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/foo-detail.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/foo-update.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/foo-delete-dialog.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/foo.route.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/foo.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/foo-update.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/foo-delete-dialog.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/foo-detail.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/foo.service.ts`, - `${CLIENT_MAIN_SRC_DIR}app/shared/model/test-root/foo.model.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/test-root/foo/foo-delete-dialog.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/test-root/foo/foo-detail.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/test-root/foo/foo-update.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/test-root/foo/foo.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/test-root/foo/foo.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/list/foo.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/detail/foo-detail.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/update/foo-update.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/delete/foo-delete-dialog.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/route/foo-routing.module.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/route/foo-routing-resolve.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/list/foo.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/update/foo-update.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/delete/foo-delete-dialog.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/detail/foo-detail.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/service/foo.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/foo.model.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/delete/foo-delete-dialog.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/detail/foo-detail.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/update/foo-update.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/list/foo.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/service/foo.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo/route/foo-routing-resolve.service.spec.ts`, ], clientNg2WithRootFolderAndSuffix: [ - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/foo-management.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/foo-management-detail.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/foo-management-update.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/foo-management-delete-dialog.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/foo-management.route.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/foo-management.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/foo-management-update.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/foo-management-delete-dialog.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/foo-management-detail.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/foo-management.service.ts`, - `${CLIENT_MAIN_SRC_DIR}app/shared/model/test-root/foo-management.model.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/test-root/foo-management/foo-management-delete-dialog.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/test-root/foo-management/foo-management-detail.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/test-root/foo-management/foo-management-update.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/test-root/foo-management/foo-management.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/test-root/foo-management/foo-management.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/list/foo-management.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/detail/foo-management-detail.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/update/foo-management-update.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/delete/foo-management-delete-dialog.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/route/foo-management-routing.module.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/route/foo-management-routing-resolve.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/list/foo-management.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/update/foo-management-update.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/delete/foo-management-delete-dialog.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/detail/foo-management-detail.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/service/foo-management.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/foo-management.model.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/delete/foo-management-delete-dialog.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/detail/foo-management-detail.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/update/foo-management-update.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/list/foo-management.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/service/foo-management.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/test-root/foo-management/route/foo-management-routing-resolve.service.spec.ts`, ], clientNg2GatewayMicroserviceEntity: [ - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/bar.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/bar-detail.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/bar-update.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/bar-delete-dialog.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/bar.route.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/bar.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/bar-update.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/bar-delete-dialog.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/bar-detail.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/bar.service.ts`, - `${CLIENT_MAIN_SRC_DIR}app/shared/model/sampleMicroservice/bar.model.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/sampleMicroservice/bar/bar-delete-dialog.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/sampleMicroservice/bar/bar-detail.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/sampleMicroservice/bar/bar-update.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/sampleMicroservice/bar/bar.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/sampleMicroservice/bar/bar.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/list/bar.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/detail/bar-detail.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/update/bar-update.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/delete/bar-delete-dialog.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/route/bar-routing.module.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/route/bar-routing-resolve.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/list/bar.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/update/bar-update.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/delete/bar-delete-dialog.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/detail/bar-detail.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/service/bar.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/bar.model.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/delete/bar-delete-dialog.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/detail/bar-detail.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/update/bar-update.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/list/bar.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/service/bar.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/bar/route/bar-routing-resolve.service.spec.ts`, ], clientBazGatewayMicroserviceEntity: [ - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/baz.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/baz-detail.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/baz-update.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/baz-delete-dialog.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/baz.route.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/baz.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/baz-update.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/baz-delete-dialog.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/baz-detail.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/baz.service.ts`, - `${CLIENT_MAIN_SRC_DIR}app/shared/model/sampleMicroservice/baz.model.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/sampleMicroservice/baz/baz-delete-dialog.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/sampleMicroservice/baz/baz-detail.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/sampleMicroservice/baz/baz-update.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/sampleMicroservice/baz/baz.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/entities/sampleMicroservice/baz/baz.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/list/baz.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/detail/baz-detail.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/update/baz-update.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/delete/baz-delete-dialog.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/route/baz-routing.module.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/route/baz-routing-resolve.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/list/baz.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/update/baz-update.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/delete/baz-delete-dialog.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/detail/baz-detail.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/service/baz.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/baz.model.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/delete/baz-delete-dialog.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/detail/baz-detail.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/update/baz-update.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/list/baz.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/service/baz.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/sampleMicroservice/baz/route/baz-routing-resolve.service.spec.ts`, ], server: [ '.jhipster/Foo.json', @@ -151,16 +163,7 @@ const expectedFiles = { maven: ['pom.xml', 'mvnw', 'mvnw.cmd', '.mvn/wrapper/maven-wrapper.jar', '.mvn/wrapper/maven-wrapper.properties', 'checkstyle.xml'], - common: [ - '.prettierignore', - '.prettierrc', - 'README.md', - '.gitignore', - '.gitattributes', - '.editorconfig', - '.huskyrc', - '.lintstagedrc.js', - ], + common: ['README.md', '.gitignore', '.gitattributes', '.editorconfig', '.huskyrc', '.lintstagedrc.js'], server: [ `${SERVER_MAIN_RES_DIR}banner.txt`, @@ -174,11 +177,11 @@ const expectedFiles = { `${SERVER_MAIN_RES_DIR}config/liquibase/master.xml`, `${SERVER_MAIN_RES_DIR}i18n/messages.properties`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/JhipsterApp.kt`, + // `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/GeneratedByJHipster.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/aop/logging/LoggingAspect.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/ApplicationProperties.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/AsyncConfiguration.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/CacheConfiguration.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/CloudDatabaseConfiguration.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/Constants.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/DatabaseConfiguration.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/DateTimeFormatConfiguration.kt`, @@ -187,9 +190,7 @@ const expectedFiles = { `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/LoggingAspectConfiguration.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/SecurityConfiguration.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/WebConfigurer.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/audit/AuditEventConverter.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/domain/AbstractAuditingEntity.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/domain/PersistentAuditEvent.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/security/AuthoritiesConstants.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/security/SecurityUtils.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/security/SpringSecurityAuditorAware.kt`, @@ -216,12 +217,9 @@ const expectedFiles = { `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/domain/Authority.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/domain/User.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/repository/AuthorityRepository.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/repository/CustomAuditEventRepository.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/repository/PersistenceAuditEventRepository.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/repository/UserRepository.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/security/DomainUserDetailsService.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/security/UserNotActivatedException.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/AuditEventService.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/MailService.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/UserService.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/service/dto/UserDTO.kt`, @@ -230,19 +228,15 @@ const expectedFiles = { `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/web/rest/errors/EmailAlreadyUsedException.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/web/rest/errors/InvalidPasswordException.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/web/rest/errors/LoginAlreadyUsedException.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/web/rest/AuditResource.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/web/rest/UserResource.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/web/rest/vm/KeyAndPasswordVM.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/web/rest/vm/ManagedUserVM.kt`, `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/config/NoOpMailConfiguration.kt`, - `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/web/rest/AuditResourceIT.kt`, `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/web/rest/UserResourceIT.kt`, `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/web/rest/WithUnauthenticatedMockUser.kt`, `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/service/UserServiceIT.kt`, `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/service/MailServiceIT.kt`, - `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/service/AuditEventServiceIT.kt`, `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/service/mapper/UserMapperTest.kt`, - `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/repository/CustomAuditEventRepositoryIT.kt`, ], infinispan: [`${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/CacheFactoryConfiguration.kt`], @@ -262,15 +256,10 @@ const expectedFiles = { i18nJson: [ `${CLIENT_MAIN_SRC_DIR}i18n/en/activate.json`, - `${CLIENT_MAIN_SRC_DIR}i18n/en/audits.json`, - `${CLIENT_MAIN_SRC_DIR}i18n/en/configuration.json`, `${CLIENT_MAIN_SRC_DIR}i18n/en/error.json`, `${CLIENT_MAIN_SRC_DIR}i18n/en/global.json`, - `${CLIENT_MAIN_SRC_DIR}i18n/en/health.json`, `${CLIENT_MAIN_SRC_DIR}i18n/en/login.json`, - `${CLIENT_MAIN_SRC_DIR}i18n/en/logs.json`, `${CLIENT_MAIN_SRC_DIR}i18n/en/home.json`, - `${CLIENT_MAIN_SRC_DIR}i18n/en/metrics.json`, `${CLIENT_MAIN_SRC_DIR}i18n/en/password.json`, `${CLIENT_MAIN_SRC_DIR}i18n/en/register.json`, `${CLIENT_MAIN_SRC_DIR}i18n/en/sessions.json`, @@ -278,15 +267,10 @@ const expectedFiles = { `${CLIENT_MAIN_SRC_DIR}i18n/en/reset.json`, `${CLIENT_MAIN_SRC_DIR}i18n/en/user-management.json`, `${CLIENT_MAIN_SRC_DIR}i18n/fr/activate.json`, - `${CLIENT_MAIN_SRC_DIR}i18n/fr/audits.json`, - `${CLIENT_MAIN_SRC_DIR}i18n/fr/configuration.json`, `${CLIENT_MAIN_SRC_DIR}i18n/fr/error.json`, `${CLIENT_MAIN_SRC_DIR}i18n/fr/global.json`, - `${CLIENT_MAIN_SRC_DIR}i18n/fr/health.json`, `${CLIENT_MAIN_SRC_DIR}i18n/fr/login.json`, - `${CLIENT_MAIN_SRC_DIR}i18n/fr/logs.json`, `${CLIENT_MAIN_SRC_DIR}i18n/fr/home.json`, - `${CLIENT_MAIN_SRC_DIR}i18n/fr/metrics.json`, `${CLIENT_MAIN_SRC_DIR}i18n/fr/password.json`, `${CLIENT_MAIN_SRC_DIR}i18n/fr/register.json`, `${CLIENT_MAIN_SRC_DIR}i18n/fr/sessions.json`, @@ -295,17 +279,23 @@ const expectedFiles = { `${CLIENT_MAIN_SRC_DIR}i18n/fr/user-management.json`, ], + i18nAdminJson: [ + `${CLIENT_MAIN_SRC_DIR}i18n/en/configuration.json`, + `${CLIENT_MAIN_SRC_DIR}i18n/en/health.json`, + `${CLIENT_MAIN_SRC_DIR}i18n/en/logs.json`, + `${CLIENT_MAIN_SRC_DIR}i18n/en/metrics.json`, + `${CLIENT_MAIN_SRC_DIR}i18n/fr/configuration.json`, + `${CLIENT_MAIN_SRC_DIR}i18n/fr/health.json`, + `${CLIENT_MAIN_SRC_DIR}i18n/fr/logs.json`, + `${CLIENT_MAIN_SRC_DIR}i18n/fr/metrics.json`, + ], + i18nDeJson: [ `${CLIENT_MAIN_SRC_DIR}i18n/de/activate.json`, - `${CLIENT_MAIN_SRC_DIR}i18n/de/audits.json`, - `${CLIENT_MAIN_SRC_DIR}i18n/de/configuration.json`, `${CLIENT_MAIN_SRC_DIR}i18n/de/error.json`, `${CLIENT_MAIN_SRC_DIR}i18n/de/global.json`, - `${CLIENT_MAIN_SRC_DIR}i18n/de/health.json`, `${CLIENT_MAIN_SRC_DIR}i18n/de/login.json`, - `${CLIENT_MAIN_SRC_DIR}i18n/de/logs.json`, `${CLIENT_MAIN_SRC_DIR}i18n/de/home.json`, - `${CLIENT_MAIN_SRC_DIR}i18n/de/metrics.json`, `${CLIENT_MAIN_SRC_DIR}i18n/de/password.json`, `${CLIENT_MAIN_SRC_DIR}i18n/de/register.json`, `${CLIENT_MAIN_SRC_DIR}i18n/de/sessions.json`, @@ -314,6 +304,13 @@ const expectedFiles = { `${CLIENT_MAIN_SRC_DIR}i18n/de/user-management.json`, ], + i18nAdminDeJson: [ + `${CLIENT_MAIN_SRC_DIR}i18n/de/configuration.json`, + `${CLIENT_MAIN_SRC_DIR}i18n/de/health.json`, + `${CLIENT_MAIN_SRC_DIR}i18n/de/logs.json`, + `${CLIENT_MAIN_SRC_DIR}i18n/de/metrics.json`, + ], + userManagementClient: [ `${CLIENT_MAIN_SRC_DIR}app/account/account.module.ts`, `${CLIENT_MAIN_SRC_DIR}app/account/account.route.ts`, @@ -329,8 +326,9 @@ const expectedFiles = { `${CLIENT_MAIN_SRC_DIR}app/account/password-reset/init/password-reset-init.component.ts`, `${CLIENT_MAIN_SRC_DIR}app/account/password-reset/init/password-reset-init.route.ts`, `${CLIENT_MAIN_SRC_DIR}app/account/password-reset/init/password-reset-init.service.ts`, - `${CLIENT_MAIN_SRC_DIR}app/account/password/password-strength-bar.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/account/password/password-strength-bar.scss`, + `${CLIENT_MAIN_SRC_DIR}app/account/password/password-strength-bar/password-strength-bar.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/account/password/password-strength-bar/password-strength-bar.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/account/password/password-strength-bar/password-strength-bar.component.scss`, `${CLIENT_MAIN_SRC_DIR}app/account/password/password.component.html`, `${CLIENT_MAIN_SRC_DIR}app/account/password/password.component.ts`, `${CLIENT_MAIN_SRC_DIR}app/account/password/password.route.ts`, @@ -339,95 +337,72 @@ const expectedFiles = { `${CLIENT_MAIN_SRC_DIR}app/account/register/register.component.ts`, `${CLIENT_MAIN_SRC_DIR}app/account/register/register.route.ts`, `${CLIENT_MAIN_SRC_DIR}app/account/register/register.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/account/register/register.model.ts`, `${CLIENT_MAIN_SRC_DIR}app/account/settings/settings.component.html`, `${CLIENT_MAIN_SRC_DIR}app/account/settings/settings.component.ts`, `${CLIENT_MAIN_SRC_DIR}app/account/settings/settings.route.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/user-management-delete-dialog.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/user-management-delete-dialog.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/user-management-detail.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/user-management-detail.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/user-management-update.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/user-management-update.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/user-management.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/user-management.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/delete/user-management-delete-dialog.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/delete/user-management-delete-dialog.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/detail/user-management-detail.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/detail/user-management-detail.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/update/user-management-update.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/update/user-management-update.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/list/user-management.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/list/user-management.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/user-management.module.ts`, `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/user-management.route.ts`, - `${CLIENT_MAIN_SRC_DIR}app/core/user/user.model.ts`, - `${CLIENT_MAIN_SRC_DIR}app/core/user/user.service.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/account/activate/activate.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/account/password-reset/finish/password-reset-finish.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/account/password-reset/init/password-reset-init.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/account/password/password-strength-bar.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/account/password/password.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/account/register/register.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/account/settings/settings.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/admin/user-management/user-management-delete-dialog.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/admin/user-management/user-management-detail.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/admin/user-management/user-management-update.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/admin/user-management/user-management.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/core/user/user.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/user-management.model.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/service/user-management.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/user/user.model.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/user/user.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/account/activate/activate.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/account/password-reset/finish/password-reset-finish.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/account/password-reset/init/password-reset-init.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/account/password/password-strength-bar/password-strength-bar.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/account/password/password.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/account/register/register.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/account/settings/settings.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/delete/user-management-delete-dialog.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/detail/user-management-detail.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/update/user-management-update.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/list/user-management.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/user-management/service/user-management.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/user/user.service.spec.ts`, ], client: [ 'angular.json', + 'ngsw-config.json', '.eslintrc.json', - '.eslintignore', - '.huskyrc', - '.lintstagedrc.js', 'package.json', - 'postcss.config.js', - 'proxy.conf.json', - `${CLIENT_MAIN_SRC_DIR}404.html`, + '.browserslistrc', + `${CLIENT_MAIN_SRC_DIR}main.ts`, + `${CLIENT_MAIN_SRC_DIR}polyfills.ts`, `${CLIENT_MAIN_SRC_DIR}app/admin/admin-routing.module.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/audits/audit-data.model.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/audits/audit.model.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/audits/audits.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/admin/audits/audits.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/audits/audits.route.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/audits/audits.module.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/audits/audits.service.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/configuration/configuration.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/admin/configuration/configuration.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/configuration/configuration.route.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/configuration/configuration.module.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/configuration/configuration.service.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/docs/docs.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/admin/docs/docs.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/docs/docs.scss`, - `${CLIENT_MAIN_SRC_DIR}app/admin/docs/docs.route.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/docs/docs.module.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/health/health-modal.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/admin/health/health-modal.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/health/health.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/admin/health/health.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/health/health.route.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/health/health.module.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/health/health.service.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/logs/log.model.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/logs/logs.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/admin/logs/logs.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/logs/logs.route.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/logs/logs.module.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/logs/logs.service.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/metrics.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/metrics.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/metrics.route.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/metrics.module.ts`, - `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/metrics.service.ts`, `${CLIENT_MAIN_SRC_DIR}app/app-routing.module.ts`, `${CLIENT_MAIN_SRC_DIR}app/app.constants.ts`, - `${CLIENT_MAIN_SRC_DIR}app/app.main.ts`, `${CLIENT_MAIN_SRC_DIR}app/app.module.ts`, - `${CLIENT_MAIN_SRC_DIR}app/blocks/config/prod.config.ts`, - `${CLIENT_MAIN_SRC_DIR}app/blocks/config/uib-pagination.config.ts`, - `${CLIENT_MAIN_SRC_DIR}app/blocks/interceptor/auth-expired.interceptor.ts`, - `${CLIENT_MAIN_SRC_DIR}app/blocks/interceptor/errorhandler.interceptor.ts`, - `${CLIENT_MAIN_SRC_DIR}app/blocks/interceptor/notification.interceptor.ts`, - `${CLIENT_MAIN_SRC_DIR}app/entities/entity.module.ts`, + `${CLIENT_MAIN_SRC_DIR}app/config/uib-pagination.config.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/interceptor/auth-expired.interceptor.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/interceptor/error-handler.interceptor.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/interceptor/notification.interceptor.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/interceptor/index.ts`, + `${CLIENT_MAIN_SRC_DIR}app/config/dayjs.ts`, + `${CLIENT_MAIN_SRC_DIR}app/entities/entity-routing.module.ts`, `${CLIENT_MAIN_SRC_DIR}app/home/home.component.html`, `${CLIENT_MAIN_SRC_DIR}app/home/home.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/home/home.scss`, + `${CLIENT_MAIN_SRC_DIR}app/home/home.component.scss`, `${CLIENT_MAIN_SRC_DIR}app/home/home.module.ts`, `${CLIENT_MAIN_SRC_DIR}app/home/home.route.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/docs/docs.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/docs/docs.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/docs/docs.component.scss`, + `${CLIENT_MAIN_SRC_DIR}app/admin/docs/docs.route.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/docs/docs.module.ts`, + `${CLIENT_MAIN_SRC_DIR}app/login/login.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/login/login.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/login/login.module.ts`, + `${CLIENT_MAIN_SRC_DIR}app/login/login.route.ts`, `${CLIENT_MAIN_SRC_DIR}app/layouts/error/error.component.html`, `${CLIENT_MAIN_SRC_DIR}app/layouts/error/error.component.ts`, `${CLIENT_MAIN_SRC_DIR}app/layouts/error/error.route.ts`, @@ -438,112 +413,176 @@ const expectedFiles = { `${CLIENT_MAIN_SRC_DIR}app/layouts/navbar/active-menu.directive.ts`, `${CLIENT_MAIN_SRC_DIR}app/layouts/navbar/navbar.component.html`, `${CLIENT_MAIN_SRC_DIR}app/layouts/navbar/navbar.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/layouts/navbar/navbar.scss`, + `${CLIENT_MAIN_SRC_DIR}app/layouts/navbar/navbar.component.scss`, `${CLIENT_MAIN_SRC_DIR}app/layouts/navbar/navbar.route.ts`, `${CLIENT_MAIN_SRC_DIR}app/layouts/profiles/page-ribbon.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/layouts/profiles/page-ribbon.scss`, + `${CLIENT_MAIN_SRC_DIR}app/layouts/profiles/page-ribbon.component.scss`, `${CLIENT_MAIN_SRC_DIR}app/layouts/profiles/profile-info.model.ts`, `${CLIENT_MAIN_SRC_DIR}app/layouts/profiles/profile.service.ts`, - `${CLIENT_MAIN_SRC_DIR}app/polyfills.ts`, + `${CLIENT_MAIN_SRC_DIR}app/shared/pagination/item-count.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/shared/sort/sort.directive.ts`, + `${CLIENT_MAIN_SRC_DIR}app/shared/sort/sort-by.directive.ts`, `${CLIENT_MAIN_SRC_DIR}app/shared/alert/alert-error.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/shared/alert/alert-error.component.html`, `${CLIENT_MAIN_SRC_DIR}app/shared/alert/alert-error.model.ts`, `${CLIENT_MAIN_SRC_DIR}app/shared/alert/alert.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/shared/alert/alert.component.html`, `${CLIENT_MAIN_SRC_DIR}app/core/auth/account.service.ts`, - `${CLIENT_MAIN_SRC_DIR}app/core/auth/csrf.service.ts`, - `${CLIENT_MAIN_SRC_DIR}app/core/icons/font-awesome-icons.ts`, + `${CLIENT_MAIN_SRC_DIR}app/config/font-awesome-icons.ts`, `${CLIENT_MAIN_SRC_DIR}app/shared/auth/has-any-authority.directive.ts`, `${CLIENT_MAIN_SRC_DIR}app/core/auth/state-storage.service.ts`, - `${CLIENT_MAIN_SRC_DIR}app/core/auth/user-route-access-service.ts`, - `${CLIENT_MAIN_SRC_DIR}app/shared/constants/authority.constants.ts`, - `${CLIENT_MAIN_SRC_DIR}app/shared/constants/error.constants.ts`, - `${CLIENT_MAIN_SRC_DIR}app/shared/constants/input.constants.ts`, - `${CLIENT_MAIN_SRC_DIR}app/shared/constants/pagination.constants.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/auth/user-route-access.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/config/application-config.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/config/application-config.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/config/authority.constants.ts`, + `${CLIENT_MAIN_SRC_DIR}app/config/error.constants.ts`, + `${CLIENT_MAIN_SRC_DIR}app/config/input.constants.ts`, + `${CLIENT_MAIN_SRC_DIR}app/config/pagination.constants.ts`, + `${CLIENT_MAIN_SRC_DIR}app/shared/date/duration.pipe.ts`, + `${CLIENT_MAIN_SRC_DIR}app/shared/date/format-medium-date.pipe.ts`, + `${CLIENT_MAIN_SRC_DIR}app/shared/date/format-medium-datetime.pipe.ts`, `${CLIENT_MAIN_SRC_DIR}app/shared/language/find-language-from-key.pipe.ts`, - `${CLIENT_MAIN_SRC_DIR}app/core/language/language.constants.ts`, - `${CLIENT_MAIN_SRC_DIR}app/core/login/login.model.ts`, - `${CLIENT_MAIN_SRC_DIR}app/core/login/login-modal.service.ts`, - `${CLIENT_MAIN_SRC_DIR}app/shared/login/login.component.html`, - `${CLIENT_MAIN_SRC_DIR}app/shared/login/login.component.ts`, - `${CLIENT_MAIN_SRC_DIR}app/core/login/login.service.ts`, - `${CLIENT_MAIN_SRC_DIR}app/shared/util/request-util.ts`, - `${CLIENT_MAIN_SRC_DIR}app/shared/util/datepicker-adapter.ts`, + `${CLIENT_MAIN_SRC_DIR}app/shared/language/translate.directive.ts`, + `${CLIENT_MAIN_SRC_DIR}app/config/language.constants.ts`, + `${CLIENT_MAIN_SRC_DIR}app/config/translation.config.ts`, + `${CLIENT_MAIN_SRC_DIR}app/login/login.model.ts`, + `${CLIENT_MAIN_SRC_DIR}app/login/login.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/request/request-util.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/request/request.model.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/util/event-manager.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/util/data-util.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/util/parse-links.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/util/alert.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/config/datepicker-adapter.ts`, `${CLIENT_MAIN_SRC_DIR}app/shared/shared-libs.module.ts`, `${CLIENT_MAIN_SRC_DIR}app/shared/shared.module.ts`, - `${CLIENT_MAIN_SRC_DIR}app/core/user/account.model.ts`, - `${CLIENT_MAIN_SRC_DIR}app/core/core.module.ts`, - `${CLIENT_MAIN_SRC_DIR}app/vendor.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/auth/account.model.ts`, `${CLIENT_MAIN_SRC_DIR}content/scss/global.scss`, - `${CLIENT_MAIN_SRC_DIR}content/css/loading.css`, `${CLIENT_MAIN_SRC_DIR}content/scss/vendor.scss`, `${CLIENT_MAIN_SRC_DIR}content/scss/_bootstrap-variables.scss`, + 'jest.conf.js', + `${CLIENT_MAIN_SRC_DIR}app/core/auth/account.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/util/operators.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/util/operators.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/util/event-manager.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/util/data-util.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/util/parse-links.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/util/alert.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/home/home.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/login/login.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/layouts/main/main.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/layouts/navbar/navbar.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/shared/pagination/item-count.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/shared/alert/alert.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/shared/alert/alert-error.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/shared/date/format-medium-date.pipe.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/shared/date/format-medium-datetime.pipe.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/shared/sort/sort.directive.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/shared/sort/sort-by.directive.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/shared/language/translate.directive.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/shared/auth/has-any-authority.directive.spec.ts`, + 'tsconfig.app.json', + 'tsconfig.spec.json', + 'tsconfig.json', + 'webpack/logo-jhipster.png', + 'webpack/proxy.conf.js', + 'webpack/webpack.custom.js', + ], + + clientCommon: [ + '.eslintignore', + `${CLIENT_MAIN_SRC_DIR}manifest.webapp`, + `${CLIENT_MAIN_SRC_DIR}404.html`, + `${CLIENT_MAIN_SRC_DIR}favicon.ico`, + `${CLIENT_MAIN_SRC_DIR}index.html`, + `${CLIENT_MAIN_SRC_DIR}robots.txt`, `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_0.svg`, - `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_1.svg`, - `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_2.svg`, - `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_3.svg`, `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_0_head-192.png`, - `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_1_head-192.png`, - `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_2_head-192.png`, - `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_3_head-192.png`, `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_0_head-256.png`, - `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_1_head-256.png`, - `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_2_head-256.png`, - `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_3_head-256.png`, `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_0_head-384.png`, - `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_1_head-384.png`, - `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_2_head-384.png`, - `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_3_head-384.png`, `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_0_head-512.png`, + `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_1.svg`, + `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_1_head-192.png`, + `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_1_head-256.png`, + `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_1_head-384.png`, `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_1_head-512.png`, + `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_2.svg`, + `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_2_head-192.png`, + `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_2_head-256.png`, + `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_2_head-384.png`, `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_2_head-512.png`, + `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_3.svg`, + `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_3_head-192.png`, + `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_3_head-256.png`, + `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_3_head-384.png`, `${CLIENT_MAIN_SRC_DIR}content/images/jhipster_family_member_3_head-512.png`, `${CLIENT_MAIN_SRC_DIR}content/images/logo-jhipster.png`, - `${CLIENT_MAIN_SRC_DIR}WEB-INF/web.xml`, - `${CLIENT_MAIN_SRC_DIR}favicon.ico`, - `${CLIENT_MAIN_SRC_DIR}index.html`, - `${CLIENT_MAIN_SRC_DIR}manifest.webapp`, - `${CLIENT_MAIN_SRC_DIR}robots.txt`, + `${CLIENT_MAIN_SRC_DIR}content/css/loading.css`, `${CLIENT_MAIN_SRC_DIR}swagger-ui/dist/images/throbber.gif`, `${CLIENT_MAIN_SRC_DIR}swagger-ui/index.html`, - `${CLIENT_TEST_SRC_DIR}jest.ts`, - `${CLIENT_TEST_SRC_DIR}jest.conf.js`, - `${CLIENT_TEST_SRC_DIR}jest-global-mocks.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/admin/audits/audits.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/admin/audits/audits.service.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/admin/configuration/configuration.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/admin/configuration/configuration.service.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/admin/health/health.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/admin/logs/logs.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/admin/logs/logs.service.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/admin/metrics/metrics.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/admin/metrics/metrics.service.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/core/user/account.service.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/core/login/login-modal.service.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/home/home.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/layouts/main/main.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/layouts/navbar/navbar.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/shared/alert/alert.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/shared/alert/alert-error.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/shared/login/login.component.spec.ts`, - `${CLIENT_TEST_SRC_DIR}spec/helpers/mock-account.service.ts`, - `${CLIENT_TEST_SRC_DIR}spec/helpers/mock-active-modal.service.ts`, - `${CLIENT_TEST_SRC_DIR}spec/helpers/mock-alert.service.ts`, - `${CLIENT_TEST_SRC_DIR}spec/helpers/mock-event-manager.service.ts`, - `${CLIENT_TEST_SRC_DIR}spec/helpers/mock-language.service.ts`, - `${CLIENT_TEST_SRC_DIR}spec/helpers/mock-login.service.ts`, - `${CLIENT_TEST_SRC_DIR}spec/helpers/mock-login-modal.service.ts`, - `${CLIENT_TEST_SRC_DIR}spec/helpers/mock-route.service.ts`, - `${CLIENT_TEST_SRC_DIR}spec/helpers/mock-state-storage.service.ts`, - `${CLIENT_TEST_SRC_DIR}spec/helpers/spyobject.ts`, - `${CLIENT_TEST_SRC_DIR}spec/test.module.ts`, - 'tsconfig.app.json', - 'tsconfig.base.json', - 'tsconfig.json', - 'tslint.json', - 'webpack/logo-jhipster.png', - 'webpack/utils.js', - 'webpack/webpack.common.js', - 'webpack/webpack.dev.js', - 'webpack/webpack.prod.js', + `${CLIENT_MAIN_SRC_DIR}WEB-INF/web.xml`, + ], + + clientAdminAngular: [ + `${CLIENT_MAIN_SRC_DIR}app/admin/configuration/configuration.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/configuration/configuration.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/configuration/configuration.route.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/configuration/configuration.module.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/configuration/configuration.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/configuration/configuration.model.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/health/modal/health-modal.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/health/modal/health-modal.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/health/health.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/health/health.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/health/health.route.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/health/health.module.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/health/health.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/health/health.model.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/logs/log.model.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/logs/logs.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/logs/logs.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/logs/logs.route.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/logs/logs.module.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/logs/logs.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/blocks/jvm-memory/jvm-memory.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/blocks/jvm-memory/jvm-memory.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/blocks/jvm-threads/jvm-threads.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/blocks/jvm-threads/jvm-threads.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/blocks/metrics-cache/metrics-cache.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/blocks/metrics-cache/metrics-cache.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/blocks/metrics-datasource/metrics-datasource.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/blocks/metrics-datasource/metrics-datasource.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/blocks/metrics-endpoints-requests/metrics-endpoints-requests.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/blocks/metrics-endpoints-requests/metrics-endpoints-requests.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/blocks/metrics-garbagecollector/metrics-garbagecollector.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/blocks/metrics-garbagecollector/metrics-garbagecollector.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/blocks/metrics-modal-threads/metrics-modal-threads.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/blocks/metrics-modal-threads/metrics-modal-threads.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/blocks/metrics-request/metrics-request.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/blocks/metrics-request/metrics-request.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/blocks/metrics-system/metrics-system.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/blocks/metrics-system/metrics-system.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/metrics.component.html`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/metrics.component.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/metrics.route.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/metrics.module.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/metrics.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/metrics.model.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/configuration/configuration.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/configuration/configuration.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/health/health.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/logs/logs.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/logs/logs.service.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/metrics.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/admin/metrics/metrics.service.spec.ts`, + ], + + clientAdminReact: [ + `${CLIENT_MAIN_SRC_DIR}app/modules/administration/configuration/configuration.tsx`, + `${CLIENT_MAIN_SRC_DIR}app/modules/administration/health/health.tsx`, + `${CLIENT_MAIN_SRC_DIR}app/modules/administration/health/health-modal.tsx`, + `${CLIENT_MAIN_SRC_DIR}app/modules/administration/metrics/metrics.tsx`, + `${CLIENT_MAIN_SRC_DIR}app/modules/administration/logs/logs.tsx`, ], i18n: [ @@ -551,8 +590,10 @@ const expectedFiles = { `${SERVER_MAIN_RES_DIR}i18n/messages_fr.properties`, `${CLIENT_MAIN_SRC_DIR}i18n/en/global.json`, `${CLIENT_MAIN_SRC_DIR}i18n/fr/global.json`, - `${CLIENT_MAIN_SRC_DIR}app/core/language/language.constants.ts`, + `${CLIENT_MAIN_SRC_DIR}app/config/language.constants.ts`, + `${CLIENT_MAIN_SRC_DIR}app/config/translation.config.ts`, `${CLIENT_MAIN_SRC_DIR}app/shared/language/find-language-from-key.pipe.ts`, + `${CLIENT_MAIN_SRC_DIR}app/shared/language/translate.directive.ts`, ], i18nRtl: [ @@ -560,7 +601,7 @@ const expectedFiles = { `${SERVER_MAIN_RES_DIR}i18n/messages_ar_LY.properties`, `${CLIENT_MAIN_SRC_DIR}i18n/en/global.json`, `${CLIENT_MAIN_SRC_DIR}i18n/ar-ly/global.json`, - `${CLIENT_MAIN_SRC_DIR}app/core/language/language.constants.ts`, + `${CLIENT_MAIN_SRC_DIR}app/config/language.constants.ts`, `${CLIENT_MAIN_SRC_DIR}content/scss/rtl.scss`, `${CLIENT_MAIN_SRC_DIR}app/shared/language/find-language-from-key.pipe.ts`, ], @@ -574,7 +615,7 @@ const expectedFiles = { `${CLIENT_MAIN_SRC_DIR}app/account/sessions/sessions.route.ts`, `${CLIENT_MAIN_SRC_DIR}app/account/sessions/sessions.service.ts`, `${CLIENT_MAIN_SRC_DIR}app/core/auth/auth-session.service.ts`, - `${CLIENT_TEST_SRC_DIR}spec/app/account/sessions/sessions.component.spec.ts`, + `${CLIENT_MAIN_SRC_DIR}app/account/sessions/sessions.component.spec.ts`, ], jwtServer: [ @@ -585,9 +626,17 @@ const expectedFiles = { `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/security/jwt/TokenProviderTest.kt`, ], + jwtServerGateway: [ + `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/security/jwt/JWTFilter.kt`, + `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/security/jwt/TokenProvider.kt`, + `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/security/jwt/JWTFilterTest.kt`, + `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/security/jwt/TokenProviderTest.kt`, + ], + jwtClient: [ - `${CLIENT_MAIN_SRC_DIR}app/blocks/interceptor/auth.interceptor.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/interceptor/auth.interceptor.ts`, `${CLIENT_MAIN_SRC_DIR}app/core/auth/auth-jwt.service.ts`, + `${CLIENT_MAIN_SRC_DIR}app/core/auth/auth-jwt.service.spec.ts`, ], oauth2: [ @@ -600,7 +649,7 @@ const expectedFiles = { `${DOCKER_DIR}keycloak.yml`, ], - oauth2Client: [`${CLIENT_MAIN_SRC_DIR}app/core/login/logout.model.ts`], + oauth2Client: [`${CLIENT_MAIN_SRC_DIR}app/login/logout.model.ts`], messageBroker: [ `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/KafkaProperties.kt`, @@ -613,25 +662,14 @@ const expectedFiles = { swaggerCodegenGradle: ['gradle/swagger.gradle'], - uaa: [ - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/UaaWebSecurityConfiguration.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/UaaConfiguration.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/UaaProperties.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/security/IatTokenEnhancer.kt`, - `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/config/OAuth2TestConfiguration.kt`, - `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/config/SecurityBeanOverrideConfiguration.kt`, - `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/security/OAuth2TokenMockUtil.kt`, - ], - gateway: [ `${SERVER_MAIN_RES_DIR}config/bootstrap.yml`, `${SERVER_MAIN_RES_DIR}config/bootstrap-prod.yml`, `${SERVER_TEST_RES_DIR}config/bootstrap.yml`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/GatewayConfiguration.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/apidoc/GatewaySwaggerResourcesProvider.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/gateway/accesscontrol/AccessControlFilter.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/gateway/responserewriting/SwaggerBasePathRewritingFilter.kt`, - `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/gateway/responserewriting/SwaggerBasePathRewritingFilterTest.kt`, + `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/apidocs/GatewaySwaggerResourcesProvider.kt`, + `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/config/apidocs/GatewaySwaggerResourcesProviderTest.kt`, + `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/web/filter/ModifyServersOpenApiFilter.kt`, + `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/web/filter/ModifyServersOpenApiFilterTest.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/web/rest/vm/RouteVM.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/web/rest/GatewayResource.kt`, `${CLIENT_MAIN_SRC_DIR}app/admin/gateway/gateway.component.ts`, @@ -641,31 +679,6 @@ const expectedFiles = { `${CLIENT_MAIN_SRC_DIR}app/admin/gateway/gateway-routes.service.ts`, ], - rateLimitingFilesForGateways: [`${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/gateway/ratelimiting/RateLimitingFilter.kt`], - - gatewayWithUaa: [ - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/CacheConfiguration.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/web/rest/AuthResource.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/web/filter/RefreshTokenFilter.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/web/filter/RefreshTokenFilterConfigurer.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/oauth2/OAuth2AuthenticationConfiguration.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/security/oauth2/CookieCollection.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/security/oauth2/CookiesHttpServletRequestWrapper.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/security/oauth2/CookieTokenExtractor.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/security/oauth2/OAuth2AuthenticationService.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/security/oauth2/OAuth2CookieHelper.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/security/oauth2/OAuth2Cookies.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/security/oauth2/OAuth2TokenEndpointClient.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/security/oauth2/OAuth2TokenEndpointClientAdapter.kt`, - `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/security/oauth2/UaaTokenEndpointClient.kt`, - `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/config/SecurityBeanOverrideConfiguration.kt`, - `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/security/OAuth2TokenMockUtil.kt`, - `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/security/oauth2/OAuth2CookieHelperTest.kt`, - `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/security/oauth2/OAuth2AuthenticationServiceTest.kt`, - `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/security/oauth2/CookieTokenExtractorTest.kt`, - `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/security/oauth2/CookieCollectionTest.kt`, - ], - feignConfig: [ `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/config/FeignConfiguration.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/client/UserFeignClientInterceptor.kt`, @@ -681,7 +694,7 @@ const expectedFiles = { microserviceGradle: ['gradle/docker.gradle'], - dockerServices: [`${DOCKER_DIR}app.yml`, `${DOCKER_DIR}sonar.yml`], + dockerServices: [`${DOCKER_DIR}app.yml`, `${DOCKER_DIR}sonar.yml`, `${DOCKER_DIR}jhipster-control-center.yml`], hibernateTimeZoneConfig: [ `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/config/timezone/HibernateTimeZoneIT.kt`, @@ -738,9 +751,7 @@ const expectedFiles = { `${SERVER_MAIN_RES_DIR}config/couchmove/changelog/V0.1__initial_setup/ROLE_ADMIN.json`, `${SERVER_MAIN_RES_DIR}config/couchmove/changelog/V0.1__initial_setup/ROLE_USER.json`, `${SERVER_MAIN_RES_DIR}config/couchmove/changelog/V0.1__initial_setup/user__admin.json`, - `${SERVER_MAIN_RES_DIR}config/couchmove/changelog/V0.1__initial_setup/user__system.json`, `${SERVER_MAIN_RES_DIR}config/couchmove/changelog/V0.1__initial_setup/user__user.json`, - `${SERVER_MAIN_RES_DIR}config/couchmove/changelog/V0.1__initial_setup/user__anonymoususer.json`, `${DOCKER_DIR}couchbase.yml`, `${DOCKER_DIR}couchbase-cluster.yml`, `${DOCKER_DIR}couchbase/Couchbase.Dockerfile`, @@ -750,9 +761,7 @@ const expectedFiles = { neo4j: [ `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/AbstractNeo4jIT.kt`, `${SERVER_MAIN_RES_DIR}config/neo4j/migrations/user__admin.json`, - `${SERVER_MAIN_RES_DIR}config/neo4j/migrations/user__system.json`, `${SERVER_MAIN_RES_DIR}config/neo4j/migrations/user__user.json`, - `${SERVER_MAIN_RES_DIR}config/neo4j/migrations/user__anonymoususer.json`, `${DOCKER_DIR}neo4j.yml`, ], @@ -777,7 +786,6 @@ const expectedFiles = { elasticsearch: [ `${DOCKER_DIR}elasticsearch.yml`, - `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/config/ElasticsearchTestConfiguration.kt`, `${SERVER_MAIN_SRC_DIR}com/mycompany/myapp/repository/search/UserSearchRepository.kt`, `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/repository/search/UserSearchRepositoryMockConfiguration.kt`, ], @@ -785,10 +793,11 @@ const expectedFiles = { cucumber: [ `${TEST_DIR}features/user/user.feature`, `${TEST_DIR}features/gitkeep`, - `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/cucumber/CucumberContextConfiguration.kt`, + `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/cucumber/CucumberTestContextConfiguration.kt`, `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/cucumber/stepdefs/UserStepDefs.kt`, `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/cucumber/stepdefs/StepDefs.kt`, `${SERVER_TEST_SRC_DIR}com/mycompany/myapp/cucumber/CucumberIT.kt`, + `${SERVER_TEST_RES_DIR}cucumber.properties`, ], eureka: [ @@ -798,6 +807,27 @@ const expectedFiles = { ], consul: [`${DOCKER_DIR}central-server-config/application.yml`, `${DOCKER_DIR}consul.yml`, `${DOCKER_DIR}config/git2consul.json`], + + cypress: [ + 'cypress.json', + `${CLIENT_TEST_SRC_DIR}cypress/plugins/index.ts`, + `${CLIENT_TEST_SRC_DIR}cypress/integration/administration/administration.spec.ts`, + `${CLIENT_TEST_SRC_DIR}cypress/support/commands.ts`, + `${CLIENT_TEST_SRC_DIR}cypress/support/navbar.ts`, + `${CLIENT_TEST_SRC_DIR}cypress/support/index.ts`, + `${CLIENT_TEST_SRC_DIR}cypress/tsconfig.json`, + ], + + cypressNoOAuth2: [`${CLIENT_TEST_SRC_DIR}cypress/integration/account/login-page.spec.ts`], + + cypressWithDatabaseAndNoOAuth2: [ + `${CLIENT_TEST_SRC_DIR}cypress/integration/account/register-page.spec.ts`, + `${CLIENT_TEST_SRC_DIR}cypress/integration/account/settings-page.spec.ts`, + `${CLIENT_TEST_SRC_DIR}cypress/integration/account/password-page.spec.ts`, + `${CLIENT_TEST_SRC_DIR}cypress/integration/account/reset-password-page.spec.ts`, + ], + + cypressWithOauth2: [`${CLIENT_TEST_SRC_DIR}cypress/support/oauth2.ts`], }; module.exports = expectedFiles; diff --git a/test/utils/utils.js b/test/utils/utils.js index bc0b2bdd2..e2d27a2f6 100644 --- a/test/utils/utils.js +++ b/test/utils/utils.js @@ -1,9 +1,10 @@ +const crypto = require('crypto'); const path = require('path'); const os = require('os'); -const shelljs = require('shelljs'); const assert = require('yeoman-assert'); const fse = require('fs-extra'); const fs = require('fs'); +const { createHelpers } = require('yeoman-test'); const Generator = require('generator-jhipster/generators/generator-base'); const constants = require('generator-jhipster/generators/generator-constants'); @@ -11,17 +12,39 @@ const constants = require('generator-jhipster/generators/generator-constants'); const DOCKER_DIR = constants.DOCKER_DIR; const FAKE_BLUEPRINT_DIR = path.join(__dirname, '../templates/fake-blueprint'); +const DEFAULT_TEST_SETTINGS = { forwardCwd: true }; +const DEFAULT_TEST_OPTIONS = { fromCli: true, skipInstall: true }; +const DEFAULT_TEST_ENV_OPTIONS = { skipInstall: true, dryRun: false }; + module.exports = { + DEFAULT_TEST_OPTIONS, + basicHelpers: createTestHelpers(), + skipPrettierHelpers: createTestHelpers({ generatorOptions: { skipPrettier: true } }), + dryRunHelpers: createTestHelpers({ generatorOptions: { skipPrettier: true }, environmentOptions: { dryRun: true } }), + createTestHelpers, getFilesForOptions, shouldBeV3DockerfileCompatible, getJHipsterCli, + prepareTempDir, testInTempDir, revertTempDir, + copyTemplateBlueprints, copyBlueprint, copyFakeBlueprint, lnYeoman, }; +function createTestHelpers(options = {}) { + const { environmentOptions = {} } = options; + const sharedOptions = { ...DEFAULT_TEST_OPTIONS, configOptions: {}, ...environmentOptions.sharedOptions }; + const newOptions = { + settings: { ...DEFAULT_TEST_SETTINGS, ...options.settings }, + environmentOptions: { ...DEFAULT_TEST_ENV_OPTIONS, ...environmentOptions, sharedOptions }, + generatorOptions: { ...DEFAULT_TEST_OPTIONS, ...options.generatorOptions }, + }; + return createHelpers(newOptions); +} + function getFilesForOptions(files, options, prefix, excludeFiles) { const generator = options; generator.debug = () => {}; @@ -52,52 +75,73 @@ function getJHipsterCli() { // corrected test for windows user cmd = cmd.replace(/\\/g, '/'); } - /* eslint-disable-next-line no-console */ - console.log(cmd); return cmd; } -function testInTempDir(cb, keepInTestDir) { +function _prepareTempEnv() { const cwd = process.cwd(); - /* eslint-disable-next-line no-console */ - console.log(`current cwd: ${cwd}`); - const tempDir = path.join(os.tmpdir(), 'jhitemp'); - shelljs.rm('-rf', tempDir); - shelljs.mkdir('-p', tempDir); + const tempDir = path.join(os.tmpdir(), crypto.randomBytes(20).toString('hex')); + process.chdir(os.tmpdir()); + if (fs.existsSync(tempDir)) { + fs.rmdirSync(tempDir, { recursive: true }); + } + fs.mkdirSync(tempDir, { recursive: true }); process.chdir(tempDir); - /* eslint-disable-next-line no-console */ - console.log(`New cwd: ${process.cwd()}`); - const cbReturn = cb(tempDir); + return { cwd, tempDir: process.cwd() }; +} + +/** + * Creates a temporary dir. + * @return {function} callback to cleanup the test dir. + */ +function prepareTempDir() { + const testEnv = _prepareTempEnv(); + return () => { + revertTempDir(testEnv.cwd, testEnv.tempDir); + }; +} + +function testInTempDir(cb) { + const preparedEnv = _prepareTempEnv(); + const cwd = preparedEnv.cwd; + const cbReturn = cb(preparedEnv.tempDir); if (cbReturn instanceof Promise) { return cbReturn.then(() => { - if (!keepInTestDir) { - revertTempDir(cwd); - } return cwd; }); } - if (!keepInTestDir) { - revertTempDir(cwd); - } return cwd; } -function revertTempDir(cwd) { - process.chdir(cwd); - /* eslint-disable-next-line no-console */ - console.log(`reverted to cwd: ${process.cwd()}`); +function revertTempDir(dest = path.join(__dirname, '..', '..'), tempDir) { + if (tempDir === undefined) { + const cwd = process.cwd(); + if (cwd.includes(os.tmpdir())) { + tempDir = cwd; + } + } + if (tempDir && dest !== tempDir) { + fs.rmdirSync(tempDir, { recursive: true }); + } + process.chdir(dest); } -function copyBlueprint(sourceDir, packagePath, ...blueprintNames) { - const nodeModulesPath = `${packagePath}/node_modules`; +function copyTemplateBlueprints(destDir, ...blueprintNames) { + blueprintNames.forEach(blueprintName => + copyBlueprint(path.join(__dirname, `../templates/blueprints/generator-jhipster-${blueprintName}`), destDir, blueprintName) + ); +} + +function copyBlueprint(sourceDir, destDir, ...blueprintNames) { + const nodeModulesPath = `${destDir}/node_modules`; fse.ensureDirSync(nodeModulesPath); blueprintNames.forEach(blueprintName => { fse.copySync(sourceDir, `${nodeModulesPath}/generator-jhipster-${blueprintName}`); }); } -function copyFakeBlueprint(packagePath, ...blueprintName) { - copyBlueprint(FAKE_BLUEPRINT_DIR, packagePath, ...blueprintName); +function copyFakeBlueprint(destDir, ...blueprintName) { + copyBlueprint(FAKE_BLUEPRINT_DIR, destDir, ...blueprintName); } function lnYeoman(packagePath) {